Exemple #1
0
        static bool GetMinix(IMediaImage imagePlugin, ulong start, ulong divider, ulong sectorOffset, uint sectorSize,
                             out List <Partition> partitions)
        {
            partitions = new List <Partition>();

            byte[] sector = imagePlugin.ReadSector(start);

            GCHandle           handle = GCHandle.Alloc(sector, GCHandleType.Pinned);
            ExtendedBootRecord mnx    =
                (ExtendedBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ExtendedBootRecord));

            handle.Free();

            DicConsole.DebugWriteLine("MBR plugin", "mnx.magic == MBR_Magic = {0}", mnx.magic == MBR_MAGIC);

            if (mnx.magic != MBR_MAGIC)
            {
                return(false);
            }

            bool anyMnx = false;

            foreach (MbrPartitionEntry mnxEntry in mnx.entries)
            {
                bool   mnxValid      = true;
                byte   startSector   = (byte)(mnxEntry.start_sector & 0x3F);
                ushort startCylinder = (ushort)(((mnxEntry.start_sector & 0xC0) << 2) | mnxEntry.start_cylinder);
                byte   endSector     = (byte)(mnxEntry.end_sector & 0x3F);
                ushort endCylinder   = (ushort)(((mnxEntry.end_sector & 0xC0) << 2) | mnxEntry.end_cylinder);
                ulong  mnxStart      = mnxEntry.lba_start;
                ulong  mnxSectors    = mnxEntry.lba_sectors;

                DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.status {0}", mnxEntry.status);
                DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.type {0}", mnxEntry.type);
                DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.lba_start {0}", mnxEntry.lba_start);
                DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.lba_sectors {0}", mnxEntry.lba_sectors);
                DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.start_cylinder {0}", startCylinder);
                DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.start_head {0}", mnxEntry.start_head);
                DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.start_sector {0}", startSector);
                DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.end_cylinder {0}", endCylinder);
                DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.end_head {0}", mnxEntry.end_head);
                DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.end_sector {0}", endSector);

                mnxValid &= mnxEntry.status == 0x00 || mnxEntry.status == 0x80;
                mnxValid &= mnxEntry.type == 0x81 || mnxEntry.type == 0x80;
                mnxValid &= mnxEntry.lba_start != 0 || mnxEntry.lba_sectors != 0 || mnxEntry.start_cylinder != 0 ||
                            mnxEntry.start_head != 0 || mnxEntry.start_sector != 0 || mnxEntry.end_cylinder != 0 ||
                            mnxEntry.end_head != 0 || mnxEntry.end_sector != 0;
                if (mnxEntry.lba_start == 0 && mnxEntry.lba_sectors == 0 && mnxValid)
                {
                    mnxStart = CHS.ToLBA(startCylinder, mnxEntry.start_head, startSector, imagePlugin.Info.Heads,
                                         imagePlugin.Info.SectorsPerTrack);
                    mnxSectors = CHS.ToLBA(endCylinder, mnxEntry.end_head, mnxEntry.end_sector,
                                           imagePlugin.Info.Heads, imagePlugin.Info.SectorsPerTrack) -
                                 mnxStart;
                }

                // For optical media
                mnxStart   /= divider;
                mnxSectors /= divider;

                DicConsole.DebugWriteLine("MBR plugin", "mnx_start {0}", mnxStart);
                DicConsole.DebugWriteLine("MBR plugin", "mnx_sectors {0}", mnxSectors);

                if (!mnxValid)
                {
                    continue;
                }

                Partition part = new Partition();
                if (mnxStart > 0 && mnxSectors > 0)
                {
                    part.Start  = mnxStart + sectorOffset;
                    part.Length = mnxSectors;
                    part.Offset = part.Start * sectorSize;
                    part.Size   = part.Length * sectorSize;
                }
                else
                {
                    mnxValid = false;
                }

                if (!mnxValid)
                {
                    continue;
                }

                anyMnx           = true;
                part.Type        = "MINIX";
                part.Name        = "MINIX";
                part.Description = mnxEntry.status == 0x80 ? "Partition is bootable." : "";
                part.Scheme      = "MINIX";

                partitions.Add(part);
            }

            return(anyMnx);
        }
Exemple #2
0
        public bool GetInformation(IMediaImage imagePlugin, out List <Partition> partitions, ulong sectorOffset)
        {
            ulong counter = 0;

            partitions = new List <Partition>();

            if (imagePlugin.Info.SectorSize < 512)
            {
                return(false);
            }

            uint sectorSize = imagePlugin.Info.SectorSize;
            // Divider of sector size in MBR between real sector size
            ulong divider = 1;

            if (imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc)
            {
                sectorSize = 512;
                divider    = 4;
            }

            byte[] sector = imagePlugin.ReadSector(sectorOffset);

            GCHandle         handle = GCHandle.Alloc(sector, GCHandleType.Pinned);
            MasterBootRecord mbr    =
                (MasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MasterBootRecord));
            TimedMasterBootRecord mbrTime =
                (TimedMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
                                                              typeof(TimedMasterBootRecord));
            SerializedMasterBootRecord mbrSerial =
                (SerializedMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
                                                                   typeof(SerializedMasterBootRecord));
            ModernMasterBootRecord mbrModern =
                (ModernMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
                                                               typeof(ModernMasterBootRecord));
            NecMasterBootRecord mbrNec =
                (NecMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NecMasterBootRecord));
            DiskManagerMasterBootRecord mbrOntrack =
                (DiskManagerMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
                                                                    typeof(DiskManagerMasterBootRecord));

            handle.Free();

            DicConsole.DebugWriteLine("MBR plugin", "xmlmedia = {0}", imagePlugin.Info.XmlMediaType);
            DicConsole.DebugWriteLine("MBR plugin", "mbr.magic = {0:X4}", mbr.magic);

            if (mbr.magic != MBR_MAGIC)
            {
                return(false);                       // Not MBR
            }
            byte[] hdrBytes = imagePlugin.ReadSector(1 + sectorOffset);

            ulong signature = BitConverter.ToUInt64(hdrBytes, 0);

            DicConsole.DebugWriteLine("MBR Plugin", "gpt.signature = 0x{0:X16}", signature);

            if (signature == GPT_MAGIC)
            {
                return(false);
            }

            if (signature != GPT_MAGIC && imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc)
            {
                hdrBytes  = imagePlugin.ReadSector(sectorOffset);
                signature = BitConverter.ToUInt64(hdrBytes, 512);
                DicConsole.DebugWriteLine("MBR Plugin", "gpt.signature @ 0x200 = 0x{0:X16}", signature);
                if (signature == GPT_MAGIC)
                {
                    return(false);
                }
            }

            MbrPartitionEntry[] entries;

            if (mbrOntrack.dm_magic == DM_MAGIC)
            {
                entries = mbrOntrack.entries;
            }
            else if (mbrNec.nec_magic == NEC_MAGIC)
            {
                entries = mbrNec.entries;
            }
            else
            {
                entries = mbr.entries;
            }

            foreach (MbrPartitionEntry entry in entries)
            {
                byte   startSector   = (byte)(entry.start_sector & 0x3F);
                ushort startCylinder = (ushort)(((entry.start_sector & 0xC0) << 2) | entry.start_cylinder);
                byte   endSector     = (byte)(entry.end_sector & 0x3F);
                ushort endCylinder   = (ushort)(((entry.end_sector & 0xC0) << 2) | entry.end_cylinder);
                ulong  lbaStart      = entry.lba_start;
                ulong  lbaSectors    = entry.lba_sectors;

                // Let's start the fun...

                bool valid    = true;
                bool extended = false;
                bool minix    = false;

                if (entry.status != 0x00 && entry.status != 0x80)
                {
                    return(false);                                             // Maybe a FAT filesystem
                }
                valid &= entry.type != 0x00;
                if (entry.type == 0x05 || entry.type == 0x0F || entry.type == 0x15 || entry.type == 0x1F ||
                    entry.type == 0x85 || entry.type == 0x91 || entry.type == 0x9B || entry.type == 0xC5 ||
                    entry.type == 0xCF || entry.type == 0xD5)
                {
                    valid    = false;
                    extended = true;                               // Extended partition
                }
                minix |= entry.type == 0x81 || entry.type == 0x80; // MINIX partition

                valid &= entry.lba_start != 0 || entry.lba_sectors != 0 || entry.start_cylinder != 0 ||
                         entry.start_head != 0 || entry.start_sector != 0 || entry.end_cylinder != 0 ||
                         entry.end_head != 0 || entry.end_sector != 0;
                if (entry.lba_start == 0 && entry.lba_sectors == 0 && valid)
                {
                    lbaStart = CHS.ToLBA(startCylinder, entry.start_head, startSector, imagePlugin.Info.Heads,
                                         imagePlugin.Info.SectorsPerTrack);
                    lbaSectors = CHS.ToLBA(endCylinder, entry.end_head, entry.end_sector, imagePlugin.Info.Heads,
                                           imagePlugin.Info.SectorsPerTrack) - lbaStart;
                }

                // For optical media
                lbaStart   /= divider;
                lbaSectors /= divider;

                if (minix && lbaStart == sectorOffset)
                {
                    minix = false;
                }

                if (lbaStart > imagePlugin.Info.Sectors)
                {
                    valid    = false;
                    extended = false;
                }

                // Some buggy implementations do some rounding errors getting a few sectors beyond device size
                if (lbaStart + lbaSectors > imagePlugin.Info.Sectors)
                {
                    lbaSectors = imagePlugin.Info.Sectors - lbaStart;
                }

                DicConsole.DebugWriteLine("MBR plugin", "entry.status {0}", entry.status);
                DicConsole.DebugWriteLine("MBR plugin", "entry.type {0}", entry.type);
                DicConsole.DebugWriteLine("MBR plugin", "entry.lba_start {0}", entry.lba_start);
                DicConsole.DebugWriteLine("MBR plugin", "entry.lba_sectors {0}", entry.lba_sectors);
                DicConsole.DebugWriteLine("MBR plugin", "entry.start_cylinder {0}", startCylinder);
                DicConsole.DebugWriteLine("MBR plugin", "entry.start_head {0}", entry.start_head);
                DicConsole.DebugWriteLine("MBR plugin", "entry.start_sector {0}", startSector);
                DicConsole.DebugWriteLine("MBR plugin", "entry.end_cylinder {0}", endCylinder);
                DicConsole.DebugWriteLine("MBR plugin", "entry.end_head {0}", entry.end_head);
                DicConsole.DebugWriteLine("MBR plugin", "entry.end_sector {0}", endSector);

                DicConsole.DebugWriteLine("MBR plugin", "entry.minix = {0}", minix);

                DicConsole.DebugWriteLine("MBR plugin", "lba_start {0}", lbaStart);
                DicConsole.DebugWriteLine("MBR plugin", "lba_sectors {0}", lbaSectors);

                if (valid && minix) // Let's mix the fun
                {
                    if (GetMinix(imagePlugin, lbaStart, divider, sectorOffset, sectorSize, out List <Partition> mnxParts))
                    {
                        partitions.AddRange(mnxParts);
                    }
                    else
                    {
                        minix = false;
                    }
                }

                if (valid && !minix)
                {
                    Partition part = new Partition();
                    if ((lbaStart > 0 || imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) &&
                        lbaSectors > 0)
                    {
                        part.Start  = lbaStart + sectorOffset;
                        part.Length = lbaSectors;
                        part.Offset = part.Start * sectorSize;
                        part.Size   = part.Length * sectorSize;
                    }
                    else
                    {
                        valid = false;
                    }

                    if (valid)
                    {
                        part.Type        = $"0x{entry.type:X2}";
                        part.Name        = DecodeMbrType(entry.type);
                        part.Sequence    = counter;
                        part.Description = entry.status == 0x80 ? "Partition is bootable." : "";
                        part.Scheme      = Name;

                        counter++;

                        partitions.Add(part);
                    }
                }

                DicConsole.DebugWriteLine("MBR plugin", "entry.extended = {0}", extended);

                if (!extended)
                {
                    continue;
                }

                bool  processingExtended = true;
                ulong chainStart         = lbaStart;

                while (processingExtended)
                {
                    sector = imagePlugin.ReadSector(lbaStart);

                    handle = GCHandle.Alloc(sector, GCHandleType.Pinned);
                    ExtendedBootRecord ebr =
                        (ExtendedBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
                                                                   typeof(ExtendedBootRecord));
                    handle.Free();

                    DicConsole.DebugWriteLine("MBR plugin", "ebr.magic == MBR_Magic = {0}", ebr.magic == MBR_MAGIC);

                    if (ebr.magic != MBR_MAGIC)
                    {
                        break;
                    }

                    ulong nextStart = 0;

                    foreach (MbrPartitionEntry ebrEntry in ebr.entries)
                    {
                        bool extValid = true;
                        startSector   = (byte)(ebrEntry.start_sector & 0x3F);
                        startCylinder = (ushort)(((ebrEntry.start_sector & 0xC0) << 2) | ebrEntry.start_cylinder);
                        endSector     = (byte)(ebrEntry.end_sector & 0x3F);
                        endCylinder   = (ushort)(((ebrEntry.end_sector & 0xC0) << 2) | ebrEntry.end_cylinder);
                        ulong extStart   = ebrEntry.lba_start;
                        ulong extSectors = ebrEntry.lba_sectors;
                        bool  extMinix   = false;

                        DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.status {0}", ebrEntry.status);
                        DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.type {0}", ebrEntry.type);
                        DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.lba_start {0}", ebrEntry.lba_start);
                        DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.lba_sectors {0}", ebrEntry.lba_sectors);
                        DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.start_cylinder {0}", startCylinder);
                        DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.start_head {0}", ebrEntry.start_head);
                        DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.start_sector {0}", startSector);
                        DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.end_cylinder {0}", endCylinder);
                        DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.end_head {0}", ebrEntry.end_head);
                        DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.end_sector {0}", endSector);

                        // Let's start the fun...
                        extValid &= ebrEntry.status == 0x00 || ebrEntry.status == 0x80;
                        extValid &= ebrEntry.type != 0x00;
                        extValid &= ebrEntry.lba_start != 0 || ebrEntry.lba_sectors != 0 ||
                                    ebrEntry.start_cylinder != 0 || ebrEntry.start_head != 0 ||
                                    ebrEntry.start_sector != 0 || ebrEntry.end_cylinder != 0 ||
                                    ebrEntry.end_head != 0 || ebrEntry.end_sector != 0;
                        if (ebrEntry.lba_start == 0 && ebrEntry.lba_sectors == 0 && extValid)
                        {
                            extStart = CHS.ToLBA(startCylinder, ebrEntry.start_head, startSector,
                                                 imagePlugin.Info.Heads, imagePlugin.Info.SectorsPerTrack);
                            extSectors = CHS.ToLBA(endCylinder, ebrEntry.end_head, ebrEntry.end_sector,
                                                   imagePlugin.Info.Heads, imagePlugin.Info.SectorsPerTrack) -
                                         extStart;
                        }
                        extMinix |= ebrEntry.type == 0x81 || ebrEntry.type == 0x80;

                        // For optical media
                        extStart   /= divider;
                        extSectors /= divider;

                        DicConsole.DebugWriteLine("MBR plugin", "ext_start {0}", extStart);
                        DicConsole.DebugWriteLine("MBR plugin", "ext_sectors {0}", extSectors);

                        if (ebrEntry.type == 0x05 || ebrEntry.type == 0x0F || ebrEntry.type == 0x15 ||
                            ebrEntry.type == 0x1F || ebrEntry.type == 0x85 || ebrEntry.type == 0x91 ||
                            ebrEntry.type == 0x9B || ebrEntry.type == 0xC5 || ebrEntry.type == 0xCF ||
                            ebrEntry.type == 0xD5)
                        {
                            extValid  = false;
                            nextStart = chainStart + extStart;
                        }

                        extStart += lbaStart;
                        extValid &= extStart <= imagePlugin.Info.Sectors;

                        // Some buggy implementations do some rounding errors getting a few sectors beyond device size
                        if (extStart + extSectors > imagePlugin.Info.Sectors)
                        {
                            extSectors = imagePlugin.Info.Sectors - extStart;
                        }

                        if (extValid && extMinix) // Let's mix the fun
                        {
                            if (GetMinix(imagePlugin, lbaStart, divider, sectorOffset, sectorSize,
                                         out List <Partition> mnxParts))
                            {
                                partitions.AddRange(mnxParts);
                            }
                            else
                            {
                                extMinix = false;
                            }
                        }

                        if (!extValid || extMinix)
                        {
                            continue;
                        }

                        Partition part = new Partition();
                        if (extStart > 0 && extSectors > 0)
                        {
                            part.Start  = extStart + sectorOffset;
                            part.Length = extSectors;
                            part.Offset = part.Start * sectorSize;
                            part.Size   = part.Length * sectorSize;
                        }
                        else
                        {
                            extValid = false;
                        }

                        if (!extValid)
                        {
                            continue;
                        }

                        part.Type        = $"0x{ebrEntry.type:X2}";
                        part.Name        = DecodeMbrType(ebrEntry.type);
                        part.Sequence    = counter;
                        part.Description = ebrEntry.status == 0x80 ? "Partition is bootable." : "";
                        part.Scheme      = Name;
                        counter++;

                        partitions.Add(part);
                    }

                    DicConsole.DebugWriteLine("MBR plugin", "next_start {0}", nextStart);
                    processingExtended &= nextStart != 0;
                    processingExtended &= nextStart <= imagePlugin.Info.Sectors;
                    lbaStart            = nextStart;
                }
            }

            // An empty MBR may exist, NeXT creates one and then hardcodes its disklabel
            return(partitions.Count != 0);
        }