Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions src/fat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,20 @@ pub fn create_fat_image(
// Add overhead and enforce a minimum size.
const MIN_FAT_SIZE: u64 = 16 * 1024 * 1024; // 16MB. Ensures FAT16 formatting.
const FAT_OVERHEAD: u64 = 2 * 1024 * 1024; // 2MB. Overhead for filesystem structures.
let mut total_size = std::cmp::max(content_size + FAT_OVERHEAD, MIN_FAT_SIZE);

// Round up to the nearest sector size
const SECTOR_SIZE: u64 = 512;
total_size = total_size.div_ceil(SECTOR_SIZE) * SECTOR_SIZE;

// Determine FAT type based on size
// Calculate the logical size based on content + overhead, rounded up to sector size.
// This is the size we want to report as Nsect.
let mut logical_size = (content_size + FAT_OVERHEAD).div_ceil(SECTOR_SIZE) * SECTOR_SIZE;
// Ensure logical_size is at least one sector
if logical_size == 0 {
logical_size = SECTOR_SIZE;
}
Comment on lines +53 to +55
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This check for logical_size == 0 is unreachable. content_size is derived from file metadata lengths and will be non-negative. Since FAT_OVERHEAD is a positive constant, the sum content_size + FAT_OVERHEAD will always be greater than zero. Consequently, logical_size, which is calculated by rounding this sum up to the nearest sector size, can never be zero. This block of code can be safely removed to simplify the logic.


// The actual total size of the FAT image file, ensuring it meets minimum requirements for FAT16.
let total_size = std::cmp::max(logical_size, MIN_FAT_SIZE);

// Determine FAT type based on total_size
let fat_type = if total_size <= 268_435_456 {
FatType::Fat16
} else {
Expand Down Expand Up @@ -86,7 +93,7 @@ pub fn create_fat_image(
copy_to_fat(&boot_dir, loader_path, "BOOTX64.EFI")?;
copy_to_fat(&boot_dir, kernel_path, "KERNEL.EFI")?;

Ok(total_size as u32 / crate::utils::ISO_SECTOR_SIZE as u32)
Ok((logical_size / SECTOR_SIZE) as u32)
}

#[cfg(test)]
Expand Down
77 changes: 40 additions & 37 deletions src/iso/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ use crate::iso::mbr::create_mbr_for_gpt_hybrid; // Import specific function
/// The main builder for creating an ISO 9660 image.
pub struct IsoBuilder {
root: IsoDirectory,
iso_file: Option<File>,
boot_info: Option<BootInfo>,
current_lba: u32,
total_sectors: u32,
Expand All @@ -47,7 +46,6 @@ impl IsoBuilder {
pub fn new() -> Self {
Self {
root: IsoDirectory::new(),
iso_file: None,
boot_info: None,
current_lba: 0,
total_sectors: 0,
Expand Down Expand Up @@ -130,17 +128,14 @@ impl IsoBuilder {
/// Builds the ISO file based on the configured files and boot information.
pub fn build(
&mut self,
iso_path: &Path,
iso_file: &mut File, // Accept File handle directly
_iso_path: &Path, // Renamed to _iso_path to silence unused variable warning
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The _iso_path parameter is unused within the build function and is marked as such. To simplify the function's interface and remove dead code, consider removing this parameter. The path is already available in the calling build_iso function where it's needed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

ลายเซ็นฟังก์ชัน build ได้รับการปรับปรุงให้ยอมรับ &mut File ซึ่งเป็นการปรับปรุงที่ดี อย่างไรก็ตาม พารามิเตอร์ _iso_path ไม่ได้ถูกใช้งานแล้วและควรถูกลบออกเพื่อทำให้ลายเซ็นฟังก์ชันสะอาดขึ้น การเปลี่ยนแปลงนี้จะต้องถูกส่งต่อไปยังตำแหน่งที่เรียกใช้ใน build_iso ด้วย

Suggested change
&mut self,
iso_path: &Path,
iso_file: &mut File, // Accept File handle directly
_iso_path: &Path, // Renamed to _iso_path to silence unused variable warning
iso_file: &mut File, // Accept File handle directly
esp_lba: Option<u32>,

esp_lba: Option<u32>,
esp_size_sectors: Option<u32>,
) -> io::Result<()> {
self.esp_lba = esp_lba;
self.esp_size_sectors = esp_size_sectors;
let mut iso_file = if let Some(file) = self.iso_file.take() {
file
} else {
File::create(iso_path)?
};
// iso_file is now passed directly

// Placeholder for MBR and GPT structures.
// We'll write the actual MBR/GPT after the ISO9660 content is written and total_sectors is known.
Expand Down Expand Up @@ -177,7 +172,7 @@ impl IsoBuilder {
// Write volume descriptors (PVD, BRVD, Terminator). These will be written starting at data_start_lba.
// Pass the calculated end of filesystem data as a preliminary total_sectors.
// This will be correctly updated by finalize later. The VDs are at fixed locations.
write_descriptors(&mut iso_file, self.root.lba, self.current_lba)?;
write_descriptors(iso_file, self.root.lba, self.current_lba)?;

let mut boot_entries = Vec::new();

Expand All @@ -204,14 +199,14 @@ impl IsoBuilder {
&uefi_boot.destination_in_iso,
)?);
}
write_boot_catalog_to_iso(&mut iso_file, boot_catalog_lba, boot_entries)?;
write_boot_catalog_to_iso(iso_file, boot_catalog_lba, boot_entries)?;

// Write directory records and copy file contents.
write_directories(&mut iso_file, &self.root, self.root.lba)?;
copy_files(&mut iso_file, &self.root)?;
write_directories(iso_file, &self.root, self.root.lba)?;
copy_files(iso_file, &self.root)?;

// Finalize the ISO by padding and updating the total sector count in the PVD
finalize_iso(&mut iso_file, &mut self.total_sectors)?;
finalize_iso(iso_file, &mut self.total_sectors)?;

// If not isohybrid, clear the initial reserved sectors (MBR area).

Expand All @@ -233,7 +228,7 @@ impl IsoBuilder {
// Write MBR
iso_file.seek(SeekFrom::Start(0))?;
let mbr = create_mbr_for_gpt_hybrid(self.total_sectors, self.is_isohybrid)?;
mbr.write_to(&mut iso_file)?;
mbr.write_to(iso_file)?;

// Write GPT structures if esp_size_sectors > 0
if let Some(esp_size_sectors_val) = esp_size_sectors
Expand All @@ -252,7 +247,8 @@ impl IsoBuilder {
"EFI System Partition",
0x0000000000000002, // EFI_PART_SYSTEM_PARTITION_ATTR_PLATFORM_REQUIRED
)];
write_gpt_structures(&mut iso_file, total_lbas, &partitions)?;
write_gpt_structures(iso_file, total_lbas, &partitions)?;
iso_file.sync_data()?; // Explicitly sync data to disk after writing MBR/GPT
}
}

Expand All @@ -261,17 +257,21 @@ impl IsoBuilder {
}

/// High-level function to create an ISO 9660 image from a structured `IsoImage`.
/// Returns the path to the generated ISO, the temporary FAT image holder (if created),
/// and the `File` handle to the ISO itself.
pub fn build_iso(
iso_path: &Path,
image: &IsoImage,
is_isohybrid: bool,
) -> io::Result<(Option<PathBuf>, Option<NamedTempFile>)> {
) -> io::Result<(PathBuf, Option<NamedTempFile>, File, Option<u32>)> {
// Added Option<u32> for logical_fat_size_512_sectors
let mut iso_builder = IsoBuilder::new();
iso_builder.set_isohybrid(is_isohybrid);

let mut temp_fat_file_holder: Option<NamedTempFile> = None;
let mut logical_fat_size_512_sectors: Option<u32> = None; // Declare here

// Open the ISO file for writing early to allow writing ESP before ISO9660 content
// Create the ISO file
let mut iso_file = File::create(iso_path)?;

if let Some(uefi_boot) = &image.boot_info.uefi_boot {
Expand All @@ -282,15 +282,16 @@ pub fn build_iso(
let path = temp_fat_file.path().to_path_buf();
temp_fat_file_holder = Some(temp_fat_file);

fat::create_fat_image(&path, &uefi_boot.boot_image, &uefi_boot.kernel_image)?;
let size_512_sectors =
fat::create_fat_image(&path, &uefi_boot.boot_image, &uefi_boot.kernel_image)?;
logical_fat_size_512_sectors = Some(size_512_sectors); // Assign here

let fat_img_metadata = std::fs::metadata(&path)?;
let calculated_esp_size_sectors =
(fat_img_metadata.len() as u32).div_ceil(crate::utils::ISO_SECTOR_SIZE as u32);
// Convert logical FAT size from 512-byte sectors to ISO 2048-byte sectors
let calculated_esp_size_iso_sectors = size_512_sectors.div_ceil(4); // 1 ISO sector = 4 * 512-byte sectors

// Store ESP LBA and size for the boot catalog
iso_builder.esp_lba = Some(ESP_START_LBA); // ESP starts at LBA 34 for hybrid ISOs
iso_builder.esp_size_sectors = Some(calculated_esp_size_sectors);
iso_builder.esp_size_sectors = Some(calculated_esp_size_iso_sectors);

// Copy the FAT image to the ISO file at the designated ESP LBA (34)
iso_file.seek(SeekFrom::Start(
Expand All @@ -317,21 +318,23 @@ pub fn build_iso(
// Set boot information for the ISO builder
iso_builder.set_boot_info(image.boot_info.clone());

// Pass the opened iso_file to the builder
iso_builder.iso_file = Some(iso_file);
iso_builder.build(iso_path, iso_builder.esp_lba, iso_builder.esp_size_sectors)?;

// Return the path to the FAT image if it was created, and the holder to keep it alive
if is_isohybrid {
Ok((
temp_fat_file_holder
.as_ref()
.map(|f| f.path().to_path_buf()),
temp_fat_file_holder,
))
} else {
Ok((None, None))
}
// Build the ISO using the mutable iso_file
iso_builder.build(
&mut iso_file,
iso_path,
iso_builder.esp_lba,
iso_builder.esp_size_sectors,
)?;

// The iso_file is already the final_iso_file
let final_iso_file = iso_file;

Ok((
iso_path.to_path_buf(),
temp_fat_file_holder,
final_iso_file,
logical_fat_size_512_sectors, // Return this value
))
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion src/iso/builder_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ pub fn create_uefi_esp_boot_entry(
Ok(BootCatalogEntry {
platform_id: BOOT_CATALOG_EFI_PLATFORM_ID,
boot_image_lba: esp_lba,
boot_image_sectors: esp_size_sectors as u16,
boot_image_sectors: (esp_size_sectors * 4) as u16,
bootable: true,
})
}
Expand Down
Loading
Loading