2020-01-18 09:38:21 +01:00
/*
2020-12-26 16:53:30 +02:00
* Copyright ( c ) 2020 , Liav A . < liavalb @ hotmail . co . il >
2020-01-18 09:38:21 +01:00
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 09:38:21 +01:00
*/
2019-06-02 22:57:44 +10:00
# include <AK/ByteBuffer.h>
2021-01-25 16:07:10 +01:00
# include <Kernel/Debug.h>
2020-12-25 20:23:35 +02:00
# include <Kernel/Storage/Partition/MBRPartitionTable.h>
2019-06-02 22:57:44 +10:00
2020-02-16 01:27:42 +01:00
namespace Kernel {
2020-12-26 16:53:30 +02: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 22:57:44 +10:00
{
2022-02-03 16:33:46 +02:00
auto table = adopt_nonnull_own_or_enomem ( new ( nothrow ) MBRPartitionTable ( device ) ) . release_value_but_fixme_should_propagate_errors ( ) ;
2020-12-26 16:53:30 +02:00
if ( table - > contains_ebr ( ) )
2022-01-06 07:07:15 -07:00
return { PartitionTable : : Error : : ContainsEBR } ;
2020-12-26 16:53:30 +02:00
if ( table - > is_protective_mbr ( ) )
return { PartitionTable : : Error : : MBRProtective } ;
if ( ! table - > is_valid ( ) )
return { PartitionTable : : Error : : Invalid } ;
return table ;
2019-06-02 22:57:44 +10:00
}
2020-12-26 16:53:30 +02:00
OwnPtr < MBRPartitionTable > MBRPartitionTable : : try_to_initialize ( const StorageDevice & device , u32 start_lba )
2019-06-02 22:57:44 +10:00
{
2022-02-03 16:33:46 +02:00
auto table = adopt_nonnull_own_or_enomem ( new ( nothrow ) MBRPartitionTable ( device , start_lba ) ) . release_value_but_fixme_should_propagate_errors ( ) ;
2020-12-26 16:53:30 +02:00
if ( ! table - > is_valid ( ) )
2021-01-10 16:29:28 -07:00
return { } ;
2020-12-26 16:53:30 +02:00
return table ;
2019-06-02 22:57:44 +10:00
}
2020-12-26 16:53:30 +02:00
bool MBRPartitionTable : : read_boot_record ( )
2019-06-02 22:57:44 +10:00
{
2020-12-26 16:53:30 +02: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 22:57:44 +10:00
}
2020-12-26 16:53:30 +02:00
MBRPartitionTable : : MBRPartitionTable ( const StorageDevice & device , u32 start_lba )
: PartitionTable ( device )
, m_start_lba ( start_lba )
2022-01-20 17:47:39 +00: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 22:57:44 +10:00
{
2020-12-26 16:53:30 +02: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 03:25:29 -08:00
MUST ( m_partitions . try_empend ( entry . offset , ( entry . offset + entry . length ) , entry . type ) ) ;
2019-06-02 22:57:44 +10:00
}
2020-12-26 16:53:30 +02:00
m_valid = true ;
}
MBRPartitionTable : : MBRPartitionTable ( const StorageDevice & device )
: PartitionTable ( device )
, m_start_lba ( 0 )
2022-01-20 17:47:39 +00: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 16:53:30 +02:00
{
if ( ! read_boot_record ( ) | | contains_ebr ( ) | | is_protective_mbr ( ) | | ! initialize ( ) )
return ;
2019-06-02 22:57:44 +10:00
auto & header = this - > header ( ) ;
2020-12-26 16:53:30 +02:00
for ( size_t index = 0 ; index < 4 ; index + + ) {
auto & entry = header . entry [ index ] ;
if ( entry . offset = = 0x00 ) {
continue ;
}
2022-01-03 03:25:29 -08:00
MUST ( m_partitions . try_empend ( entry . offset , ( entry . offset + entry . length ) , entry . type ) ) ;
2020-12-26 16:53:30 +02:00
}
m_valid = true ;
}
MBRPartitionTable : : ~ MBRPartitionTable ( )
{
}
const MBRPartitionTable : : Header & MBRPartitionTable : : header ( ) const
{
return * ( const MBRPartitionTable : : Header * ) m_cached_header . data ( ) ;
}
2019-06-02 22:57:44 +10:00
2020-12-26 16:53:30 +02:00
bool MBRPartitionTable : : initialize ( )
{
auto & header = this - > header ( ) ;
2021-03-12 14:02:17 +01:00
dbgln_if ( MBR_DEBUG , " Master Boot Record: mbr_signature={:#08x} " , header . mbr_signature ) ;
2019-06-02 22:57:44 +10:00
if ( header . mbr_signature ! = MBR_SIGNATURE ) {
2021-03-12 14:02:17 +01:00
dbgln ( " Master Boot Record: invalid signature " ) ;
2019-06-02 22:57:44 +10:00
return false ;
}
return true ;
}
2020-02-01 23:28:39 +02: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-07 03:12:37 +03:00
bool MBRPartitionTable : : is_protective_mbr ( ) const
{
return header ( ) . entry [ 0 ] . type = = MBR_PROTECTIVE ;
}
2020-02-16 01:27:42 +01:00
}