Serenity Operating System
at master 90 lines 3.1 kB view raw
1/* 2 * Copyright (c) 2020-2022, Liav A. <liavalb@hotmail.co.il> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibPartition/EBRPartitionTable.h> 8 9#ifndef KERNEL 10# include <LibCore/DeprecatedFile.h> 11#endif 12 13namespace Partition { 14 15#ifdef KERNEL 16ErrorOr<NonnullOwnPtr<EBRPartitionTable>> EBRPartitionTable::try_to_initialize(Kernel::StorageDevice& device) 17{ 18 auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) EBRPartitionTable(device))); 19#else 20ErrorOr<NonnullOwnPtr<EBRPartitionTable>> EBRPartitionTable::try_to_initialize(NonnullRefPtr<Core::DeprecatedFile> device_file) 21{ 22 auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) EBRPartitionTable(move(device_file)))); 23#endif 24 if (table->is_protective_mbr()) 25 return Error::from_errno(ENOTSUP); 26 if (!table->is_valid()) 27 return Error::from_errno(EINVAL); 28 return table; 29} 30 31#ifdef KERNEL 32void EBRPartitionTable::search_extended_partition(Kernel::StorageDevice& device, MBRPartitionTable& checked_ebr, u64 current_block_offset, size_t limit) 33#else 34void EBRPartitionTable::search_extended_partition(NonnullRefPtr<Core::DeprecatedFile> device, MBRPartitionTable& checked_ebr, u64 current_block_offset, size_t limit) 35#endif 36{ 37 if (limit == 0) 38 return; 39 // EBRs should not carry more than 2 partitions (because they need to form a linked list) 40 VERIFY(checked_ebr.partitions_count() <= 2); 41 auto checked_logical_partition = checked_ebr.partition(0); 42 43 // If we are pointed to an invalid logical partition, something is seriously wrong. 44 VERIFY(checked_logical_partition.has_value()); 45 m_partitions.append(checked_logical_partition.value().offset(current_block_offset)); 46 if (!checked_ebr.contains_ebr()) 47 return; 48 current_block_offset += checked_ebr.partition(1).value().start_block(); 49 auto next_ebr = MBRPartitionTable::try_to_initialize(device, current_block_offset); 50 if (!next_ebr) 51 return; 52 search_extended_partition(device, *next_ebr, current_block_offset, (limit - 1)); 53} 54 55#ifdef KERNEL 56EBRPartitionTable::EBRPartitionTable(Kernel::StorageDevice& device) 57#else 58EBRPartitionTable::EBRPartitionTable(NonnullRefPtr<Core::DeprecatedFile> device) 59#endif 60 : MBRPartitionTable(device) 61{ 62 if (!is_header_valid()) 63 return; 64 m_valid = true; 65 66 VERIFY(partitions_count() == 0); 67 68 auto& header = this->header(); 69 for (size_t index = 0; index < 4; index++) { 70 auto& entry = header.entry[index]; 71 // Start enumerating all logical partitions 72 if (entry.type == 0xf) { 73 auto checked_ebr = MBRPartitionTable::try_to_initialize(device, entry.offset); 74 if (!checked_ebr) 75 continue; 76 // It's quite unlikely to see that amount of partitions, so stop at 128 partitions. 77 search_extended_partition(device, *checked_ebr, entry.offset, 128); 78 continue; 79 } 80 81 if (entry.offset == 0x00) { 82 continue; 83 } 84 MUST(m_partitions.try_empend(entry.offset, (entry.offset + entry.length) - 1, entry.type)); 85 } 86} 87 88EBRPartitionTable::~EBRPartitionTable() = default; 89 90}