22
33use super :: fail:: { fail, UnwrapOrFail } ;
44
5- pub fn get_partition ( buffer : & [ u8 ] , index : usize ) -> PartitionTableEntry {
6- if buffer. len ( ) < BUFFER_SIZE {
5+ /// Returns the first bootable partition in the partition table.
6+ pub fn boot_partition ( partitions_raw : & [ u8 ] ) -> Option < PartitionTableEntry > {
7+ for index in 0 ..4 {
8+ let entry = get_partition ( partitions_raw, index) ;
9+ if entry. bootable {
10+ return Some ( entry) ;
11+ }
12+ }
13+ None
14+ }
15+
16+ pub fn get_partition ( partitions_raw : & [ u8 ] , index : usize ) -> PartitionTableEntry {
17+ if partitions_raw. len ( ) < PARTITIONS_AREA_SIZE {
718 fail ( b'a' ) ;
8- } else if buffer. get ( BUFFER_SIZE - SUFFIX_BYTES . len ( ) ..BUFFER_SIZE ) != Some ( & SUFFIX_BYTES [ ..] ) {
9- fail ( b'b' ) ;
1019 }
1120
12- let offset = TABLE_OFFSET + index * ENTRY_SIZE ;
13- let buffer = buffer. get ( offset..) . unwrap_or_fail ( b'c' ) ;
21+ let offset = index * ENTRY_SIZE ;
22+ let buffer = partitions_raw. get ( offset..) . unwrap_or_fail ( b'c' ) ;
23+
24+ let bootable_raw = * buffer. get ( 0 ) . unwrap_or_fail ( b'd' ) ;
25+ let bootable = bootable_raw == 0x80 ;
1426
15- let partition_type = * buffer. get ( 4 ) . unwrap_or_fail ( b'd ' ) ;
27+ let partition_type = * buffer. get ( 4 ) . unwrap_or_fail ( b'e ' ) ;
1628
1729 let lba = u32:: from_le_bytes (
1830 buffer
@@ -28,64 +40,11 @@ pub fn get_partition(buffer: &[u8], index: usize) -> PartitionTableEntry {
2840 . and_then ( |s| s. try_into ( ) . ok ( ) )
2941 . unwrap_or_fail ( b'f' ) ,
3042 ) ;
31- PartitionTableEntry :: new ( partition_type, lba, len)
43+ PartitionTableEntry :: new ( bootable , partition_type, lba, len)
3244}
3345
34- /// A struct representing an MBR partition table.
35- pub struct MasterBootRecord {
36- entries : [ PartitionTableEntry ; MAX_ENTRIES ] ,
37- }
38-
39- const BUFFER_SIZE : usize = 512 ;
40- const TABLE_OFFSET : usize = 446 ;
46+ const PARTITIONS_AREA_SIZE : usize = 16 * 4 ;
4147const ENTRY_SIZE : usize = 16 ;
42- const SUFFIX_BYTES : [ u8 ; 2 ] = [ 0x55 , 0xaa ] ;
43- const MAX_ENTRIES : usize = ( BUFFER_SIZE - TABLE_OFFSET - 2 ) / ENTRY_SIZE ;
44-
45- impl MasterBootRecord {
46- /// Parses the MBR table from a raw byte buffer.
47-
48- pub fn from_bytes ( buffer : & [ u8 ] ) -> MasterBootRecord {
49- if buffer. len ( ) < BUFFER_SIZE {
50- fail ( b'1' ) ;
51- } else if buffer. get ( BUFFER_SIZE - SUFFIX_BYTES . len ( ) ..BUFFER_SIZE )
52- != Some ( & SUFFIX_BYTES [ ..] )
53- {
54- fail ( b'2' ) ;
55- }
56- let mut entries = [ PartitionTableEntry :: empty ( ) ; MAX_ENTRIES ] ;
57-
58- for idx in 0 ..MAX_ENTRIES {
59- let offset = TABLE_OFFSET + idx * ENTRY_SIZE ;
60- let buffer = buffer. get ( offset..) . unwrap_or_fail ( b'8' ) ;
61-
62- let partition_type = * buffer. get ( 4 ) . unwrap_or_fail ( b'4' ) ;
63-
64- let lba = u32:: from_le_bytes (
65- buffer
66- . get ( 8 ..)
67- . and_then ( |s| s. get ( ..4 ) )
68- . and_then ( |s| s. try_into ( ) . ok ( ) )
69- . unwrap_or_fail ( b'5' ) ,
70- ) ;
71- let len = u32:: from_le_bytes (
72- buffer
73- . get ( 12 ..)
74- . and_then ( |s| s. get ( ..4 ) )
75- . and_then ( |s| s. try_into ( ) . ok ( ) )
76- . unwrap_or_fail ( b'6' ) ,
77- ) ;
78- * entries. get_mut ( idx) . unwrap_or_fail ( b'7' ) =
79- PartitionTableEntry :: new ( partition_type, lba, len) ;
80- }
81-
82- MasterBootRecord { entries }
83- }
84-
85- pub fn partition_table_entries ( & self ) -> & [ PartitionTableEntry ] {
86- & self . entries [ ..]
87- }
88- }
8948
9049/// The type of a particular partition.
9150#[ derive( Copy , Clone , Eq , PartialEq ) ]
@@ -129,6 +88,9 @@ impl PartitionType {
12988/// An entry in a partition table.
13089#[ derive( Copy , Clone , Eq , PartialEq ) ]
13190pub struct PartitionTableEntry {
91+ /// Whether this partition is a boot partition.
92+ pub bootable : bool ,
93+
13294 /// The type of partition in this entry.
13395 pub partition_type : u8 ,
13496
@@ -141,18 +103,16 @@ pub struct PartitionTableEntry {
141103
142104impl PartitionTableEntry {
143105 pub fn new (
106+ bootable : bool ,
144107 partition_type : u8 ,
145108 logical_block_address : u32 ,
146109 sector_count : u32 ,
147110 ) -> PartitionTableEntry {
148111 PartitionTableEntry {
112+ bootable,
149113 partition_type,
150114 logical_block_address,
151115 sector_count,
152116 }
153117 }
154-
155- pub fn empty ( ) -> PartitionTableEntry {
156- PartitionTableEntry :: new ( 0 , 0 , 0 )
157- }
158118}
0 commit comments