1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-18 17:45:08 +00:00
serenity/Kernel/Storage/Partition/EBRPartitionTable.cpp
Liav A 5ed3f7c6bf Kernel/Storage: Migrate the partition code to use the ErrorOr container
That code used the old AK::Result container, which leads to overly
complicated initialization flow when trying to figure out the correct
partition table type. Instead, when using the ErrorOr container the code
is much simpler and more understandable.
2022-04-28 22:13:54 +02:00

73 lines
2.5 KiB
C++

/*
* Copyright (c) 2020-2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/ByteBuffer.h>
#include <Kernel/Storage/Partition/EBRPartitionTable.h>
namespace Kernel {
ErrorOr<NonnullOwnPtr<EBRPartitionTable>> EBRPartitionTable::try_to_initialize(StorageDevice const& device)
{
auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) EBRPartitionTable(device)));
if (table->is_protective_mbr())
return Error::from_errno(ENOTSUP);
if (!table->is_valid())
return Error::from_errno(EINVAL);
return table;
}
void EBRPartitionTable::search_extended_partition(StorageDevice const& device, MBRPartitionTable& checked_ebr, u64 current_block_offset, size_t limit)
{
if (limit == 0)
return;
// EBRs should not carry more than 2 partitions (because they need to form a linked list)
VERIFY(checked_ebr.partitions_count() <= 2);
auto checked_logical_partition = checked_ebr.partition(0);
// If we are pointed to an invalid logical partition, something is seriously wrong.
VERIFY(checked_logical_partition.has_value());
m_partitions.append(checked_logical_partition.value().offset(current_block_offset));
if (!checked_ebr.contains_ebr())
return;
current_block_offset += checked_ebr.partition(1).value().start_block();
auto next_ebr = MBRPartitionTable::try_to_initialize(device, current_block_offset);
if (!next_ebr)
return;
search_extended_partition(device, *next_ebr, current_block_offset, (limit - 1));
}
EBRPartitionTable::EBRPartitionTable(StorageDevice const& device)
: MBRPartitionTable(device)
{
if (!is_header_valid())
return;
m_valid = true;
VERIFY(partitions_count() == 0);
auto& header = this->header();
for (size_t index = 0; index < 4; index++) {
auto& entry = header.entry[index];
// Start enumerating all logical partitions
if (entry.type == 0xf) {
auto checked_ebr = MBRPartitionTable::try_to_initialize(device, entry.offset);
if (!checked_ebr)
continue;
// It's quite unlikely to see that amount of partitions, so stop at 128 partitions.
search_extended_partition(device, *checked_ebr, entry.offset, 128);
continue;
}
if (entry.offset == 0x00) {
continue;
}
MUST(m_partitions.try_empend(entry.offset, (entry.offset + entry.length), entry.type));
}
}
EBRPartitionTable::~EBRPartitionTable() = default;
}