/// <summary> /// Reads the master boot block. /// </summary> /// <returns></returns> public bool Read() { valid = false; MasterBootBlock mbr = new MasterBootBlock(diskDevice); if (!mbr.Valid) return false; if ((mbr.Partitions[0].PartitionType != PartitionType.GPT) || (mbr.Partitions[1].PartitionType != PartitionType.Empty) || (mbr.Partitions[2].PartitionType != PartitionType.Empty) || (mbr.Partitions[3].PartitionType != PartitionType.Empty) || (!mbr.Partitions[0].Bootable) || (mbr.Partitions[0].StartLBA != 1)) return false; BinaryFormat gpt = new BinaryFormat(diskDevice.ReadBlock(1, 1)); if ((gpt.GetByte(0) != 45) && (gpt.GetByte(1) != 46) && (gpt.GetByte(2) != 49) && (gpt.GetByte(3) != 20) && (gpt.GetByte(4) != 50) && (gpt.GetByte(5) != 41) && (gpt.GetByte(6) != 52) && (gpt.GetByte(7) != 54)) return false; if ((gpt.GetUInt(GPT.Revision) != GPTConstant.SupportedRevision) || (gpt.GetUInt(GPT.HeaderSize) != GPTConstant.HeaderSize) || (gpt.GetUInt(GPT.Reserved) != 0) || (gpt.GetUInt(GPT.PartitionStartingLBA) != 2) ) return false; valid = true; return valid; }
/// <summary> /// Creates the partition devices. /// </summary> public void CreatePartitionDevices() { // FIXME: Do not create multiple partition devices if this method executed more than once // Find all online disk devices foreach (var device in deviceManager.GetDevices(new IsDiskDevice(), new IsOnline())) { var diskDevice = device as IDiskDevice; var mbr = new MasterBootBlock(diskDevice); if (!mbr.Valid) { return; } for (uint i = 0; i < MasterBootBlock.MaxMBRPartitions; i++) { if (mbr.Partitions[i].PartitionType != PartitionType.Empty) { deviceManager.Add(new PartitionDevice(diskDevice, mbr.Partitions[i], false)); } } } }
/// <summary> /// Reads the master boot block. /// </summary> /// <returns></returns> public bool Read() { valid = false; MasterBootBlock mbr = new MasterBootBlock(diskDevice); if (!mbr.Valid) { return(false); } if ((mbr.Partitions[0].PartitionType != PartitionType.GPT) || (mbr.Partitions[1].PartitionType != PartitionType.Empty) || (mbr.Partitions[2].PartitionType != PartitionType.Empty) || (mbr.Partitions[3].PartitionType != PartitionType.Empty) || (!mbr.Partitions[0].Bootable) || (mbr.Partitions[0].StartLBA != 1)) { return(false); } BinaryFormat gpt = new BinaryFormat(diskDevice.ReadBlock(1, 1)); if ((gpt.GetByte(0) != 45) && (gpt.GetByte(1) != 46) && (gpt.GetByte(2) != 49) && (gpt.GetByte(3) != 20) && (gpt.GetByte(4) != 50) && (gpt.GetByte(5) != 41) && (gpt.GetByte(6) != 52) && (gpt.GetByte(7) != 54)) { return(false); } if ((gpt.GetUInt(GPT.Revision) != GPTConstant.SupportedRevision) || (gpt.GetUInt(GPT.HeaderSize) != GPTConstant.HeaderSize) || (gpt.GetUInt(GPT.Reserved) != 0) || (gpt.GetUInt(GPT.PartitionStartingLBA) != 2) ) { return(false); } valid = true; return(valid); }
/// <summary> /// Creates the partition devices. /// </summary> public void CreatePartitionDevices() { // FIXME: Do not create multiple partition devices if this method executed more than once // Find all online disk devices foreach (var device in deviceManager.GetDevices(new IsDiskDevice(), new IsOnline())) { var diskDevice = device as IDiskDevice; var mbr = new MasterBootBlock(diskDevice); if (!mbr.Valid) return; for (uint i = 0; i < MasterBootBlock.MaxMBRPartitions; i++) { if (mbr.Partitions[i].PartitionType != PartitionType.Empty) { deviceManager.Add(new PartitionDevice(diskDevice, mbr.Partitions[i], false)); } } } }
/// <summary> /// Creates the specified options. /// </summary> /// <param name="options">The options.</param> public static void Create(BootImageOptions options) { if (File.Exists(options.DiskImageFileName)) { File.Delete(options.DiskImageFileName); } uint blockCount = options.BlockCount; if (blockCount == 0) { blockCount = 8400 + 1; foreach (var file in options.IncludeFiles) { blockCount += ((uint)file.Content.Length / SectorSize) + 1; } } var diskGeometry = new DiskGeometry(); diskGeometry.GuessGeometry(blockCount); // Create disk image file var diskDevice = new BlockFileStream(options.DiskImageFileName); if (options.ImageFormat == ImageFormat.VDI) { // Create header var header = VDI.CreateHeader( blockCount, options.MediaGuid.ToByteArray(), options.MediaLastSnapGuid.ToByteArray(), diskGeometry ); diskDevice.WriteBlock(0, 1, header); var map = VDI.CreateImageMap(blockCount); diskDevice.WriteBlock(1, (uint)(map.Length / SectorSize), map); diskDevice.BlockOffset = 1 + (uint)(map.Length / 512); } // Expand disk image diskDevice.WriteBlock(blockCount - 1, 1, new byte[SectorSize]); // Create partition device PartitionDevice partitionDevice; if (options.MBROption) { // Create master boot block record var mbr = new MasterBootBlock(diskDevice); // Setup partition entry mbr.DiskSignature = 0x12345678; mbr.Partitions[0].Bootable = true; mbr.Partitions[0].StartLBA = diskGeometry.SectorsPerTrack; mbr.Partitions[0].TotalBlocks = blockCount - mbr.Partitions[0].StartLBA; switch (options.FileSystem) { 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; } mbr.Code = options.MBRCode; mbr.Write(); partitionDevice = new PartitionDevice(diskDevice, mbr.Partitions[0], false); } else { partitionDevice = new PartitionDevice(diskDevice, false); } // Set FAT settings var fatSettings = new FatSettings(); switch (options.FileSystem) { case FileSystem.FAT12: fatSettings.FATType = FatType.FAT12; break; case FileSystem.FAT16: fatSettings.FATType = FatType.FAT16; break; case FileSystem.FAT32: fatSettings.FATType = FatType.FAT32; break; default: break; } fatSettings.FloppyMedia = false; fatSettings.VolumeLabel = options.VolumeLabel; fatSettings.SerialID = new byte[4] { 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); if (!fat.Format(fatSettings)) { throw new Exception("ERROR: Invalid FAT settings"); } fat.SetVolumeName(options.VolumeLabel); foreach (var includeFile in options.IncludeFiles) { var fileAttributes = new FatFileAttributes(); if (includeFile.Archive) fileAttributes |= FatFileAttributes.Archive; if (includeFile.ReadOnly) fileAttributes |= FatFileAttributes.ReadOnly; if (includeFile.Hidden) fileAttributes |= FatFileAttributes.Hidden; if (includeFile.System) fileAttributes |= FatFileAttributes.System; string newname = (Path.GetFileNameWithoutExtension(includeFile.Filename).PadRight(8).Substring(0, 8) + Path.GetExtension(includeFile.Filename).PadRight(4).Substring(1, 3)).ToUpper(); var location = fat.CreateFile(newname, fileAttributes); if (!location.IsValid) throw new Exception("Unable to write file"); var fatFileStream = new FatFileStream(fat, location); fatFileStream.Write(includeFile.Content, 0, includeFile.Content.Length); fatFileStream.Flush(); } if (options.PatchSyslinuxOption) { if (options.BootLoader == BootLoader.Syslinux_6_03) { Syslinux.PatchSyslinux_6_03(partitionDevice, fat); } else if (options.BootLoader == BootLoader.Syslinux_3_72) { Syslinux.PatchSyslinux_3_72(partitionDevice, fat); } } if (options.ImageFormat == ImageFormat.VHD) { // Create footer var footer = VHD.CreateFooter( blockCount, (uint)(DateTime.Now - (new DateTime(2000, 1, 1, 0, 0, 0))).Seconds, options.MediaGuid.ToByteArray(), diskGeometry ); diskDevice.WriteBlock(blockCount, 1, footer); } diskDevice.Dispose(); }
/// <summary> /// Starts this instance. /// </summary> public static void Start() { // Setup hardware abstraction interface IHardwareAbstraction hardwareAbstraction = new Mosa.EmulatedKernel.HardwareAbstraction(); // Set device driver system to the emulator port and memory methods Mosa.DeviceSystem.HAL.SetHardwareAbstraction(hardwareAbstraction); // Start the emulated devices Mosa.EmulatedDevices.Setup.Initialize(); // Initialize the driver system Mosa.DeviceSystem.Setup.Initialize(); // Registry device drivers Mosa.DeviceSystem.Setup.DeviceDriverRegistry.RegisterBuiltInDeviceDrivers(); Mosa.DeviceSystem.Setup.DeviceDriverRegistry.RegisterDeviceDrivers(typeof(Mosa.DeviceDrivers.ISA.CMOS).Module.Assembly); // Set the interrupt handler Mosa.DeviceSystem.HAL.SetInterruptHandler(Mosa.DeviceSystem.Setup.ResourceManager.InterruptManager.ProcessInterrupt); // Start the driver system Mosa.DeviceSystem.Setup.Start(); // Create pci controller manager PCIControllerManager pciControllerManager = new PCIControllerManager(Mosa.DeviceSystem.Setup.DeviceManager); // Create pci controller devices pciControllerManager.CreatePartitionDevices(); // Create synthetic graphic pixel device Mosa.EmulatedDevices.Synthetic.PixelGraphicDevice pixelGraphicDevice = new Mosa.EmulatedDevices.Synthetic.PixelGraphicDevice(Mosa.EmulatedDevices.Setup.PrimaryDisplayForm); // Added the synthetic graphic device to the device drivers Mosa.DeviceSystem.Setup.DeviceManager.Add(pixelGraphicDevice); // Create synthetic ram disk device Mosa.EmulatedDevices.Synthetic.RamDiskDevice ramDiskDevice = new Mosa.EmulatedDevices.Synthetic.RamDiskDevice(1024 * 1024 * 10 / 512); // Add emulated ram disk device to the device drivers Mosa.DeviceSystem.Setup.DeviceManager.Add(ramDiskDevice); // Create disk controller manager DiskControllerManager diskControllerManager = new DiskControllerManager(Mosa.DeviceSystem.Setup.DeviceManager); // Create disk devices from disk controller devices diskControllerManager.CreateDiskDevices(); // Get the text VGA device LinkedList<IDevice> devices = Mosa.DeviceSystem.Setup.DeviceManager.GetDevices(new FindDevice.WithName("VGAText")); // Create a screen interface to the text VGA device ITextScreen screen = new TextScreen((ITextDevice)devices.First.value); // Create synthetic keyboard device Mosa.EmulatedDevices.Synthetic.Keyboard keyboard = new Mosa.EmulatedDevices.Synthetic.Keyboard(Mosa.EmulatedDevices.Setup.PrimaryDisplayForm); // Add the synthetic keyboard device to the device drivers Mosa.DeviceSystem.Setup.DeviceManager.Add(keyboard); // Create master boot block record MasterBootBlock mbr = new MasterBootBlock(ramDiskDevice); mbr.DiskSignature = 0x12345678; mbr.Partitions[0].Bootable = true; mbr.Partitions[0].StartLBA = 17; mbr.Partitions[0].TotalBlocks = ramDiskDevice.TotalBlocks - 17; mbr.Partitions[0].PartitionType = PartitionType.FAT12; mbr.Write(); // Create partition device PartitionDevice partitionDevice = new PartitionDevice(ramDiskDevice, mbr.Partitions[0], false); // Set FAT settings FatSettings fatSettings = new FatSettings(); fatSettings.FATType = FatType.FAT12; fatSettings.FloppyMedia = false; fatSettings.VolumeLabel = "MOSADISK"; fatSettings.SerialID = new byte[4] { 0x01, 0x02, 0x03, 0x04 }; // Create FAT file system FatFileSystem fat12 = new FatFileSystem(partitionDevice); fat12.Format(fatSettings); // Create partition manager PartitionManager partitionManager = new PartitionManager(Mosa.DeviceSystem.Setup.DeviceManager); // Create partition devices partitionManager.CreatePartitionDevices(); // Get a list of all devices devices = Mosa.DeviceSystem.Setup.DeviceManager.GetAllDevices(); // Print them screen.WriteLine("Devices: "); foreach (IDevice device in devices) { screen.Write(device.Name); screen.Write(" ["); switch (device.Status) { case DeviceStatus.Online: screen.Write("Online"); break; case DeviceStatus.Available: screen.Write("Available"); break; case DeviceStatus.Initializing: screen.Write("Initializing"); break; case DeviceStatus.NotFound: screen.Write("Not Found"); break; case DeviceStatus.Error: screen.Write("Error"); break; } screen.Write("]"); if (device.Parent != null) { screen.Write(" - Parent: "); screen.Write(device.Parent.Name); } screen.WriteLine(); if (device is IPartitionDevice) { FileSystem.FAT.FatFileSystem fat = new Mosa.FileSystem.FAT.FatFileSystem(device as IPartitionDevice); screen.Write(" File System: "); if (fat.IsValid) { switch (fat.FATType) { case FatType.FAT12: screen.WriteLine("FAT12"); break; case FatType.FAT16: screen.WriteLine("FAT16"); break; case FatType.FAT32: screen.WriteLine("FAT32"); break; default: screen.WriteLine("Unknown"); break; } screen.WriteLine(" Volume Name: " + fat.VolumeLabel); } else screen.WriteLine("Unknown"); } if (device is PCIDevice) { PCIDevice pciDevice = (device as PCIDevice); screen.Write(" Vendor:0x"); screen.Write(pciDevice.VendorID.ToString("X")); screen.Write(" ["); screen.Write(DeviceTable.Lookup(pciDevice.VendorID)); screen.WriteLine("]"); screen.Write(" Device:0x"); screen.Write(pciDevice.DeviceID.ToString("X")); screen.Write(" Rev:0x"); screen.Write(pciDevice.RevisionID.ToString("X")); screen.Write(" ["); screen.Write(DeviceTable.Lookup(pciDevice.VendorID, pciDevice.DeviceID)); screen.WriteLine("]"); screen.Write(" Class:0x"); screen.Write(pciDevice.ClassCode.ToString("X")); screen.Write(" ["); screen.Write(ClassCodeTable.Lookup(pciDevice.ClassCode)); screen.WriteLine("]"); screen.Write(" SubClass:0x"); screen.Write(pciDevice.SubClassCode.ToString("X")); screen.Write(" ["); screen.Write(SubClassCodeTable.Lookup(pciDevice.ClassCode, pciDevice.SubClassCode, pciDevice.ProgIF)); screen.WriteLine("]"); // screen.Write(" "); // screen.WriteLine(DeviceTable.Lookup(pciDevice.VendorID, pciDevice.DeviceID, pciDevice.SubDeviceID, pciDevice.SubVendorID)); foreach (BaseAddress address in pciDevice.BaseAddresses) { if (address == null) continue; if (address.Address == 0) continue; screen.Write(" "); if (address.Region == AddressType.IO) screen.Write("I/O Port at 0x"); else screen.Write("Memory at 0x"); screen.Write(address.Address.ToString("X")); screen.Write(" [size="); if ((address.Size & 0xFFFFF) == 0) { screen.Write((address.Size >> 20).ToString()); screen.Write("M"); } else if ((address.Size & 0x3FF) == 0) { screen.Write((address.Size >> 10).ToString()); screen.Write("K"); } else screen.Write(address.Size.ToString()); screen.Write("]"); if (address.Prefetchable) screen.Write("(prefetchable)"); screen.WriteLine(); } if (pciDevice.IRQ != 0) { screen.Write(" "); screen.Write("IRQ at "); screen.Write(pciDevice.IRQ.ToString()); screen.WriteLine(); } } } //while (keyboard.GetKeyPressed() == null) ; Mosa.HelloWorld.Boot.Main(); //EmulatorDemo.StartDemo(); return; }
/// <summary> /// Creates the specified options. /// </summary> /// <param name="options">The options.</param> public static void Create(Options options) { if (File.Exists(options.DiskImageFileName)) { File.Delete(options.DiskImageFileName); } uint blockCount = options.BlockCount; if (blockCount == 0) { blockCount = 8400 + 1; foreach (var file in options.IncludeFiles) { blockCount += ((uint)file.Content.Length / 512) + 1; } } var diskGeometry = new Mosa.DeviceSystem.DiskGeometry(); diskGeometry.GuessGeometry(blockCount); // Create disk image file BlockFileStream diskDevice = new BlockFileStream(options.DiskImageFileName); if (options.ImageFormat == ImageFormatType.VDI) { // Create header byte[] header = Mosa.DeviceSystem.VDI.CreateHeader( blockCount, options.MediaGuid.ToByteArray(), options.MediaLastSnapGuid.ToByteArray(), diskGeometry ); diskDevice.WriteBlock(0, 1, header); byte[] map = Mosa.DeviceSystem.VDI.CreateImageMap(blockCount); diskDevice.WriteBlock(1, (uint)(map.Length / 512), map); diskDevice.BlockOffset = 1 + (uint)(map.Length / 512); } // Expand disk image diskDevice.WriteBlock(blockCount - 1, 1, new byte[512]); // Create partition device PartitionDevice partitionDevice; if (options.MBROption) { // Create master boot block record MasterBootBlock mbr = new MasterBootBlock(diskDevice); // Setup partition entry mbr.DiskSignature = 0x12345678; mbr.Partitions[0].Bootable = true; mbr.Partitions[0].StartLBA = diskGeometry.SectorsPerTrack; mbr.Partitions[0].TotalBlocks = blockCount - mbr.Partitions[0].StartLBA; switch (options.FileSystem) { case FileSystemType.FAT12: mbr.Partitions[0].PartitionType = PartitionType.FAT12; break; case FileSystemType.FAT16: mbr.Partitions[0].PartitionType = PartitionType.FAT16; break; case FileSystemType.FAT32: mbr.Partitions[0].PartitionType = PartitionType.FAT32; break; default: break; } mbr.Code = options.MBRCode; mbr.Write(); partitionDevice = new PartitionDevice(diskDevice, mbr.Partitions[0], false); } else { partitionDevice = new PartitionDevice(diskDevice, false); } // Set FAT settings FatSettings fatSettings = new FatSettings(); switch (options.FileSystem) { case FileSystemType.FAT12: fatSettings.FATType = FatType.FAT12; break; case FileSystemType.FAT16: fatSettings.FATType = FatType.FAT16; break; case FileSystemType.FAT32: fatSettings.FATType = FatType.FAT32; break; default: break; } fatSettings.FloppyMedia = false; fatSettings.VolumeLabel = options.VolumeLabel; fatSettings.SerialID = new byte[4] { 0x01, 0x02, 0x03, 0x04 }; fatSettings.SectorsPerTrack = diskGeometry.SectorsPerTrack; fatSettings.NumberOfHeads = diskGeometry.Heads; fatSettings.HiddenSectors = diskGeometry.SectorsPerTrack; fatSettings.OSBootCode = options.FatBootCode; // Create FAT file system FatFileSystem fat = new FatFileSystem(partitionDevice); if (!fat.Format(fatSettings)) { throw new Exception("ERROR: Invalid FAT settings"); } fat.SetVolumeName(options.VolumeLabel); foreach (var includeFile in options.IncludeFiles) { Mosa.FileSystem.FAT.FatFileAttributes fileAttributes = new Mosa.FileSystem.FAT.FatFileAttributes(); if (includeFile.Archive) fileAttributes |= Mosa.FileSystem.FAT.FatFileAttributes.Archive; if (includeFile.ReadOnly) fileAttributes |= Mosa.FileSystem.FAT.FatFileAttributes.ReadOnly; if (includeFile.Hidden) fileAttributes |= Mosa.FileSystem.FAT.FatFileAttributes.Hidden; if (includeFile.System) fileAttributes |= Mosa.FileSystem.FAT.FatFileAttributes.System; //byte[] file = File.ReadAllBytes(includeFile.Filename); string newname = (Path.GetFileNameWithoutExtension(includeFile.Filename).PadRight(8).Substring(0, 8) + Path.GetExtension(includeFile.Filename).PadRight(4).Substring(1, 3)).ToUpper(); FatFileLocation location = fat.CreateFile(newname, fileAttributes, 0); if (!location.Valid) throw new Exception("Unable to write file"); FatFileStream fatFileStream = new FatFileStream(fat, location); fatFileStream.Write(includeFile.Content, 0, includeFile.Content.Length); fatFileStream.Flush(); } if (options.PatchSyslinuxOption) { // Locate ldlinux.sys file for patching string filename = "ldlinux.sys"; string name = (Path.GetFileNameWithoutExtension(filename) + Path.GetExtension(filename).PadRight(4).Substring(0, 4)).ToUpper(); FatFileLocation location = fat.FindEntry(new Mosa.FileSystem.FAT.Find.WithName(name), 0); if (location.Valid) { // Read boot sector Mosa.ClassLib.BinaryFormat bootSector = new Mosa.ClassLib.BinaryFormat(partitionDevice.ReadBlock(0, 1)); // Set the first sector location of the file bootSector.SetUInt(0x1F8, fat.GetSectorByCluster(location.FirstCluster)); // Change jump address bootSector.SetUInt(0x01, 0x58); // Write back patched boot sector partitionDevice.WriteBlock(0, 1, bootSector.Data); // Get the file size & number of sectors used uint fileSize = fat.GetFileSize(location.DirectorySector, location.DirectorySectorIndex); uint sectorCount = (fileSize + 511) >> 9; uint[] sectors = new uint[65]; uint nsec = 0; // Create list of the first 65 sectors of the file for (uint cluster = location.FirstCluster; ((cluster != 0) & (nsec <= 64)); cluster = fat.GetNextCluster(cluster)) { uint sec = fat.GetSectorByCluster(cluster); for (uint s = 0; s < fat.SectorsPerCluster; s++) sectors[nsec++] = sec + s; } // Read the first cluster of the file Mosa.ClassLib.BinaryFormat firstCluster = new Mosa.ClassLib.BinaryFormat(fat.ReadCluster(location.FirstCluster)); uint patchArea = 0; // Search for 0x3EB202FE (magic) for (patchArea = 0; (firstCluster.GetUInt(patchArea) != 0x3EB202FE) && (patchArea < fat.ClusterSizeInBytes); patchArea += 4) ; patchArea = patchArea + 8; if (patchArea < fat.ClusterSizeInBytes) { // Set up the totals firstCluster.SetUShort(patchArea, (ushort)(fileSize >> 2)); firstCluster.SetUShort(patchArea + 2, (ushort)(sectorCount - 1)); // Clear sector entries firstCluster.Fill(patchArea + 8, 0, 64 * 4); // Set sector entries for (nsec = 0; nsec < 64; nsec++) firstCluster.SetUInt(patchArea + 8 + (nsec * 4), sectors[nsec + 1]); // Clear out checksum firstCluster.SetUInt(patchArea + 4, 0); // Write back the updated cluster fat.WriteCluster(location.FirstCluster, firstCluster.Data); // Re-Calculate checksum by opening the file FatFileStream file = new FatFileStream(fat, location); uint csum = 0x3EB202FE; for (uint index = 0; index < (file.Length >> 2); index++) { uint value = (uint)file.ReadByte() | ((uint)file.ReadByte() << 8) | ((uint)file.ReadByte() << 16) | ((uint)file.ReadByte() << 24); csum -= value; } // Set the checksum firstCluster.SetUInt(patchArea + 4, csum); // Write patched cluster back to disk fat.WriteCluster(location.FirstCluster, firstCluster.Data); } } } if (options.ImageFormat == ImageFormatType.VHD) { // Create footer byte[] footer = Mosa.DeviceSystem.VHD.CreateFooter( blockCount, (uint)(DateTime.Now - (new DateTime(2000, 1, 1, 0, 0, 0))).Seconds, options.MediaGuid.ToByteArray(), diskGeometry ); diskDevice.WriteBlock(blockCount, 1, footer); } diskDevice.Dispose(); }
/// <summary> /// Main /// </summary> /// <param name="args">The args.</param> /// <returns></returns> static int Main(string[] args) { Console.WriteLine(); Console.WriteLine("MakeImageBoot v1.0 [www.mosa-project.org]"); Console.WriteLine("Copyright 2010. New BSD License."); Console.WriteLine("Written by Philipp Garcia ([email protected])"); Console.WriteLine(); string mbrFilename = string.Empty; string fatcodeFilename = string.Empty; string volumeLabel = string.Empty; ImageFormat imageFormat = ImageFormat.VHD; bool mbrOption = true; bool patchSyslinuxOption = false; bool floppyMedia = false; uint blockCount = 1024 * 1024 / 512; FileSystem fileSystem = FileSystem.FAT12; List<IncludeFile> includeFiles = new List<IncludeFile>(); bool valid = (args.Length < 2); if (valid) valid = System.IO.File.Exists(args[0]); if (valid) { Console.WriteLine("Usage: CreateBootImage <boot.config file> <image name>"); Console.Error.WriteLine("ERROR: Missing arguments"); return -1; } Console.WriteLine("Building image..."); try { StreamReader reader = File.OpenText(args[0]); while (true) { string line = reader.ReadLine(); if (line == null) break; if (string.IsNullOrEmpty(line)) continue; string[] parts = line.Split('\t'); switch (parts[0].Trim()) { case "-mbr": mbrOption = true; mbrFilename = (parts.Length > 1) ? parts[1] : null; break; case "-boot": fatcodeFilename = (parts.Length > 1) ? parts[1] : null; break; case "-vhd": imageFormat = ImageFormat.VHD; break; case "-img": imageFormat = ImageFormat.IMG; break; case "-vdi": imageFormat = ImageFormat.VDI; break; case "-syslinux": patchSyslinuxOption = true; break; case "-fat12": fileSystem = FileSystem.FAT12; break; case "-fat16": fileSystem = FileSystem.FAT16; break; case "-fat32": fileSystem = FileSystem.FAT32; break; case "-file": if (parts.Length > 2) includeFiles.Add(new IncludeFile(parts[1], parts[2])); else includeFiles.Add(new IncludeFile(parts[1])); break; case "-blocks": blockCount = Convert.ToUInt32(parts[1]); break; case "-volume": volumeLabel = parts[1]; break; case "-floppy": floppyMedia = true; break; default: break; } } reader.Close(); if (System.IO.File.Exists(args[1])) System.IO.File.Delete(args[1]); DiskGeometry diskGeometry = new Mosa.DeviceSystem.DiskGeometry(); diskGeometry.GuessGeometry(blockCount); Console.WriteLine("Disk Geometry CHS = " + diskGeometry.Cylinders + "/" + diskGeometry.Heads + "/" + diskGeometry.SectorsPerTrack); // Create disk image file Mosa.EmulatedDevices.Synthetic.DiskDevice diskDevice = new Mosa.EmulatedDevices.Synthetic.DiskDevice(args[1]); if (imageFormat == ImageFormat.VDI) { // Create header byte[] header = Mosa.DeviceSystem.VDI.CreateHeader( blockCount, Guid.NewGuid().ToByteArray(), Guid.NewGuid().ToByteArray(), diskGeometry ); diskDevice.WriteBlock(0, 1, header); byte[] map = Mosa.DeviceSystem.VDI.CreateImageMap(blockCount); diskDevice.WriteBlock(1, (uint)(map.Length / 512), map); diskDevice.BlockOffset = 1 + (uint)(map.Length / 512); } // Expand disk image diskDevice.WriteBlock(blockCount - 1, 1, new byte[512]); // Create partition device PartitionDevice partitionDevice; if (mbrOption) { // Create master boot block record MasterBootBlock mbr = new MasterBootBlock(diskDevice); // Setup partition entry mbr.DiskSignature = 0x12345678; mbr.Partitions[0].Bootable = true; mbr.Partitions[0].StartLBA = diskGeometry.SectorsPerTrack; mbr.Partitions[0].TotalBlocks = blockCount - mbr.Partitions[0].StartLBA; switch (fileSystem) { 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; } if (!string.IsNullOrEmpty(mbrFilename)) mbr.Code = ReadFile(mbrFilename); mbr.Write(); partitionDevice = new PartitionDevice(diskDevice, mbr.Partitions[0], false); } else { partitionDevice = new PartitionDevice(diskDevice, false); } // Set FAT settings FatSettings fatSettings = new FatSettings(); switch (fileSystem) { case FileSystem.FAT12: fatSettings.FATType = FatType.FAT12; break; case FileSystem.FAT16: fatSettings.FATType = FatType.FAT16; break; case FileSystem.FAT32: fatSettings.FATType = FatType.FAT32; break; default: break; } fatSettings.FloppyMedia = floppyMedia; fatSettings.VolumeLabel = volumeLabel; fatSettings.SerialID = new byte[4] { 0x01, 0x02, 0x03, 0x04 }; fatSettings.SectorsPerTrack = diskGeometry.SectorsPerTrack; fatSettings.NumberOfHeads = diskGeometry.Heads; fatSettings.HiddenSectors = diskGeometry.SectorsPerTrack; if (!string.IsNullOrEmpty(fatcodeFilename)) fatSettings.OSBootCode = ReadFile(fatcodeFilename); // Create FAT file system FatFileSystem fat = new FatFileSystem(partitionDevice); fat.Format(fatSettings); fat.SetVolumeName(volumeLabel); foreach (IncludeFile includeFile in includeFiles) { string filename = includeFile.Filename; Mosa.FileSystem.FAT.FatFileAttributes fileAttributes = new Mosa.FileSystem.FAT.FatFileAttributes(); if (includeFile.Archive) fileAttributes |= Mosa.FileSystem.FAT.FatFileAttributes.Archive; if (includeFile.ReadOnly) fileAttributes |= Mosa.FileSystem.FAT.FatFileAttributes.ReadOnly; if (includeFile.Hidden) fileAttributes |= Mosa.FileSystem.FAT.FatFileAttributes.Hidden; if (includeFile.System) fileAttributes |= Mosa.FileSystem.FAT.FatFileAttributes.System; byte[] file = ReadFile(filename); string newname = (Path.GetFileNameWithoutExtension(includeFile.Newname).PadRight(8).Substring(0, 8) + Path.GetExtension(includeFile.Newname).PadRight(3).Substring(1, 3)).ToUpper(); FatFileLocation location = fat.CreateFile(newname, fileAttributes, 0); if (!location.Valid) throw new Exception("Unable to write file"); FatFileStream fatFileStream = new FatFileStream(fat, location); fatFileStream.Write(file, 0, file.Length); fatFileStream.Flush(); } if (patchSyslinuxOption) { // Locate ldlinux.sys file for patching string filename = "ldlinux.sys"; string name = (Path.GetFileNameWithoutExtension(filename) + Path.GetExtension(filename).PadRight(3).Substring(0, 4)).ToUpper(); FatFileLocation location = fat.FindEntry(new Mosa.FileSystem.FAT.Find.WithName(name), 0); if (location.Valid) { // Read boot sector Mosa.ClassLib.BinaryFormat bootSector = new Mosa.ClassLib.BinaryFormat(partitionDevice.ReadBlock(0, 1)); // Set the first sector location of the file bootSector.SetUInt(0x1F8, fat.GetSectorByCluster(location.FirstCluster)); // Change jump address bootSector.SetUInt(0x01, 0x58); // Write back patched boot sector partitionDevice.WriteBlock(0, 1, bootSector.Data); // Get the file size & number of sectors used uint fileSize = fat.GetFileSize(location.DirectorySector, location.DirectorySectorIndex); uint sectorCount = (fileSize + 511) >> 9; uint[] sectors = new uint[65]; uint nsec = 0; // Create list of the first 65 sectors of the file for (uint cluster = location.FirstCluster; ((cluster != 0) & (nsec <= 64)); cluster = fat.GetNextCluster(cluster)) { uint sec = fat.GetSectorByCluster(cluster); for (uint s = 0; s < fat.SectorsPerCluster; s++) sectors[nsec++] = sec + s; } // Read the first cluster of the file Mosa.ClassLib.BinaryFormat firstCluster = new Mosa.ClassLib.BinaryFormat(fat.ReadCluster(location.FirstCluster)); uint patchArea = 0; // Search for 0x3EB202FE (magic) for (patchArea = 0; (firstCluster.GetUInt(patchArea) != 0x3EB202FE) && (patchArea < fat.ClusterSizeInBytes); patchArea += 4) ; patchArea = patchArea + 8; if (patchArea < fat.ClusterSizeInBytes) { // Set up the totals firstCluster.SetUShort(patchArea, (ushort)(fileSize >> 2)); firstCluster.SetUShort(patchArea + 2, (ushort)(sectorCount - 1)); // Clear sector entries firstCluster.Fill(patchArea + 8, 0, 64 * 4); // Set sector entries for (nsec = 0; nsec < 64; nsec++) firstCluster.SetUInt(patchArea + 8 + (nsec * 4), sectors[nsec + 1]); // Clear out checksum firstCluster.SetUInt(patchArea + 4, 0); // Write back the updated cluster fat.WriteCluster(location.FirstCluster, firstCluster.Data); // Re-Calculate checksum by openning the file FatFileStream file = new FatFileStream(fat, location); uint csum = 0x3EB202FE; for (uint index = 0; index < (file.Length >> 2); index++) { uint value = (uint)file.ReadByte() | ((uint)file.ReadByte() << 8) | ((uint)file.ReadByte() << 16) | ((uint)file.ReadByte() << 24); csum -= value; } // Set the checksum firstCluster.SetUInt(patchArea + 4, csum); // Write patched cluster back to disk fat.WriteCluster(location.FirstCluster, firstCluster.Data); } } } if (imageFormat == ImageFormat.VHD) { // Create footer byte[] footer = Mosa.DeviceSystem.VHD.CreateFooter( blockCount, (uint)(DateTime.Now - (new DateTime(2000, 1, 1, 0, 0, 0))).Seconds, Guid.NewGuid().ToByteArray(), diskGeometry ); diskDevice.WriteBlock(blockCount, 1, footer); } Console.WriteLine("Completed!"); } catch (Exception e) { Console.Error.WriteLine("Error: " + e.ToString()); return -1; } return 0; }
private static void Main(string[] args) { // Create synthetic ram disk device var ramDiskDevice = new RamDiskDevice(1024 * 1024 * 10 / 512); // Create master boot block record var mbr = new MasterBootBlock(ramDiskDevice); mbr.DiskSignature = 0x12345678; mbr.Partitions[0].Bootable = true; mbr.Partitions[0].StartLBA = 17; mbr.Partitions[0].TotalBlocks = ramDiskDevice.TotalBlocks - 17; mbr.Partitions[0].PartitionType = PartitionType.FAT12; mbr.Write(); // Create partition device var partitionDevice = new PartitionDevice(ramDiskDevice, mbr.Partitions[0], false); // Set FAT settings var fatSettings = new FatSettings(); fatSettings.FATType = FatType.FAT12; fatSettings.FloppyMedia = false; fatSettings.VolumeLabel = "MOSADISK"; fatSettings.SerialID = new byte[4] { 0x01, 0x02, 0x03, 0x04 }; // Create FAT file system var fat = new FatFileSystem(partitionDevice); fat.Format(fatSettings); if (fat.IsValid) { switch (fat.FATType) { case FatType.FAT12: Console.WriteLine("FAT12"); break; case FatType.FAT16: Console.WriteLine("FAT16"); break; case FatType.FAT32: Console.WriteLine("FAT32"); break; default: Console.WriteLine("Unknown"); break; } Console.WriteLine(" Volume Name: " + fat.VolumeLabel); } else { Console.WriteLine("Unknown File System"); } var files = new List<IncludeFile>(); files.Add(new IncludeFile("CREDITS.TXT", GetResource("CREDITS.txt"))); files.Add(new IncludeFile("LICENSE.TXT", GetResource("LICENSE.txt"))); foreach (var includeFile in files) { Console.WriteLine("Writing File: " + includeFile.Filename); var fileAttributes = new FatFileAttributes(); if (includeFile.Archive) fileAttributes |= FatFileAttributes.Archive; if (includeFile.ReadOnly) fileAttributes |= FatFileAttributes.ReadOnly; if (includeFile.Hidden) fileAttributes |= FatFileAttributes.Hidden; if (includeFile.System) fileAttributes |= FatFileAttributes.System; string newname = (Path.GetFileNameWithoutExtension(includeFile.Filename).PadRight(8).Substring(0, 8) + Path.GetExtension(includeFile.Filename).PadRight(4).Substring(1, 3)).ToUpper(); var location = fat.CreateFile(newname, fileAttributes); if (!location.IsValid) throw new Exception("Unable to write file"); var fatFileStream = new FatFileStream(fat, location); fatFileStream.Write(includeFile.Content, 0, includeFile.Content.Length); fatFileStream.Flush(); Console.WriteLine(" Source Length: " + includeFile.Content.Length.ToString()); Console.WriteLine(" Stream Length: " + fatFileStream.Length.ToString()); } foreach (var includeFile in files) { Console.WriteLine("Searching File: " + includeFile.Filename); var location = fat.FindEntry(includeFile.Filename); if (location.IsValid) { Console.WriteLine(" Found: " + includeFile.Filename); var fatFileStream = new FatFileStream(fat, location); Console.WriteLine(" Length: " + fatFileStream.Length.ToString()); for (;;) { int i = fatFileStream.ReadByte(); if (i < 0) break; Console.Write((char)i); } Console.WriteLine(); fatFileStream.Position = 0; var buffer = new byte[fatFileStream.Length]; fatFileStream.Read(buffer, 0, (int)fatFileStream.Length); Console.WriteLine(System.Text.Encoding.UTF8.GetString(buffer)); } else { Console.WriteLine(" Not Found: " + includeFile.Filename); } } return; }