Skip to content

Commit 1fa479c

Browse files
committed
partitioning/writer: Free up first 2MiB properly, deal with LBA mixups
Signed-off-by: Ikey Doherty <[email protected]>
1 parent dfa49bb commit 1fa479c

File tree

1 file changed

+40
-13
lines changed

1 file changed

+40
-13
lines changed

crates/partitioning/src/writer.rs

+40-13
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::{
1717
planner::{Change, Planner},
1818
GptAttributes,
1919
};
20+
const SECTOR_SIZE: u64 = 512;
2021

2122
/// Errors that can occur when writing changes to disk
2223
#[derive(Debug, Error)]
@@ -50,21 +51,36 @@ pub struct DiskWriter<'a> {
5051
pub planner: &'a Planner,
5152
}
5253

53-
/// Zero out up to 2MiB of a region by writing 32 * 64KiB blocks
54-
fn zero_prefix_n<W: Write + Seek>(writer: &mut W, offset: u64, size: u64) -> io::Result<()> {
54+
/// Zero out a specific region of the disk
55+
fn zero_region<W: Write + Seek>(writer: &mut W, offset: u64, size: u64) -> io::Result<()> {
5556
let zeros = [0u8; 65_536];
5657
writer.seek(std::io::SeekFrom::Start(offset))?;
57-
// Write up to 32 blocks or until we hit the partition size
58-
for _ in 0..32 {
59-
if offset + (65_536 * (32 + 1)) as u64 > size {
60-
break;
61-
}
58+
let chunks = (size / 65_536) as usize;
59+
for _ in 0..chunks {
6260
writer.write_all(&zeros)?;
6361
}
62+
// Handle any remaining bytes
63+
let remainder = size % 65_536;
64+
if remainder > 0 {
65+
writer.write_all(&zeros[..remainder as usize])?;
66+
}
6467
writer.flush()?;
6568
Ok(())
6669
}
6770

71+
/// Zero out disk headers by wiping first 2MiB of the disk
72+
fn zero_disk_headers<W: Write + Seek>(writer: &mut W) -> io::Result<()> {
73+
// Clear first 2MiB to wipe all common boot structures
74+
zero_region(writer, 0, 2 * 1024 * 1024)
75+
}
76+
77+
/// Zero out up to 2MiB of a partition by writing 32 * 64KiB blocks
78+
/// Zero out up to 2MiB of a region by writing 32 * 64KiB blocks
79+
fn zero_partition_prefix<W: Write + Seek>(writer: &mut W, offset: u64, size: u64) -> io::Result<()> {
80+
let to_zero = std::cmp::min(size, 2 * 1024 * 1024); // 2MiB max
81+
zero_region(writer, offset, to_zero)
82+
}
83+
6884
impl<'a> DiskWriter<'a> {
6985
/// Create a new DiskWriter.
7086
pub fn new(device: &'a BlockDevice, planner: &'a Planner) -> Self {
@@ -130,11 +146,13 @@ impl<'a> DiskWriter<'a> {
130146

131147
let mut gpt_table = if self.planner.wipe_disk() {
132148
if writable {
133-
// Zero out the first MiB to clear any old partition tables and boot sectors
134-
zero_prefix_n(device, 0, 1_048_576)?;
149+
// Zero out headers including potential ISO structures
150+
zero_disk_headers(device)?;
135151

152+
// Convert total bytes to LBA sectors, subtract 1 as per GPT spec
153+
let total_lba = self.device.size() / SECTOR_SIZE;
136154
let mbr = mbr::ProtectiveMBR::with_lb_size(
137-
u32::try_from((self.device.size() / 512) - 1).unwrap_or(0xFF_FF_FF_FF),
155+
u32::try_from(total_lba.saturating_sub(1)).unwrap_or(0xFF_FF_FF_FF),
138156
);
139157
eprintln!("size is {}", self.device.size());
140158
mbr.overwrite_lba0(device)?;
@@ -177,15 +195,24 @@ impl<'a> DiskWriter<'a> {
177195
partition_id,
178196
attributes,
179197
} => {
180-
let start_lba = *start / 512;
181-
let size_lba = (*end - *start) / 512;
198+
// Convert byte offsets to LBA sectors
199+
let start_lba = *start / SECTOR_SIZE;
200+
let size_bytes = *end - *start;
201+
let size_lba = size_bytes / SECTOR_SIZE;
182202
let (part_type, part_name) = match attributes.as_ref().and_then(|a| a.table.as_gpt()) {
183203
Some(GptAttributes { type_guid, name, .. }) => {
184204
(type_guid.clone(), name.clone().unwrap_or_default())
185205
}
186206
None => (partition_types::BASIC, "".to_string()),
187207
};
188208

209+
eprintln!(
210+
"Converting partition: bytes {}..{} to LBA {}..{}",
211+
start,
212+
end,
213+
start_lba,
214+
start_lba + size_lba
215+
);
189216
let id =
190217
gpt_table.add_partition_at(&part_name, *partition_id, start_lba, size_lba, part_type, 0)?;
191218
println!("Added partition {}: {:?}", partition_id, id);
@@ -212,7 +239,7 @@ impl<'a> DiskWriter<'a> {
212239
original.sync_all()?;
213240

214241
for (start, end) in zero_regions {
215-
zero_prefix_n(original, start, end - start)?;
242+
zero_partition_prefix(original, start, end - start)?;
216243
}
217244

218245
blkpg::create_kernel_partitions(self.device.device())?;

0 commit comments

Comments
 (0)