Beispiel #1
0
        public static void PatchSyslinux_6_03(PartitionDeviceDriver partitionDevice, FatFileSystem fat)
        {
            // Locate ldlinux.sys file for patching
            string filename = "ldlinux.sys";
            string name     = (Path.GetFileNameWithoutExtension(filename) + Path.GetExtension(filename).PadRight(4).Substring(0, 4)).ToUpper();

            var location = fat.FindEntry(name);

            if (!location.IsValid)
            {
                throw new InvalidProgramException("Unable to find syslinux.sys");
            }

            // Get the file size & number of sectors used
            uint fileSize = fat.GetFileSize(location.DirectorySector, location.DirectorySectorIndex);

            var sectors = new List <uint>();

            // Create list of the sectors of the file
            for (uint cluster = location.FirstCluster; (cluster != 0); cluster = fat.GetNextCluster(cluster))
            {
                uint sec = fat.GetSectorByCluster(cluster);
                for (uint i = 0; i < fat.SectorsPerCluster; i++)
                {
                    sectors.Add(sec + i);
                }
            }

            // Get the ldlinux.sys file stream
            var ldlinux = new FatFileStream(fat, location);

            var ldlinuxReader = new EndianAwareBinaryReader(ldlinux, Endianness.Little);

            // Search for 0x3EB202FE (magic)
            while ((ldlinuxReader.ReadUInt32() != Syslinux.LDLINUX_MAGIC) && (ldlinux.Position < ldlinux.Length))
            {
                ;
            }

            if (ldlinux.Position >= ldlinux.Length || ldlinux.Position <= 0)
            {
                throw new InvalidProgramException("Unable to find patch location for syslinux");
            }

            uint patchArea = (uint)ldlinux.Position - 4;

            // Get Extended Patch Area offset
            ldlinux.Position = patchArea + Syslinux.PatchAreaOffset.EPAOffset;
            ushort epa = ldlinuxReader.ReadUInt16();

            ldlinux.Position = epa + Syslinux.ExtendedPatchAreaOffset.Sect1Ptr0;
            uint sect1Ptr0 = ldlinuxReader.ReadUInt16();

            ldlinux.Position = epa + Syslinux.ExtendedPatchAreaOffset.Sect1Ptr1;
            uint sect1Ptr1 = ldlinuxReader.ReadUInt16();

            ldlinux.Position = epa + Syslinux.ExtendedPatchAreaOffset.SecPtrOffset;
            uint ex = ldlinuxReader.ReadUInt16();

            ldlinux.Position = epa + Syslinux.ExtendedPatchAreaOffset.SecPtrCnt;
            uint nptrs = ldlinuxReader.ReadUInt16();

            ldlinux.Position = epa + Syslinux.ExtendedPatchAreaOffset.AdvPtrOffset;
            uint advptrs = ldlinuxReader.ReadUInt16();

            if (sectors.Count > nptrs)
            {
                throw new InvalidProgramException("Insufficient space for patching syslinux");
            }

            var ldlinuxWriter = new EndianAwareBinaryWriter(ldlinux, Endianness.Little);

            // Set up the totals
            ldlinux.Position = patchArea + Syslinux.PatchAreaOffset.DataSectors;
            ldlinuxWriter.Write((ushort)sectors.Count);

            ldlinux.Position = patchArea + Syslinux.PatchAreaOffset.DataSectors;
            ldlinuxWriter.Write((ushort)2);

            ldlinux.Position = patchArea + Syslinux.PatchAreaOffset.DataSectors;
            ldlinuxWriter.Write(fileSize >> 2);

            // Generate Extents
            var extents = GenerateExtents(sectors);

            ldlinux.Position = ex;

            // Write out extents
            foreach (var extent in extents)
            {
                ldlinuxWriter.Write(extent.Start);
                ldlinuxWriter.Write(extent.Length);
            }

            // Write out ADV
            ldlinux.Position = advptrs;
            ldlinuxWriter.Write((ulong)sectors[sectors.Count - 2]);
            ldlinuxWriter.Write((ulong)sectors[sectors.Count - 1]);

            // Clear out checksum
            ldlinux.Position = patchArea + Syslinux.PatchAreaOffset.Checksum;
            ldlinuxWriter.Write((uint)0);

            // Write back the updated cluster
            ldlinuxWriter.Flush();

            // Re-Calculate checksum
            ldlinux.Position = 0;
            uint csum = Syslinux.LDLINUX_MAGIC;

            for (uint index = 0; index < (ldlinux.Length >> 2); index++)
            {
                csum = csum + ldlinuxReader.ReadUInt32();
            }

            // Set the checksum
            ldlinux.Position = patchArea + Syslinux.PatchAreaOffset.Checksum;
            ldlinuxWriter.Write(csum);

            // Write patched cluster back to disk
            ldlinuxWriter.Flush();

            // Read boot sector
            var fatBootSector = new DataBlock(partitionDevice.ReadBlock(0, 1));

            // Set the first sector location of the file
            fatBootSector.SetUInt(sect1Ptr0, fat.GetSectorByCluster(location.FirstCluster));
            fatBootSector.SetUInt(sect1Ptr1, 0);               // since only 32-bit offsets are support, the high portion of 64-bit value is zero

            // Write back patched boot sector
            partitionDevice.WriteBlock(0, 1, fatBootSector.Data);
        }
Beispiel #2
0
        /// <summary>
        /// Creates the specified options.
        /// </summary>
        /// <param name="options">The options.</param>
        static public 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 diskDeviceDriver = new BlockFileStreamDriver(options.DiskImageFileName);

            var diskDevice = new Device()
            {
                DeviceDriver = diskDeviceDriver
            };

            // Setup device -- required as part of framework in operating system
            diskDeviceDriver.Setup(diskDevice);
            diskDeviceDriver.Initialize();
            diskDeviceDriver.Start();

            if (options.ImageFormat == ImageFormat.VDI)
            {
                // Create header
                var header = VDI.CreateHeader(
                    blockCount,
                    options.MediaGuid.ToByteArray(),
                    options.MediaLastSnapGuid.ToByteArray(),
                    diskGeometry
                    );

                diskDeviceDriver.WriteBlock(0, 1, header);

                var map = VDI.CreateImageMap(blockCount);

                diskDeviceDriver.WriteBlock(1, (uint)(map.Length / SectorSize), map);

                diskDeviceDriver.BlockOffset = 1 + (uint)(map.Length / 512);
            }

            // Expand disk image
            diskDeviceDriver.WriteBlock(blockCount - 1, 1, new byte[SectorSize]);

            // Create partition device driver
            var partitionDevice = new PartitionDeviceDriver();

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

            if (options.MBROption)
            {
                // Create master boot block record
                var mbr = new MasterBootBlock(diskDeviceDriver)
                {
                    // Setup partition entry
                    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();

                configuraiton.StartLBA    = mbr.Partitions[0].StartLBA;
                configuraiton.TotalBlocks = mbr.Partitions[0].TotalBlocks;
            }
            else
            {
                configuraiton.StartLBA    = 0;
                configuraiton.TotalBlocks = diskDeviceDriver.TotalBlocks;
            }

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

            // Setup and initialize
            partitionDevice.Setup(device);
            partitionDevice.Initialize();
            partitionDevice.Start();

            // 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
                    );

                diskDeviceDriver.WriteBlock(blockCount, 1, footer);
            }

            diskDeviceDriver.Dispose();
        }
Beispiel #3
0
        public static void PatchSyslinux_3_72(PartitionDeviceDriver partitionDevice, FatFileSystem fat)
        {
            // Locate ldlinux.sys file for patching
            string filename = "ldlinux.sys";
            string name     = (Path.GetFileNameWithoutExtension(filename) + Path.GetExtension(filename).PadRight(4).Substring(0, 4)).ToUpper();

            var location = fat.FindEntry(name);

            if (location.IsValid)
            {
                // Read boot sector
                var bootSector = new DataBlock(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
                var firstCluster = new DataBlock(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
                    var 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);
                }
            }
        }
Beispiel #4
0
        private static void Main(string[] args)
        {
            // Create synthetic ram disk device
            var ramDiskDevice = new RamDiskDevice(1024 * 1024 * 10 / 512);

            var ramDevice = new Device()
            {
                DeviceDriver = ramDiskDevice
            };

            // Setup device -- required as part of framework in operating system
            ramDiskDevice.Setup(ramDevice);
            ramDiskDevice.Initialize();
            ramDiskDevice.Start();

            // Create master boot block record
            var mbr = new MasterBootBlock(ramDiskDevice)
            {
                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 driver
            var partitionDevice = new PartitionDeviceDriver();

            // Setup partition configuration
            var configuraiton = new DiskPartitionConfiguration()
            {
                StartLBA    = mbr.Partitions[0].StartLBA,
                TotalBlocks = mbr.Partitions[0].TotalBlocks,
                Index       = 0,
                ReadOnly    = false,
            };

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

            // Setup and initialize
            partitionDevice.Setup(device);
            partitionDevice.Initialize();
            partitionDevice.Start();

            // 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)).ToUpperInvariant();
                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;
        }