2020-01-18 05:38:21 -03:00
/*
2020-12-26 11:53:30 -03:00
* Copyright ( c ) 2020 , Liav A . < liavalb @ hotmail . co . il >
2020-01-18 05:38:21 -03:00
*
2021-04-22 05:24:48 -03:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 05:38:21 -03:00
*/
2019-06-02 09:57:44 -03:00
# include <AK/ByteBuffer.h>
2021-01-25 12:07:10 -03:00
# include <Kernel/Debug.h>
2020-12-25 15:23:35 -03:00
# include <Kernel/Storage/Partition/MBRPartitionTable.h>
2019-06-02 09:57:44 -03:00
2020-02-15 21:27:42 -03:00
namespace Kernel {
2020-12-26 11:53:30 -03:00
# define MBR_SIGNATURE 0xaa55
# define MBR_PROTECTIVE 0xEE
# define EBR_CHS_CONTAINER 0x05
# define EBR_LBA_CONTAINER 0x0F
Result < NonnullOwnPtr < MBRPartitionTable > , PartitionTable : : Error > MBRPartitionTable : : try_to_initialize ( const StorageDevice & device )
2019-06-02 09:57:44 -03:00
{
2020-12-26 11:53:30 -03:00
auto table = make < MBRPartitionTable > ( device ) ;
if ( table - > contains_ebr ( ) )
2022-01-06 11:07:15 -03:00
return { PartitionTable : : Error : : ContainsEBR } ;
2020-12-26 11:53:30 -03:00
if ( table - > is_protective_mbr ( ) )
return { PartitionTable : : Error : : MBRProtective } ;
if ( ! table - > is_valid ( ) )
return { PartitionTable : : Error : : Invalid } ;
return table ;
2019-06-02 09:57:44 -03:00
}
2020-12-26 11:53:30 -03:00
OwnPtr < MBRPartitionTable > MBRPartitionTable : : try_to_initialize ( const StorageDevice & device , u32 start_lba )
2019-06-02 09:57:44 -03:00
{
2020-12-26 11:53:30 -03:00
auto table = make < MBRPartitionTable > ( device , start_lba ) ;
if ( ! table - > is_valid ( ) )
2021-01-10 20:29:28 -03:00
return { } ;
2020-12-26 11:53:30 -03:00
return table ;
2019-06-02 09:57:44 -03:00
}
2020-12-26 11:53:30 -03:00
bool MBRPartitionTable : : read_boot_record ( )
2019-06-02 09:57:44 -03:00
{
2020-12-26 11:53:30 -03:00
auto buffer = UserOrKernelBuffer : : for_kernel_buffer ( m_cached_header . data ( ) ) ;
if ( ! m_device - > read_block ( m_start_lba , buffer ) )
return false ;
m_header_valid = true ;
return m_header_valid ;
2019-06-02 09:57:44 -03:00
}
2020-12-26 11:53:30 -03:00
MBRPartitionTable : : MBRPartitionTable ( const StorageDevice & device , u32 start_lba )
: PartitionTable ( device )
, m_start_lba ( start_lba )
2022-01-20 14:47:39 -03:00
, m_cached_header ( ByteBuffer : : create_zeroed ( m_device - > block_size ( ) ) . release_value_but_fixme_should_propagate_errors ( ) ) // FIXME: Do something sensible if this fails because of OOM.
2019-06-02 09:57:44 -03:00
{
2020-12-26 11:53:30 -03:00
if ( ! read_boot_record ( ) | | ! initialize ( ) )
return ;
m_header_valid = true ;
auto & header = this - > header ( ) ;
for ( size_t index = 0 ; index < 4 ; index + + ) {
auto & entry = header . entry [ index ] ;
if ( entry . offset = = 0x00 ) {
continue ;
}
2022-01-03 08:25:29 -03:00
MUST ( m_partitions . try_empend ( entry . offset , ( entry . offset + entry . length ) , entry . type ) ) ;
2019-06-02 09:57:44 -03:00
}
2020-12-26 11:53:30 -03:00
m_valid = true ;
}
MBRPartitionTable : : MBRPartitionTable ( const StorageDevice & device )
: PartitionTable ( device )
, m_start_lba ( 0 )
2022-01-20 14:47:39 -03:00
, m_cached_header ( ByteBuffer : : create_zeroed ( m_device - > block_size ( ) ) . release_value_but_fixme_should_propagate_errors ( ) ) // FIXME: Do something sensible if this fails because of OOM.
2020-12-26 11:53:30 -03:00
{
if ( ! read_boot_record ( ) | | contains_ebr ( ) | | is_protective_mbr ( ) | | ! initialize ( ) )
return ;
2019-06-02 09:57:44 -03:00
auto & header = this - > header ( ) ;
2020-12-26 11:53:30 -03:00
for ( size_t index = 0 ; index < 4 ; index + + ) {
auto & entry = header . entry [ index ] ;
if ( entry . offset = = 0x00 ) {
continue ;
}
2022-01-03 08:25:29 -03:00
MUST ( m_partitions . try_empend ( entry . offset , ( entry . offset + entry . length ) , entry . type ) ) ;
2020-12-26 11:53:30 -03:00
}
m_valid = true ;
}
MBRPartitionTable : : ~ MBRPartitionTable ( )
{
}
const MBRPartitionTable : : Header & MBRPartitionTable : : header ( ) const
{
return * ( const MBRPartitionTable : : Header * ) m_cached_header . data ( ) ;
}
2019-06-02 09:57:44 -03:00
2020-12-26 11:53:30 -03:00
bool MBRPartitionTable : : initialize ( )
{
auto & header = this - > header ( ) ;
2021-03-12 10:02:17 -03:00
dbgln_if ( MBR_DEBUG , " Master Boot Record: mbr_signature={:#08x} " , header . mbr_signature ) ;
2019-06-02 09:57:44 -03:00
if ( header . mbr_signature ! = MBR_SIGNATURE ) {
2021-03-12 10:02:17 -03:00
dbgln ( " Master Boot Record: invalid signature " ) ;
2019-06-02 09:57:44 -03:00
return false ;
}
return true ;
}
2020-02-01 18:28:39 -03:00
bool MBRPartitionTable : : contains_ebr ( ) const
{
for ( int i = 0 ; i < 4 ; i + + ) {
if ( header ( ) . entry [ i ] . type = = EBR_CHS_CONTAINER | | header ( ) . entry [ i ] . type = = EBR_LBA_CONTAINER )
return true ;
}
return false ;
}
2019-10-06 21:12:37 -03:00
bool MBRPartitionTable : : is_protective_mbr ( ) const
{
return header ( ) . entry [ 0 ] . type = = MBR_PROTECTIVE ;
}
2020-02-15 21:27:42 -03:00
}