Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WIP GPT generation code #1040

Merged
merged 9 commits into from
May 13, 2023
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
91 changes: 0 additions & 91 deletions Source/Mosa.DeviceSystem/GUIDPartitionTable.cs

This file was deleted.

6 changes: 6 additions & 0 deletions Source/Mosa.Tool.Launcher/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@
<Label FontSize="14" Name="qemuPathLbl" Margin="165, -23, 0, 0">No path specified</Label>
<Label FontSize="14">QEMU BIOS Directory:</Label>
<Label FontSize="14" Name="qemuBiosPathLbl" Margin="165, -23, 0, 0">No path specified</Label>
<Label FontSize="14">QEMU EDK2 x86:</Label>
<Label FontSize="14" Name="qemuEdk2X86PathLbl" Margin="165, -23, 0, 0">No path specified</Label>
<Label FontSize="14">QEMU EDK2 x64:</Label>
<Label FontSize="14" Name="qemuEdk2X64PathLbl" Margin="165, -23, 0, 0">No path specified</Label>
<Label FontSize="14">QEMU EDK2 ARM:</Label>
<Label FontSize="14" Name="qemuEdk2ARMPathLbl" Margin="165, -23, 0, 0">No path specified</Label>
<Label FontSize="14">QEMU Image:</Label>
<Label FontSize="14" Name="qemuImgPathLbl" Margin="165, -23, 0, 0">No path specified</Label>
<Label FontSize="14">Bochs:</Label>
Expand Down
3 changes: 3 additions & 0 deletions Source/Mosa.Tool.Launcher/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ private void UpdateInterfaceAppLocations()
ndiasmPathLbl.Content = settings.GetValue("AppLocation.Ndisasm", "N/A");
qemuPathLbl.Content = settings.GetValue("AppLocation.Qemu", "N/A");
qemuBiosPathLbl.Content = settings.GetValue("AppLocation.QemuBIOS", "N/A");
qemuEdk2X86PathLbl.Content = settings.GetValue("AppLocation.QemuEDK2X86", "N/A");
qemuEdk2X64PathLbl.Content = settings.GetValue("AppLocation.QemuEDK2X64", "N/A");
qemuEdk2ARMPathLbl.Content = settings.GetValue("AppLocation.QemuEDK2ARM", "N/A");
qemuImgPathLbl.Content = settings.GetValue("AppLocation.QemuImg", "N/A");
vboxPathLbl.Content = settings.GetValue("AppLocation.VirtualBox", "N/A");
mkisofsPathLbl.Content = settings.GetValue("AppLocation.Mkisofs", "N/A");
Expand Down
11 changes: 0 additions & 11 deletions Source/Mosa.Utility.BootImage/BootImageOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,15 @@

namespace Mosa.Utility.BootImage;

/// <summary>
///
/// </summary>
public class BootImageOptions
{
public Guid MediaGuid = Guid.NewGuid();
public Guid MediaLastSnapGuid = Guid.NewGuid();
public byte[] MBRCode = null;
public byte[] FatBootCode = null;
public string VolumeLabel = string.Empty;
public ImageFirmware ImageFirmware = ImageFirmware.Bios;
public ImageFormat ImageFormat = ImageFormat.IMG;
public bool MBROption = true;
public uint BlockCount = 0;
public FileSystem FileSystem = FileSystem.FAT12;
public List<IncludeFile> IncludeFiles = new List<IncludeFile>();

public string DiskImageFileName = null;

public BootImageOptions()
{
}
}
84 changes: 53 additions & 31 deletions Source/Mosa.Utility.BootImage/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,52 +75,74 @@ public static void Create(BootImageOptions options)
var partitionDevice = new PartitionDeviceDriver();

// Setup partition configuration
var configuraiton = new DiskPartitionConfiguration
var configuration = new DiskPartitionConfiguration
{
Index = 0,
ReadOnly = false,
};

if (options.MBROption)
if (options.ImageFirmware == ImageFirmware.Bios)
{
// Create master boot block record
var mbr = new MasterBootBlock(diskDeviceDriver)
{
// Setup partition entry
DiskSignature = 0x12345678
DiskSignature = 0x12345678,
Code = null
};

mbr.Partitions[0].Bootable = true;
mbr.Partitions[0].StartLBA = 2048; // minimum for grub legacy = 64, grub2 = 2048 (1Mb)
mbr.Partitions[0].StartLBA = 2048;
mbr.Partitions[0].TotalBlocks = blockCount - mbr.Partitions[0].StartLBA;
mbr.Partitions[0].PartitionType = options.FileSystem switch
{
FileSystem.FAT12 => PartitionType.FAT12,
FileSystem.FAT16 => PartitionType.FAT16,
FileSystem.FAT32 => PartitionType.FAT32
};

mbr.Write();

switch (options.FileSystem)
configuration.StartLBA = mbr.Partitions[0].StartLBA;
configuration.TotalBlocks = mbr.Partitions[0].TotalBlocks;
}
else if (options.ImageFirmware == ImageFirmware.Uefi)
{
// Create protective MBR
var mbr = new MasterBootBlock(diskDeviceDriver)
{
case FileSystem.FAT12: mbr.Partitions[0].PartitionType = PartitionType.FAT12; break;
case FileSystem.FAT16: mbr.Partitions[0].PartitionType = PartitionType.FAT16; break;
case FileSystem.FAT32: mbr.Partitions[0].PartitionType = PartitionType.FAT32; break;
default: break;
}
// Setup partition entry
DiskSignature = 0x12345678,
Code = null
};

mbr.Code = options.MBRCode;
mbr.Partitions[0].Bootable = false;
mbr.Partitions[0].StartLBA = 1;
mbr.Partitions[0].TotalBlocks = blockCount - mbr.Partitions[0].StartLBA;
mbr.Partitions[0].PartitionType = 0xEE; // GPT protective MBR ID

mbr.Write();

configuraiton.StartLBA = mbr.Partitions[0].StartLBA;
configuraiton.TotalBlocks = mbr.Partitions[0].TotalBlocks;
// Create GUID partition table
var gpt = new GuidPartitionTable(diskDeviceDriver);

gpt.Write();

configuration.StartLBA = 3;
configuration.TotalBlocks = blockCount - configuration.StartLBA;
}
else
{
configuraiton.StartLBA = 0;
configuraiton.TotalBlocks = diskDeviceDriver.TotalBlocks;
configuration.StartLBA = 0;
configuration.TotalBlocks = diskDeviceDriver.TotalBlocks;
}

// Setup device -- required as part of framework in operating system
var device = new Device
{
Configuration = configuraiton,
Configuration = configuration,
DeviceDriver = partitionDevice,
Parent = diskDevice,
Parent = diskDevice
};

// Setup and initialize
Expand All @@ -129,22 +151,22 @@ public static void Create(BootImageOptions options)
partitionDevice.Start();

// Set FAT settings
var fatSettings = new FatSettings();

fatSettings.FATType = options.FileSystem switch
var fatSettings = new FatSettings
{
FileSystem.FAT12 => FatType.FAT12,
FileSystem.FAT16 => FatType.FAT16,
FileSystem.FAT32 => FatType.FAT32,
_ => fatSettings.FATType
FATType = options.FileSystem switch
{
FileSystem.FAT12 => FatType.FAT12,
FileSystem.FAT16 => FatType.FAT16,
FileSystem.FAT32 => FatType.FAT32
},
FloppyMedia = false,
VolumeLabel = options.VolumeLabel,
SerialID = new byte[] { 0x01, 0x02, 0x03, 0x04 },
SectorsPerTrack = diskGeometry.SectorsPerTrack,
NumberOfHeads = diskGeometry.Heads,
HiddenSectors = diskGeometry.SectorsPerTrack,
OSBootCode = null
};
fatSettings.FloppyMedia = false;
fatSettings.VolumeLabel = options.VolumeLabel;
fatSettings.SerialID = new byte[] { 0x01, 0x02, 0x03, 0x04 };
fatSettings.SectorsPerTrack = diskGeometry.SectorsPerTrack;
fatSettings.NumberOfHeads = diskGeometry.Heads;
fatSettings.HiddenSectors = diskGeometry.SectorsPerTrack;
fatSettings.OSBootCode = options.FatBootCode;

// Create FAT file system
var fat = new FatFileSystem(partitionDevice);
Expand Down
84 changes: 84 additions & 0 deletions Source/Mosa.Utility.BootImage/GuidPartitionTable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) MOSA Project. Licensed under the New BSD License.

using System;
using System.IO.Hashing;
using System.Text;
using Mosa.DeviceSystem;

namespace Mosa.Utility.BootImage;

//https://en.wikipedia.org/wiki/GUID_Partition_Table
public class GuidPartitionTable
{
private const uint HeaderSize = 0x5C; // 92 bytes
private const uint PartitionEntrySize = 0x80; // 128 bytes

private readonly IDiskDevice diskDevice;

private static readonly byte[] Signature = { 0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54 }; // "EFI PART"
private static readonly byte[] Revision = { 0x00, 0x00, 0x01, 0x00 }; // Revision 1.0 (UEFI 2.8)

public GuidPartitionTable(IDiskDevice diskDevice)
{
this.diskDevice = diskDevice;
}

public void Write()
{
var tableHeaderLba = 1U;
var partitionEntriesLba = 2U;
var backupTableHeaderLba = diskDevice.TotalBlocks - 1; // Last LBA
var backupPartitionEntriesLba = diskDevice.TotalBlocks - 2;

// EFI System Partition
var efiSystemPartition = new DataBlock(diskDevice.BlockSize);
efiSystemPartition.SetBytes(0, Guid.Parse("C12A7328-F81F-11D2-BA4B-00A0C93EC93B").ToByteArray());
efiSystemPartition.SetBytes(16, Guid.NewGuid().ToByteArray());
efiSystemPartition.SetULong(32, partitionEntriesLba + 1);
efiSystemPartition.SetULong(40, backupPartitionEntriesLba - 1);
efiSystemPartition.SetULong(48, 0b0000000000000000000000000000000000000000000000000000000000000000);
efiSystemPartition.SetBytes(56, Encoding.Unicode.GetBytes("MOSA-PROJECT-POWERED-BY-DO"));

var partitionEntries = new DataBlock[1];
partitionEntries[0] = efiSystemPartition;

var partitionEntriesCrc32 = Crc32.Hash(efiSystemPartition.Data[..128]);

// Partition table header
var partitionTableHeader = new DataBlock(diskDevice.BlockSize);
partitionTableHeader.SetBytes(0, Signature);
partitionTableHeader.SetBytes(8, Revision);
partitionTableHeader.SetUInt32(12, HeaderSize);
partitionTableHeader.SetUInt32(16, 0); // CRC32 checksum, zeroed during calculation
partitionTableHeader.SetUInt32(20, 0); // Reserved
partitionTableHeader.SetULong(24, tableHeaderLba);
partitionTableHeader.SetULong(32, backupTableHeaderLba);
partitionTableHeader.SetULong(40, (uint)(partitionEntriesLba + partitionEntries.Length + 1)); // First usable LBA
partitionTableHeader.SetULong(48, (uint)(backupPartitionEntriesLba - partitionEntries.Length - 1)); // Last usable LBA
partitionTableHeader.SetBytes(56, Guid.NewGuid().ToByteArray()); // Disk GUID
partitionTableHeader.SetULong(72, partitionEntriesLba);
partitionTableHeader.SetUInt32(80, (uint)partitionEntries.Length);
partitionTableHeader.SetUInt32(84, PartitionEntrySize);
partitionTableHeader.SetBytes(88, partitionEntriesCrc32); // CRC32 checksum of partition entries array

var tableHeaderCrc32 = Crc32.Hash(partitionTableHeader.Data[..0x5C]);
partitionTableHeader.SetBytes(16, tableHeaderCrc32);

for (uint offset = 92; offset < partitionTableHeader.Length; offset++)
partitionTableHeader.SetByte(offset, 0);

// Main table header
diskDevice.WriteBlock(tableHeaderLba, 1, partitionTableHeader.Data);

// Main entries
for (uint i = 0; i < partitionEntries.Length; i++)
diskDevice.WriteBlock(partitionEntriesLba + i, 1, partitionEntries[i].Data);

// Backup entries
for (uint i = 0; i < partitionEntries.Length; i++)
diskDevice.WriteBlock(backupPartitionEntriesLba + i, 1, partitionEntries[i].Data);

// Backup table header
diskDevice.WriteBlock(backupTableHeaderLba, 1, partitionTableHeader.Data);
}
}
3 changes: 2 additions & 1 deletion Source/Mosa.Utility.BootImage/ImageFirmware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ namespace Mosa.Utility.BootImage;

public enum ImageFirmware
{
Bios
Bios,
Uefi
}
7 changes: 5 additions & 2 deletions Source/Mosa.Utility.BootImage/Mosa.Utility.BootImage.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<AssemblyTitle>Mosa.Utility.BootImage</AssemblyTitle>
Expand All @@ -17,4 +17,7 @@
<ProjectReference Include="..\Mosa.Compiler.Common\Mosa.Compiler.Common.csproj" />
<ProjectReference Include="..\Mosa.Utility.FileSystem\Mosa.Utility.FileSystem.csproj" />
</ItemGroup>
</Project>
<ItemGroup>
<PackageReference Include="System.IO.Hashing" Version="7.0.0" />
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions Source/Mosa.Utility.Configuration/CommandLineArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ private static List<Argument> GetMap()
new Argument { Name = "-include", Setting = "Image.FileSystem.RootInclude" },

new Argument { Name = "-bios", Setting = "Image.Firmware", Value="bios"},
new Argument { Name = "-uefi", Setting = "Image.Firmware", Value="uefi"},
new Argument { Name = "-firmware", Setting = "Image.Firmware"},

// Advance:
Expand Down
Loading