2020-01-18 09:38:21 +01:00
/*
2022-04-25 19:54:06 +03:00
* Copyright ( c ) 2020 - 2022 , 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
*/
2022-03-01 19:42:06 -05:00
# include <AK/Debug.h>
# include <LibPartition/MBRPartitionTable.h>
2019-06-02 22:57:44 +10:00
2022-03-01 19:42:06 -05:00
namespace Partition {
2020-02-16 01:27:42 +01:00
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
2023-05-21 20:33:09 +02:00
ErrorOr < NonnullOwnPtr < MBRPartitionTable > > MBRPartitionTable : : try_to_initialize ( PartitionableDevice device )
2022-03-20 20:35:10 -04:00
{
2023-05-21 20:33:09 +02:00
auto table = TRY ( adopt_nonnull_own_or_enomem ( new ( nothrow ) MBRPartitionTable ( move ( device ) ) ) ) ;
2020-12-26 16:53:30 +02:00
if ( table - > contains_ebr ( ) )
2022-04-25 19:54:06 +03:00
return Error : : from_errno ( ENOTSUP ) ;
2020-12-26 16:53:30 +02:00
if ( table - > is_protective_mbr ( ) )
2022-04-25 19:54:06 +03:00
return Error : : from_errno ( ENOTSUP ) ;
2020-12-26 16:53:30 +02:00
if ( ! table - > is_valid ( ) )
2022-04-25 19:54:06 +03:00
return Error : : from_errno ( EINVAL ) ;
2020-12-26 16:53:30 +02:00
return table ;
2019-06-02 22:57:44 +10:00
}
2023-05-21 20:33:09 +02:00
OwnPtr < MBRPartitionTable > MBRPartitionTable : : try_to_initialize ( PartitionableDevice device , u32 start_lba )
2022-03-20 20:35:10 -04:00
{
2023-05-21 20:33:09 +02:00
auto table = adopt_nonnull_own_or_enomem ( new ( nothrow ) MBRPartitionTable ( move ( 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
{
2023-05-21 20:33:09 +02:00
if ( block_size ( ) ! = 512 )
2020-12-26 16:53:30 +02:00
return false ;
2023-05-21 20:33:09 +02:00
auto maybe_error = m_device . read_block ( m_start_lba , m_cached_header . bytes ( ) ) ;
m_header_valid = ! maybe_error . is_error ( ) ;
2020-12-26 16:53:30 +02:00
return m_header_valid ;
2019-06-02 22:57:44 +10:00
}
2023-05-21 20:33:09 +02:00
MBRPartitionTable : : MBRPartitionTable ( PartitionableDevice device , u32 start_lba )
: PartitionTable ( move ( device ) )
2020-12-26 16:53:30 +02:00
, m_start_lba ( start_lba )
2023-05-21 20:33:09 +02:00
, m_cached_header ( ByteBuffer : : create_zeroed ( 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-06-28 19:06:05 -04:00
MUST ( m_partitions . try_empend ( entry . offset , ( entry . offset + entry . length ) - 1 , entry . type ) ) ;
2019-06-02 22:57:44 +10:00
}
2020-12-26 16:53:30 +02:00
m_valid = true ;
}
2023-05-21 20:33:09 +02:00
MBRPartitionTable : : MBRPartitionTable ( PartitionableDevice device )
: PartitionTable ( move ( device ) )
2020-12-26 16:53:30 +02:00
, m_start_lba ( 0 )
2023-05-21 20:33:09 +02:00
, m_cached_header ( ByteBuffer : : create_zeroed ( 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-06-28 19:06:05 -04:00
MUST ( m_partitions . try_empend ( entry . offset , ( entry . offset + entry . length ) - 1 , entry . type ) ) ;
2020-12-26 16:53:30 +02:00
}
m_valid = true ;
}
2022-03-16 13:15:15 -06:00
MBRPartitionTable : : ~ MBRPartitionTable ( ) = default ;
2020-12-26 16:53:30 +02:00
2022-04-01 20:58:27 +03:00
MBRPartitionTable : : Header const & MBRPartitionTable : : header ( ) const
2020-12-26 16:53:30 +02:00
{
2022-04-01 20:58:27 +03:00
return * ( MBRPartitionTable : : Header const * ) m_cached_header . data ( ) ;
2020-12-26 16:53:30 +02:00
}
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
}