GuessGeometry() 공개 메소드

Guesses the geometry.
public GuessGeometry ( ulong lba ) : void
lba ulong The lba.
리턴 void
예제 #1
0
        /// <summary>
        /// Writes the master boot block.
        /// </summary>
        /// <returns></returns>
        public bool Write()
        {
            if (!diskDevice.CanWrite)
            {
                return(false);
            }

            BinaryFormat masterboot = new BinaryFormat(new byte[512]);

            masterboot.SetUInt(MBR.DiskSignature, diskSignature);
            masterboot.SetUShort(MBR.MBRSignature, MBRConstant.MBRSignature);

            if (code != null)
            {
                for (uint index = 0; ((index < MBRConstant.CodeAreaSize) && (index < code.Length)); index++)
                {
                    masterboot.SetByte(index, code[index]);
                }
            }

            for (uint index = 0; index < MaxMBRPartitions; index++)
            {
                if (Partitions[index].TotalBlocks != 0)
                {
                    uint offset = MBR.FirstPartition + (index * 16);
                    masterboot.SetByte(offset + PartitionRecord.Status, (byte)(Partitions[index].Bootable ? 0x80 : 0x00));
                    masterboot.SetByte(offset + PartitionRecord.PartitionType, Partitions[index].PartitionType);
                    masterboot.SetUInt(offset + PartitionRecord.LBA, Partitions[index].StartLBA);
                    masterboot.SetUInt(offset + PartitionRecord.Sectors, Partitions[index].TotalBlocks);

                    DiskGeometry diskGeometry = new DiskGeometry();
                    diskGeometry.GuessGeometry(diskDevice.TotalBlocks);

                    CHS chsStart = new CHS();
                    CHS chsEnd   = new CHS();

                    chsStart.SetCHS(diskGeometry, Partitions[index].StartLBA);
                    chsEnd.SetCHS(diskGeometry, Partitions[index].StartLBA + Partitions[index].TotalBlocks - 1);

                    masterboot.SetByte(offset + PartitionRecord.FirstCRS, chsStart.Head);
                    masterboot.SetByte(offset + PartitionRecord.FirstCRS + 1, (byte)((chsStart.Sector & 0x3F) | ((chsStart.Cylinder >> 8) & 0x03)));
                    masterboot.SetByte(offset + PartitionRecord.FirstCRS + 2, (byte)(chsStart.Cylinder & 0xFF));
                    masterboot.SetByte(offset + PartitionRecord.LastCRS, chsEnd.Head);
                    masterboot.SetByte(offset + PartitionRecord.LastCRS + 1, (byte)((chsEnd.Sector & 0x3F) | ((chsEnd.Cylinder >> 8) & 0x03)));
                    masterboot.SetByte(offset + PartitionRecord.LastCRS + 2, (byte)(chsEnd.Cylinder & 0xFF));
                }
            }

            diskDevice.WriteBlock(0, 1, masterboot.Data);

            return(true);
        }
예제 #2
0
        /// <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();
        }
예제 #3
0
        /// <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();
        }
예제 #4
0
        /// <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;
        }
예제 #5
0
        /// <summary>
        /// Creates the specified options.
        /// </summary>
        /// <param name="options">The options.</param>
        static public 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();
        }
예제 #6
0
        /// <summary>
        /// Writes the master boot block.
        /// </summary>
        /// <returns></returns>
        public bool Write()
        {
            if (!diskDevice.CanWrite) { return false; }

            BinaryFormat masterboot = new BinaryFormat(new byte[512]);

            masterboot.SetUInt(MBR.DiskSignature, diskSignature);
            masterboot.SetUShort(MBR.MBRSignature, MBRConstant.MBRSignature);

            if (code != null)
                for (uint index = 0; ((index < MBRConstant.CodeAreaSize) && (index < code.Length)); index++)
                    masterboot.SetByte(index, code[index]);

            for (uint index = 0; index < MaxMBRPartitions; index++)
                if (Partitions[index].TotalBlocks != 0) {
                    uint offset = MBR.FirstPartition + (index * 16);
                    masterboot.SetByte(offset + PartitionRecord.Status, (byte)(Partitions[index].Bootable ? 0x80 : 0x00));
                    masterboot.SetByte(offset + PartitionRecord.PartitionType, Partitions[index].PartitionType);
                    masterboot.SetUInt(offset + PartitionRecord.LBA, Partitions[index].StartLBA);
                    masterboot.SetUInt(offset + PartitionRecord.Sectors, Partitions[index].TotalBlocks);

                    DiskGeometry diskGeometry = new DiskGeometry();
                    diskGeometry.GuessGeometry(diskDevice.TotalBlocks);

                    CHS chsStart = new CHS();
                    CHS chsEnd = new CHS();

                    chsStart.SetCHS(diskGeometry, Partitions[index].StartLBA);
                    chsEnd.SetCHS(diskGeometry, Partitions[index].StartLBA + Partitions[index].TotalBlocks - 1);

                    masterboot.SetByte(offset + PartitionRecord.FirstCRS, chsStart.Head);
                    masterboot.SetByte(offset + PartitionRecord.FirstCRS + 1, (byte)((chsStart.Sector & 0x3F) | ((chsStart.Cylinder >> 8) & 0x03)));
                    masterboot.SetByte(offset + PartitionRecord.FirstCRS + 2, (byte)(chsStart.Cylinder & 0xFF));
                    masterboot.SetByte(offset + PartitionRecord.LastCRS, chsEnd.Head);
                    masterboot.SetByte(offset + PartitionRecord.LastCRS + 1, (byte)((chsEnd.Sector & 0x3F) | ((chsEnd.Cylinder >> 8) & 0x03)));
                    masterboot.SetByte(offset + PartitionRecord.LastCRS + 2, (byte)(chsEnd.Cylinder & 0xFF));
                }

            diskDevice.WriteBlock(0, 1, masterboot.Data);

            return true;
        }
예제 #7
0
        /// <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);
        }