1use alloc::vec::Vec;
50use core::fmt;
51
52use crate::{DirectBlockDevice, PartitionDevice, Size};
53
54mod error;
55mod partition;
56mod utilities;
57pub use error::*;
58pub use partition::*;
59pub use utilities::*;
60
61#[cfg(test)]
62use crate::MemoryDevice;
63
64#[derive(Debug, Clone)]
66pub struct Mbr {
67 pub bootstrap_code: [u8; 440],
69 pub disk_signature: [u8; 4],
71 pub reserved: [u8; 2],
73 pub partitions: [PartitionEntry; 4],
75 pub boot_signature: [u8; 2],
77}
78
79impl Mbr {
80 pub const SIGNATURE: [u8; 2] = [0x55, 0xAA];
82
83 pub const SIZE: usize = 512;
85
86 pub const MAXIMUM_PARTITIONS_COUNT: usize = 4;
88
89 pub const MINIMUM_START_BLOCK: Size = 2048;
90
91 pub fn new() -> Self {
93 Self {
94 bootstrap_code: [0; 440],
95 disk_signature: [0; 4],
96 reserved: [0; 2],
97 partitions: [PartitionEntry::new_empty(); 4],
98 boot_signature: Self::SIGNATURE,
99 }
100 }
101
102 pub fn new_with_signature(disk_signature: u32) -> Self {
104 let mut mbr = Self::new();
105 mbr.set_disk_signature(disk_signature);
106 mbr
107 }
108
109 pub fn from_bytes(data: &[u8]) -> Result<Self> {
111 if data.len() < Self::SIZE {
112 return Err(Error::BufferTooSmall);
113 }
114
115 if data[510] != Self::SIGNATURE[0] || data[511] != Self::SIGNATURE[1] {
117 return Err(Error::InvalidSignature);
118 }
119
120 let mut mbr = Mbr {
121 bootstrap_code: [0; 440],
122 disk_signature: [0; 4],
123 reserved: [0; 2],
124 partitions: [PartitionEntry::new_empty(); 4],
125 boot_signature: [0; 2],
126 };
127
128 mbr.bootstrap_code.copy_from_slice(&data[0..440]);
130
131 mbr.disk_signature.copy_from_slice(&data[440..444]);
133
134 mbr.reserved.copy_from_slice(&data[444..446]);
136
137 for (i, partition) in mbr.partitions.iter_mut().enumerate() {
139 let offset = 446 + (i * 16);
140 let partition_data = &data[offset..offset + 16];
141
142 *partition = PartitionEntry::parse(partition_data).unwrap();
143 }
144
145 mbr.boot_signature.copy_from_slice(&data[510..512]);
147
148 Ok(mbr)
149 }
150
151 pub fn read_from_device(device: &impl DirectBlockDevice) -> Result<Self> {
153 device.open()?;
156
157 let mut buffer = [0u8; Self::SIZE];
158 device.set_position(0, &crate::Position::Start(0))?;
159 let bytes_read = device.read(&mut buffer, 0)?;
160
161 if bytes_read < Self::SIZE {
162 return Err(Error::ReadFailed);
163 }
164
165 device.close()?;
166
167 Self::from_bytes(&buffer)
168 }
169
170 pub fn write_to_device(&self, device: &impl DirectBlockDevice) -> Result<()> {
172 device.open()?;
175
176 device.set_position(0, &crate::Position::Start(0))?;
177
178 let buffer = self.to_bytes();
180 let bytes_written = device.write(&buffer, 0)?;
181
182 if bytes_written < Self::SIZE {
183 return Err(Error::WriteFailed);
184 }
185
186 device.close()?;
187
188 Ok(())
189 }
190
191 pub fn is_valid(&self) -> bool {
193 self.boot_signature == Self::SIGNATURE
194 }
195
196 pub fn get_valid_partitions(&self) -> Vec<&PartitionEntry> {
198 self.partitions
199 .iter()
200 .filter(|partition| partition.is_valid())
201 .collect()
202 }
203
204 pub fn get_valid_partitions_mut(&mut self) -> Vec<&mut PartitionEntry> {
206 self.partitions
207 .iter_mut()
208 .filter(|partition| partition.is_valid())
209 .collect()
210 }
211
212 pub fn get_bootable_partition(&self) -> Option<&PartitionEntry> {
214 self.partitions.iter().find(|partition| partition.bootable)
215 }
216
217 pub fn get_bootable_partition_mut(&mut self) -> Option<&mut PartitionEntry> {
219 self.partitions
220 .iter_mut()
221 .find(|partition| partition.bootable)
222 }
223
224 pub fn set_bootable_partition(&mut self, index: usize) -> Result<()> {
226 if index >= Self::MAXIMUM_PARTITIONS_COUNT {
227 return Err(Error::InvalidIndex);
228 }
229
230 for partition in &mut self.partitions {
232 partition.bootable = false;
233 }
234
235 self.partitions[index].bootable = true;
237 Ok(())
238 }
239
240 pub fn has_gpt_protective_partition(&self) -> bool {
242 self.partitions
243 .iter()
244 .any(|partition| partition.kind == PartitionKind::GptProtective)
245 }
246
247 pub fn get_disk_signature(&self) -> u32 {
249 u32::from_le_bytes(self.disk_signature)
250 }
251
252 pub fn set_disk_signature(&mut self, signature: u32) {
254 self.disk_signature = signature.to_le_bytes();
255 }
256
257 pub fn get_free_partition_slot(&self) -> Option<usize> {
259 self.partitions
260 .iter()
261 .position(|partition| !partition.is_valid())
262 }
263
264 pub fn add_partition(
266 &mut self,
267 partition_type: PartitionKind,
268 start_lba: u32,
269 size_sectors: u32,
270 bootable: bool,
271 ) -> Result<usize> {
272 let slot = self.get_free_partition_slot().ok_or(Error::Full)?;
273
274 let new_partition =
275 PartitionEntry::new_with_params(bootable, partition_type, start_lba, size_sectors);
276
277 for existing in &self.partitions {
279 if existing.is_valid() && new_partition.overlaps_with(existing) {
280 return Err(Error::OverlappingPartitions);
281 }
282 }
283
284 self.partitions[slot] = new_partition;
285
286 if bootable {
288 self.set_bootable_partition(slot)?;
289 }
290
291 Ok(slot)
292 }
293
294 pub fn remove_partition(&mut self, index: usize) -> Result<()> {
296 if index >= Self::MAXIMUM_PARTITIONS_COUNT {
297 return Err(Error::InvalidIndex);
298 }
299
300 self.partitions[index].clear();
301 Ok(())
302 }
303
304 pub fn has_overlapping_partitions(&self) -> bool {
306 let valid_partitions = self.get_valid_partitions();
307
308 for (i, partition1) in valid_partitions.iter().enumerate() {
309 for partition2 in valid_partitions.iter().skip(i + 1) {
310 if partition1.overlaps_with(partition2) {
311 return true;
312 }
313 }
314 }
315
316 false
317 }
318
319 pub fn get_partition_count(&self) -> usize {
321 self.partitions.iter().filter(|p| p.is_valid()).count()
322 }
323
324 pub fn create_all_partition_devices<'a, D: DirectBlockDevice>(
362 &self,
363 base_device: &'a D,
364 ) -> Result<Vec<PartitionDevice<'a, D>>> {
365 let mut devices = Vec::new();
366
367 for partition in &self.partitions {
368 if partition.is_valid() {
369 let device = create_partition_device(base_device, partition)?;
370 devices.push(device);
371 }
372 }
373
374 Ok(devices)
375 }
376
377 pub fn find_partitions_by_type(&self, kind: PartitionKind) -> Vec<(usize, &PartitionEntry)> {
411 self.partitions
412 .iter()
413 .enumerate()
414 .filter(|(_, partition)| partition.is_valid() && partition.kind == kind)
415 .collect()
416 }
417
418 pub fn validate(&self) -> Result<()> {
450 if !self.is_valid() {
452 return Err(Error::InvalidSignature);
453 }
454
455 if self.has_overlapping_partitions() {
457 return Err(Error::OverlappingPartitions);
458 }
459
460 let bootable_count = self.partitions.iter().filter(|p| p.bootable).count();
462
463 if bootable_count > 1 {
464 return Err(Error::MultipleBootablePartitions);
465 }
466
467 Ok(())
468 }
469
470 pub fn get_statistics(&self) -> PartitionStatistics {
501 let valid_partitions: Vec<_> = self.get_valid_partitions();
502
503 let total_partitions = valid_partitions.len();
504 let bootable_partitions = valid_partitions.iter().filter(|p| p.bootable).count();
505
506 let fat_partitions = valid_partitions.iter().filter(|p| p.kind.is_fat()).count();
507
508 let linux_partitions = valid_partitions
509 .iter()
510 .filter(|p| p.kind.is_linux())
511 .count();
512
513 let hidden_partitions = valid_partitions
514 .iter()
515 .filter(|p| p.kind.is_hidden())
516 .count();
517
518 let extended_partitions = valid_partitions
519 .iter()
520 .filter(|p| p.kind.is_extended())
521 .count();
522
523 let unknown_partitions = valid_partitions
524 .iter()
525 .filter(|p| matches!(p.kind, PartitionKind::Unknown(_)))
526 .count();
527
528 let total_used_sectors = valid_partitions.iter().map(|p| p.block_count as Size).sum();
529
530 let largest_partition_sectors = valid_partitions
531 .iter()
532 .map(|p| p.block_count)
533 .max()
534 .unwrap_or(0);
535
536 let smallest_partition_sectors = valid_partitions
537 .iter()
538 .map(|p| p.block_count)
539 .min()
540 .unwrap_or(0);
541
542 PartitionStatistics {
543 total_partitions,
544 bootable_partitions,
545 fat_partitions,
546 linux_partitions,
547 hidden_partitions,
548 extended_partitions,
549 unknown_partitions,
550 total_used_sectors,
551 largest_partition_sectors,
552 smallest_partition_sectors,
553 }
554 }
555
556 pub fn create_basic(
587 disk_signature: u32,
588 partition_type: PartitionKind,
589 block_count: u32,
590 ) -> Result<Self> {
591 let mut mbr = Self::new_with_signature(disk_signature);
592
593 let partition_block_count = block_count.saturating_sub(Self::MINIMUM_START_BLOCK as u32);
595
596 if partition_block_count == 0 {
597 return Err(Error::DeviceTooSmall);
598 }
599
600 mbr.add_partition(
601 partition_type,
602 Self::MINIMUM_START_BLOCK as u32,
603 partition_block_count,
604 true,
605 )?;
606
607 Ok(mbr)
608 }
609
610 pub fn to_bytes(&self) -> [u8; Self::SIZE] {
612 let mut buffer = [0u8; Self::SIZE];
613
614 buffer[0..440].copy_from_slice(&self.bootstrap_code);
616
617 buffer[440..444].copy_from_slice(&self.disk_signature);
619
620 buffer[444..446].copy_from_slice(&self.reserved);
622
623 for (i, partition) in self.partitions.iter().enumerate() {
625 let offset = 446 + (i * 16);
626 buffer[offset..offset + 16].copy_from_slice(&partition.to_bytes());
627 }
628
629 buffer[510..512].copy_from_slice(&self.boot_signature);
631
632 buffer
633 }
634
635 pub fn find_or_create_partition_with_signature<'a, D: DirectBlockDevice>(
672 device: &'a D,
673 target_signature: u32,
674 partition_type: PartitionKind,
675 ) -> Result<PartitionDevice<'a, D>> {
676 if let Ok(existing_mbr) = Self::read_from_device(device) {
678 if existing_mbr.get_disk_signature() == target_signature && existing_mbr.is_valid() {
680 let valid_partitions = existing_mbr.get_valid_partitions();
682
683 if !valid_partitions.is_empty() {
685 return create_partition_device(device, valid_partitions[0]);
686 }
687 }
688 }
689
690 Self::format_disk_with_signature_and_partition(device, target_signature, partition_type)
693 }
694
695 pub fn format_disk_with_signature_and_partition<'a, D: DirectBlockDevice>(
732 device: &'a D,
733 disk_signature: u32,
734 partition_type: PartitionKind,
735 ) -> Result<PartitionDevice<'a, D>> {
736 device.open()?;
738 let block_count = device.get_block_count()?;
739 device.close()?;
740
741 if block_count < 2048 {
743 return Err(Error::DeviceTooSmall);
744 }
745
746 let new_mbr = Self::create_basic(disk_signature, partition_type, block_count as _)?;
748
749 new_mbr.write_to_device(device)?;
751
752 let valid_partitions = new_mbr.get_valid_partitions();
754 if valid_partitions.is_empty() {
755 return Err(Error::NoValidPartitions);
756 }
757
758 create_partition_device(device, valid_partitions[0])
760 }
761}
762
763impl Default for Mbr {
764 fn default() -> Self {
765 Self::new()
766 }
767}
768
769impl fmt::Display for Mbr {
770 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
771 writeln!(formatter, "Master Boot Record:")?;
772 writeln!(
773 formatter,
774 " Disk Signature: 0x{:08X}",
775 self.get_disk_signature()
776 )?;
777 writeln!(
778 formatter,
779 " Boot Signature: 0x{:02X}{:02X}",
780 self.boot_signature[1], self.boot_signature[0]
781 )?;
782 writeln!(formatter, " Valid: {}", self.is_valid())?;
783 writeln!(
784 formatter,
785 " GPT Protective: {}",
786 self.has_gpt_protective_partition()
787 )?;
788 writeln!(
789 formatter,
790 " Partition Count: {}",
791 self.get_partition_count()
792 )?;
793 writeln!(
794 formatter,
795 " Has Overlaps: {}",
796 self.has_overlapping_partitions()
797 )?;
798 writeln!(formatter, " Partitions:")?;
799
800 for (i, partition) in self.partitions.iter().enumerate() {
801 if partition.is_valid() {
802 writeln!(formatter, " {}: {}", i + 1, partition)?;
803 } else {
804 writeln!(formatter, " {}: Empty", i + 1)?;
805 }
806 }
807
808 Ok(())
809 }
810}
811
812#[cfg(test)]
813mod tests {
814 use super::*;
815 use crate::mbr::PartitionEntry;
816 use alloc::{format, vec};
817
818 fn create_sample_mbr_bytes() -> [u8; 512] {
819 let mut data = [0u8; 512];
820
821 data[510] = 0x55;
823 data[511] = 0xAA;
824
825 data[440..444].copy_from_slice(&0x12345678u32.to_le_bytes());
827
828 let partition1_offset = 446;
830 data[partition1_offset] = 0x80; data[partition1_offset + 4] = 0x0C; data[partition1_offset + 8..partition1_offset + 12].copy_from_slice(&2048u32.to_le_bytes());
833 data[partition1_offset + 12..partition1_offset + 16]
834 .copy_from_slice(&204800u32.to_le_bytes());
835
836 let partition2_offset = 446 + 16;
838 data[partition2_offset + 4] = 0x83; data[partition2_offset + 8..partition2_offset + 12]
840 .copy_from_slice(&206848u32.to_le_bytes());
841 data[partition2_offset + 12..partition2_offset + 16]
842 .copy_from_slice(&102400u32.to_le_bytes());
843
844 data
845 }
846
847 #[test]
848 fn test_mbr_new() {
849 let mbr = super::Mbr::new();
850 assert!(mbr.is_valid());
851 assert_eq!(mbr.get_disk_signature(), 0);
852 assert_eq!(mbr.get_partition_count(), 0);
853 assert!(!mbr.has_gpt_protective_partition());
854 assert!(!mbr.has_overlapping_partitions());
855 }
856
857 #[test]
858 fn test_mbr_new_with_signature() {
859 let signature = 0xDEADBEEF;
860 let mbr = Mbr::new_with_signature(signature);
861 assert!(mbr.is_valid());
862 assert_eq!(mbr.get_disk_signature(), signature);
863 }
864
865 #[test]
866 fn test_mbr_from_bytes() {
867 let data = create_sample_mbr_bytes();
868 let mbr = Mbr::from_bytes(&data).expect("Should parse MBR successfully");
869
870 assert!(mbr.is_valid());
871 assert_eq!(mbr.get_disk_signature(), 0x12345678);
872 assert_eq!(mbr.get_partition_count(), 2);
873
874 let partitions = mbr.get_valid_partitions();
875 assert_eq!(partitions.len(), 2);
876
877 let p1 = &partitions[0];
879 assert!(p1.bootable);
880 assert_eq!(p1.kind, super::PartitionKind::Fat32Lba);
881 assert_eq!(p1.start_block, 2048);
882 assert_eq!(p1.block_count, 204800);
883
884 let p2 = &partitions[1];
886 assert!(!p2.bootable);
887 assert_eq!(p2.kind, super::PartitionKind::Linux);
888 assert_eq!(p2.start_block, 206848);
889 assert_eq!(p2.block_count, 102400);
890 }
891
892 #[test]
893 fn test_mbr_from_bytes_invalid_signature() {
894 let mut data = create_sample_mbr_bytes();
895 data[510] = 0x00; data[511] = 0x00;
897
898 let result = Mbr::from_bytes(&data);
899 assert!(result.is_err());
900 assert_eq!(result.unwrap_err(), Error::InvalidSignature);
901 }
902
903 #[test]
904 fn test_mbr_from_bytes_too_small() {
905 let data = [0u8; 256]; let result = Mbr::from_bytes(&data);
907 assert!(result.is_err());
908 assert_eq!(result.unwrap_err(), Error::BufferTooSmall);
909 }
910
911 #[test]
912 fn test_mbr_to_bytes_round_trip() {
913 let original_data = create_sample_mbr_bytes();
914 let mbr = Mbr::from_bytes(&original_data).unwrap();
915 let serialized_data = mbr.to_bytes();
916
917 assert_eq!(original_data.len(), serialized_data.len());
918 assert_eq!(original_data, serialized_data);
919 }
920
921 #[test]
922 fn test_mbr_disk_signature() {
923 let mut mbr = super::Mbr::new();
924 assert_eq!(mbr.get_disk_signature(), 0);
925
926 mbr.set_disk_signature(0xCAFEBABE);
927 assert_eq!(mbr.get_disk_signature(), 0xCAFEBABE);
928 }
929
930 #[test]
931 fn test_mbr_get_bootable_partition() {
932 let data = create_sample_mbr_bytes();
933 let mbr = Mbr::from_bytes(&data).unwrap();
934
935 let bootable = mbr.get_bootable_partition();
936 assert!(bootable.is_some());
937 assert_eq!(bootable.unwrap().kind, super::PartitionKind::Fat32Lba);
938 }
939
940 #[test]
941 fn test_mbr_set_bootable_partition() {
942 let mut mbr = super::Mbr::new();
943
944 mbr.add_partition(super::PartitionKind::Fat32, 2048, 100000, false)
946 .unwrap();
947 mbr.add_partition(super::PartitionKind::Linux, 102048, 50000, true)
948 .unwrap();
949
950 let bootable = mbr.get_bootable_partition().unwrap();
952 assert_eq!(bootable.kind, super::PartitionKind::Linux);
953
954 mbr.set_bootable_partition(0).unwrap();
956 let bootable = mbr.get_bootable_partition().unwrap();
957 assert_eq!(bootable.kind, super::PartitionKind::Fat32);
958 }
959
960 #[test]
961 fn test_mbr_add_partition() {
962 let mut mbr = super::Mbr::new();
963
964 let index = mbr
965 .add_partition(super::PartitionKind::Fat32Lba, 2048, 204800, true)
966 .unwrap();
967
968 assert_eq!(index, 0);
969 assert_eq!(mbr.get_partition_count(), 1);
970
971 let partition = &mbr.partitions[index];
972 assert!(partition.is_valid());
973 assert!(partition.bootable);
974 assert_eq!(partition.kind, super::PartitionKind::Fat32Lba);
975 }
976
977 #[test]
978 fn test_mbr_add_overlapping_partition() {
979 let mut mbr = super::Mbr::new();
980
981 mbr.add_partition(super::PartitionKind::Fat32, 1000, 2000, false)
983 .unwrap();
984
985 let result = mbr.add_partition(super::PartitionKind::Linux, 1500, 1000, false);
987 assert!(result.is_err());
988 assert_eq!(result.unwrap_err(), Error::OverlappingPartitions);
989 }
990
991 #[test]
992 fn test_mbr_add_too_many_partitions() {
993 let mut mbr = super::Mbr::new();
994
995 for i in 0..4 {
997 let start = (i as u32) * 10000 + 1000;
998 mbr.add_partition(super::PartitionKind::Linux, start, 5000, false)
999 .unwrap();
1000 }
1001
1002 let result = mbr.add_partition(super::PartitionKind::Fat32, 50000, 1000, false);
1004 assert!(result.is_err());
1005 assert_eq!(result.unwrap_err(), Error::Full);
1006 }
1007
1008 #[test]
1009 fn test_mbr_remove_partition() {
1010 let mut mbr = super::Mbr::new();
1011
1012 mbr.add_partition(super::PartitionKind::Fat32, 2048, 100000, false)
1013 .unwrap();
1014 assert_eq!(mbr.get_partition_count(), 1);
1015
1016 mbr.remove_partition(0).unwrap();
1017 assert_eq!(mbr.get_partition_count(), 0);
1018 }
1019
1020 #[test]
1021 fn test_mbr_remove_invalid_partition() {
1022 let mut mbr = super::Mbr::new();
1023 let result = mbr.remove_partition(5); assert!(result.is_err());
1025 assert_eq!(result.unwrap_err(), Error::InvalidIndex);
1026 }
1027
1028 #[test]
1029 fn test_mbr_free_partition_slot() {
1030 let mut mbr = super::Mbr::new();
1031
1032 assert_eq!(mbr.get_free_partition_slot(), Some(0));
1034
1035 mbr.add_partition(super::PartitionKind::Fat32, 1000, 1000, false)
1037 .unwrap();
1038 mbr.add_partition(super::PartitionKind::Linux, 3000, 1000, false)
1039 .unwrap();
1040
1041 assert_eq!(mbr.get_free_partition_slot(), Some(2));
1043
1044 mbr.add_partition(super::PartitionKind::LinuxSwap, 5000, 1000, false)
1046 .unwrap();
1047 mbr.add_partition(super::PartitionKind::NtfsExfat, 7000, 1000, false)
1048 .unwrap();
1049
1050 assert_eq!(mbr.get_free_partition_slot(), None);
1052 }
1053
1054 #[test]
1055 fn test_mbr_has_gpt_protective() {
1056 let mut mbr = super::Mbr::new();
1057 assert!(!mbr.has_gpt_protective_partition());
1058
1059 mbr.add_partition(super::PartitionKind::GptProtective, 1, 0xFFFFFFFF, false)
1060 .unwrap();
1061 assert!(mbr.has_gpt_protective_partition());
1062 }
1063
1064 #[test]
1065 fn test_mbr_overlapping_partitions_detection() {
1066 let mut mbr = super::Mbr::new();
1067
1068 mbr.add_partition(super::PartitionKind::Fat32, 1000, 1000, false)
1070 .unwrap();
1071 mbr.add_partition(super::PartitionKind::Linux, 3000, 1000, false)
1072 .unwrap();
1073 assert!(!mbr.has_overlapping_partitions());
1074
1075 mbr.partitions[2] =
1077 PartitionEntry::new_with_params(false, super::PartitionKind::LinuxSwap, 1500, 1000);
1078 assert!(mbr.has_overlapping_partitions());
1079 }
1080
1081 #[test]
1082 fn test_mbr_default() {
1083 let mbr = super::Mbr::default();
1084 assert!(mbr.is_valid());
1085 assert_eq!(mbr.get_partition_count(), 0);
1086 }
1087
1088 #[test]
1089 fn test_mbr_display() {
1090 let data = create_sample_mbr_bytes();
1091 let mbr = Mbr::from_bytes(&data).unwrap();
1092
1093 let display_string = format!("{mbr}");
1094 assert!(display_string.contains("Master Boot Record"));
1095 assert!(display_string.contains("Disk Signature: 0x12345678"));
1096 assert!(display_string.contains("Valid: true"));
1097 assert!(display_string.contains("Partition Count: 2"));
1098 assert!(display_string.contains("FAT32 LBA"));
1099 assert!(display_string.contains("Linux"));
1100 }
1101
1102 #[test]
1103 fn test_mbr_constants() {
1104 assert_eq!(super::Mbr::SIZE, 512);
1105 assert_eq!(super::Mbr::MAXIMUM_PARTITIONS_COUNT, 4);
1106 assert_eq!(super::Mbr::SIGNATURE, [0x55, 0xAA]);
1107 }
1108
1109 #[test]
1110 fn test_find_or_create_partition_with_signature_existing() {
1111 let mbr_data = create_sample_mbr_bytes();
1112 let mut data = vec![0u8; 4096 * 1024];
1114 data[0..512].copy_from_slice(&mbr_data);
1115
1116 let device = MemoryDevice::<512>::from_vec(data);
1117
1118 let result = Mbr::find_or_create_partition_with_signature(
1120 &device,
1121 0x12345678,
1122 PartitionKind::Fat32Lba,
1123 );
1124 assert!(result.is_ok());
1125
1126 let partition_device = result.unwrap();
1127 assert!(partition_device.is_valid());
1128 assert_eq!(partition_device.get_start_lba(), Mbr::MINIMUM_START_BLOCK); }
1130
1131 #[test]
1132 fn test_find_or_create_partition_with_signature_wrong_signature() {
1133 let mbr_data = create_sample_mbr_bytes();
1134 let mut data = vec![0u8; 4096 * 1024];
1136 data[0..512].copy_from_slice(&mbr_data);
1137
1138 let device = MemoryDevice::<512>::from_vec(data);
1139
1140 let result = Mbr::find_or_create_partition_with_signature(
1142 &device,
1143 0xABCDEF00, PartitionKind::Linux,
1145 );
1146
1147 assert!(result.is_ok());
1148
1149 let partition_device = result.unwrap();
1150 assert!(partition_device.is_valid());
1151
1152 let new_mbr = Mbr::read_from_device(&device).unwrap();
1154 assert_eq!(new_mbr.get_disk_signature(), 0xABCDEF00);
1155
1156 let valid_partitions = new_mbr.get_valid_partitions();
1158 assert_eq!(valid_partitions.len(), 1);
1159 assert_eq!(valid_partitions[0].kind, PartitionKind::Linux);
1160 }
1161
1162 #[test]
1163 fn test_find_or_create_partition_with_signature_no_mbr() {
1164 let data = vec![0u8; 4096 * 1024]; let device = MemoryDevice::<512>::from_vec(data);
1167
1168 let result = Mbr::find_or_create_partition_with_signature(
1169 &device,
1170 0x11223344,
1171 PartitionKind::Fat32Lba,
1172 );
1173 assert!(result.is_ok());
1174
1175 let partition_device = result.unwrap();
1176 assert!(partition_device.is_valid());
1177 assert_eq!(partition_device.get_start_lba(), Mbr::MINIMUM_START_BLOCK); let mbr = Mbr::read_from_device(&device).unwrap();
1181 assert_eq!(mbr.get_disk_signature(), 0x11223344);
1182 assert!(mbr.is_valid());
1183 }
1184
1185 #[test]
1186 fn test_find_or_create_partition_with_signature_empty_mbr() {
1187 let mut data = vec![0u8; 4096 * 1024];
1189 let empty_mbr = Mbr::new_with_signature(0x55667788);
1190 let mbr_bytes = empty_mbr.to_bytes();
1191 data[0..512].copy_from_slice(&mbr_bytes);
1192
1193 let device = MemoryDevice::<512>::from_vec(data);
1194
1195 let result = Mbr::find_or_create_partition_with_signature(
1196 &device,
1197 0x55667788, PartitionKind::NtfsExfat,
1199 );
1200 assert!(result.is_ok());
1201
1202 let partition_device = result.unwrap();
1203 assert!(partition_device.is_valid());
1204
1205 let mbr = Mbr::read_from_device(&device).unwrap();
1207 assert_eq!(mbr.get_disk_signature(), 0x55667788);
1208 let valid_partitions = mbr.get_valid_partitions();
1209 assert_eq!(valid_partitions.len(), 1);
1210 assert_eq!(valid_partitions[0].kind, PartitionKind::NtfsExfat);
1211 }
1212
1213 #[test]
1214 fn test_format_disk_with_signature_and_partition() {
1215 let data = vec![0u8; 2048 * 1024]; let device = MemoryDevice::<512>::from_vec(data);
1217
1218 let result = Mbr::format_disk_with_signature_and_partition(
1219 &device,
1220 0x99887766,
1221 PartitionKind::LinuxSwap,
1222 );
1223 assert!(result.is_ok());
1224
1225 let partition_device: PartitionDevice<'_, MemoryDevice<512>> = result.unwrap();
1226 assert!(partition_device.is_valid());
1227 assert_eq!(partition_device.get_start_lba(), Mbr::MINIMUM_START_BLOCK);
1228
1229 let mbr = Mbr::read_from_device(&device).unwrap();
1231 assert_eq!(mbr.get_disk_signature(), 0x99887766);
1232 assert!(mbr.is_valid());
1233
1234 let valid_partitions = mbr.get_valid_partitions();
1235 assert_eq!(valid_partitions.len(), 1);
1236 assert_eq!(valid_partitions[0].kind, PartitionKind::LinuxSwap);
1237 assert!(valid_partitions[0].bootable); }
1239
1240 #[test]
1241 fn test_format_disk_with_signature_and_partition_device_too_small() {
1242 let data = vec![0u8; 1024]; let device = MemoryDevice::<512>::from_vec(data);
1245
1246 let result = Mbr::format_disk_with_signature_and_partition(
1247 &device,
1248 0x12345678,
1249 PartitionKind::Fat32Lba,
1250 );
1251 assert!(result.is_err());
1252 assert_eq!(result.unwrap_err(), Error::DeviceTooSmall);
1253 }
1254}