2016-07-28 18:13:49 +01:00
|
|
|
// /***************************************************************************
|
|
|
|
|
// The Disc Image Chef
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Filename : MBR.cs
|
|
|
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
|
|
|
|
//
|
|
|
|
|
// Component : Partitioning scheme plugins.
|
|
|
|
|
//
|
|
|
|
|
// --[ Description ] ----------------------------------------------------------
|
|
|
|
|
//
|
2017-12-19 03:50:57 +00:00
|
|
|
// Manages Intel/Microsoft MBR (aka Master Boot Record).
|
2016-07-28 18:13:49 +01:00
|
|
|
//
|
|
|
|
|
// --[ License ] --------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// This library is free software; you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU Lesser General Public License as
|
|
|
|
|
// published by the Free Software Foundation; either version 2.1 of the
|
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// This library is distributed in the hope that it will be useful, but
|
|
|
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
// Lesser General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
//
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2017-12-19 03:50:57 +00:00
|
|
|
// Copyright © 2011-2018 Natalia Portillo
|
2016-07-28 18:13:49 +01:00
|
|
|
// ****************************************************************************/
|
2014-04-17 19:58:14 +00:00
|
|
|
|
2011-03-25 10:39:11 +00:00
|
|
|
using System;
|
2014-04-14 02:29:13 +00:00
|
|
|
using System.Collections.Generic;
|
2017-07-24 04:05:38 +01:00
|
|
|
using System.Runtime.InteropServices;
|
2017-07-25 02:47:42 +01:00
|
|
|
using DiscImageChef.CommonTypes;
|
2018-06-25 19:08:16 +01:00
|
|
|
using DiscImageChef.CommonTypes.Enums;
|
|
|
|
|
using DiscImageChef.CommonTypes.Interfaces;
|
2017-07-24 04:05:38 +01:00
|
|
|
using DiscImageChef.Console;
|
2017-12-21 14:30:38 +00:00
|
|
|
using DiscImageChef.Helpers;
|
2011-03-25 10:39:11 +00:00
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
namespace DiscImageChef.Partitions
|
2011-03-25 10:39:11 +00:00
|
|
|
{
|
2017-07-25 02:47:42 +01:00
|
|
|
// TODO: Support AAP extensions
|
2017-12-26 06:05:12 +00:00
|
|
|
public class MBR : IPartition
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2017-12-24 03:11:33 +00:00
|
|
|
const ulong GPT_MAGIC = 0x5452415020494645;
|
|
|
|
|
|
|
|
|
|
const ushort MBR_MAGIC = 0xAA55;
|
|
|
|
|
const ushort NEC_MAGIC = 0xA55A;
|
2018-06-22 08:08:38 +01:00
|
|
|
const ushort DM_MAGIC = 0x55AA;
|
2017-12-24 03:11:33 +00:00
|
|
|
|
|
|
|
|
static readonly string[] MbrTypes =
|
|
|
|
|
{
|
|
|
|
|
// 0x00
|
|
|
|
|
"Empty", "FAT12", "XENIX root", "XENIX /usr",
|
|
|
|
|
// 0x04
|
|
|
|
|
"FAT16 < 32 MiB", "Extended", "FAT16", "IFS (HPFS/NTFS)",
|
|
|
|
|
// 0x08
|
|
|
|
|
"AIX boot, OS/2, Commodore DOS", "AIX data, Coherent, QNX", "Coherent swap, OPUS, OS/2 Boot Manager",
|
|
|
|
|
"FAT32",
|
|
|
|
|
// 0x0C
|
|
|
|
|
"FAT32 (LBA)", "Unknown", "FAT16 (LBA)", "Extended (LBA)",
|
|
|
|
|
// 0x10
|
|
|
|
|
"OPUS", "Hidden FAT12", "Compaq diagnostics, recovery partition", "Unknown",
|
|
|
|
|
// 0x14
|
|
|
|
|
"Hidden FAT16 < 32 MiB, AST-DOS", "Unknown", "Hidden FAT16", "Hidden IFS (HPFS/NTFS)",
|
|
|
|
|
// 0x18
|
|
|
|
|
"AST-Windows swap", "Willowtech Photon coS", "Unknown", "Hidden FAT32",
|
|
|
|
|
// 0x1C
|
|
|
|
|
"Hidden FAT32 (LBA)", "Unknown", "Hidden FAT16 (LBA)", "Unknown",
|
|
|
|
|
// 0x20
|
|
|
|
|
"Willowsoft Overture File System", "Oxygen FSo2", "Oxygen Extended ", "SpeedStor reserved",
|
|
|
|
|
// 0x24
|
|
|
|
|
"NEC-DOS", "Unknown", "SpeedStor reserved", "Hidden NTFS",
|
|
|
|
|
// 0x28
|
|
|
|
|
"Unknown", "Unknown", "Unknown", "Unknown",
|
|
|
|
|
// 0x2C
|
|
|
|
|
"Unknown", "Unknown", "Unknown", "Unknown",
|
|
|
|
|
// 0x30
|
|
|
|
|
"Unknown", "SpeedStor reserved", "Unknown", "SpeedStor reserved",
|
|
|
|
|
// 0x34
|
|
|
|
|
"SpeedStor reserved", "Unknown", "SpeedStor reserved", "Unknown",
|
|
|
|
|
// 0x38
|
|
|
|
|
"Theos", "Plan 9", "Unknown", "Unknown",
|
|
|
|
|
// 0x3C
|
|
|
|
|
"Partition Magic", "Hidden NetWare", "Unknown", "Unknown",
|
|
|
|
|
// 0x40
|
|
|
|
|
"VENIX 80286", "PReP Boot", "Secure File System", "PTS-DOS",
|
|
|
|
|
// 0x44
|
|
|
|
|
"Unknown", "Priam, EUMEL/Elan", "EUMEL/Elan", "EUMEL/Elan",
|
|
|
|
|
// 0x48
|
|
|
|
|
"EUMEL/Elan", "Unknown", "ALFS/THIN lightweight filesystem for DOS", "Unknown",
|
|
|
|
|
// 0x4C
|
|
|
|
|
"Unknown", "QNX 4", "QNX 4", "QNX 4, Oberon",
|
|
|
|
|
// 0x50
|
|
|
|
|
"Ontrack DM, R/O, FAT", "Ontrack DM, R/W, FAT", "CP/M, Microport UNIX", "Ontrack DM 6",
|
|
|
|
|
// 0x54
|
|
|
|
|
"Ontrack DM 6", "EZ-Drive", "Golden Bow VFeature", "Unknown",
|
|
|
|
|
// 0x58
|
|
|
|
|
"Unknown", "Unknown", "Unknown", "Unknown",
|
|
|
|
|
// 0x5C
|
|
|
|
|
"Priam EDISK", "Unknown", "Unknown", "Unknown",
|
|
|
|
|
// 0x60
|
|
|
|
|
"Unknown", "SpeedStor", "Unknown", "GNU Hurd, System V, 386/ix",
|
|
|
|
|
// 0x64
|
|
|
|
|
"NetWare 286", "NetWare", "NetWare 386", "NetWare",
|
|
|
|
|
// 0x68
|
|
|
|
|
"NetWare", "NetWare NSS", "Unknown", "Unknown",
|
|
|
|
|
// 0x6C
|
|
|
|
|
"Unknown", "Unknown", "Unknown", "Unknown",
|
|
|
|
|
// 0x70
|
|
|
|
|
"DiskSecure Multi-Boot", "Unknown", "UNIX 7th Edition", "Unknown",
|
|
|
|
|
// 0x74
|
|
|
|
|
"Unknown", "IBM PC/IX", "Unknown", "Unknown",
|
|
|
|
|
// 0x78
|
|
|
|
|
"Unknown", "Unknown", "Unknown", "Unknown",
|
|
|
|
|
// 0x7C
|
|
|
|
|
"Unknown", "Unknown", "Unknown", "Unknown",
|
|
|
|
|
// 0x80
|
|
|
|
|
"Old MINIX", "MINIX, Old Linux", "Linux swap, Solaris", "Linux",
|
|
|
|
|
// 0x84
|
|
|
|
|
"Hidden by OS/2, APM hibernation", "Linux extended", "NT Stripe Set", "NT Stripe Set",
|
|
|
|
|
// 0x88
|
|
|
|
|
"Linux Plaintext", "Unknown", "Unknown", "Unknown",
|
|
|
|
|
// 0x8C
|
|
|
|
|
"Unknown", "Unknown", "Linux LVM", "Unknown",
|
|
|
|
|
// 0x90
|
|
|
|
|
"Unknown", "Unknown", "Unknown", "Amoeba, Hidden Linux",
|
|
|
|
|
// 0x94
|
|
|
|
|
"Amoeba bad blocks", "Unknown", "Unknown", "Unknown",
|
|
|
|
|
// 0x98
|
|
|
|
|
"Unknown", "Mylex EISA SCSI", "Unknown", "Unknown",
|
|
|
|
|
// 0x9C
|
|
|
|
|
"Unknown", "Unknown", "Unknown", "BSD/OS",
|
|
|
|
|
// 0xA0
|
|
|
|
|
"Hibernation", "HP Volume Expansion", "Unknown", "HP Volume Expansion",
|
|
|
|
|
// 0xA4
|
|
|
|
|
"HP Volume Expansion", "FreeBSD", "OpenBSD", "NeXTStep",
|
|
|
|
|
// 0xA8
|
|
|
|
|
"Apple UFS", "NetBSD", "Olivetti DOS FAT12", "Apple Boot",
|
|
|
|
|
// 0xAC
|
|
|
|
|
"Unknown", "Unknown", "Unknown", "Apple HFS",
|
|
|
|
|
// 0xB0
|
|
|
|
|
"BootStar", "HP Volume Expansion", "Unknown", "HP Volume Expansion",
|
|
|
|
|
// 0xB4
|
|
|
|
|
"HP Volume Expansion", "Unknown", "HP Volume Expansion", "BSDi",
|
|
|
|
|
// 0xB8
|
|
|
|
|
"BSDi swap", "Unknown", "Unknown", "PTS BootWizard",
|
|
|
|
|
// 0xBC
|
|
|
|
|
"Unknown", "Unknown", "Solaris boot", "Solaris",
|
|
|
|
|
// 0xC0
|
|
|
|
|
"Novell DOS, DR-DOS secured", "DR-DOS secured FAT12", "DR-DOS reserved", "DR-DOS reserved",
|
|
|
|
|
// 0xC4
|
|
|
|
|
"DR-DOS secured FAT16 < 32 MiB", "Unknown", "DR-DOS secured FAT16", "Syrinx",
|
|
|
|
|
// 0xC8
|
|
|
|
|
"DR-DOS reserved", "DR-DOS reserved", "DR-DOS reserved", "DR-DOS secured FAT32",
|
|
|
|
|
// 0xCC
|
|
|
|
|
"DR-DOS secured FAT32 (LBA)", "DR-DOS reserved", "DR-DOS secured FAT16 (LBA)",
|
|
|
|
|
"DR-DOS secured extended (LBA)",
|
|
|
|
|
// 0xD0
|
|
|
|
|
"Multiuser DOS secured FAT12", "Multiuser DOS secured FAT12", "Unknown", "Unknown",
|
|
|
|
|
// 0xD4
|
|
|
|
|
"Multiuser DOS secured FAT16 < 32 MiB", "Multiuser DOS secured extended", "Multiuser DOS secured FAT16",
|
|
|
|
|
"Unknown",
|
|
|
|
|
// 0xD8
|
|
|
|
|
"CP/M", "Unknown", "Filesystem-less data", "CP/M, CCP/M, CTOS",
|
|
|
|
|
// 0xDC
|
|
|
|
|
"Unknown", "Unknown", "Dell partition", "BootIt EMBRM",
|
|
|
|
|
// 0xE0
|
|
|
|
|
"Unknown", "SpeedStor", "DOS read/only", "SpeedStor",
|
|
|
|
|
// 0xE4
|
|
|
|
|
"SpeedStor", "Tandy DOS", "SpeedStor", "Unknown",
|
|
|
|
|
// 0xE8
|
|
|
|
|
"Unknown", "Unknown", "Unknown", "BeOS",
|
|
|
|
|
// 0xEC
|
|
|
|
|
"Unknown", "Spryt*x", "Guid Partition Table", "EFI system partition",
|
|
|
|
|
// 0xF0
|
|
|
|
|
"Linux boot", "SpeedStor", "DOS 3.3 secondary, Unisys DOS", "SpeedStor",
|
|
|
|
|
// 0xF4
|
|
|
|
|
"SpeedStor", "Prologue", "SpeedStor", "Unknown",
|
|
|
|
|
// 0xF8
|
|
|
|
|
"Unknown", "Unknown", "Unknown", "VMWare VMFS",
|
|
|
|
|
// 0xFC
|
|
|
|
|
"VMWare VMKCORE", "Linux RAID, FreeDOS", "SpeedStor, LANStep, PS/2 IML", "Xenix bad block"
|
|
|
|
|
};
|
2017-08-07 16:12:08 +01:00
|
|
|
|
2017-12-26 07:28:40 +00:00
|
|
|
public string Name => "Master Boot Record";
|
2018-06-22 08:08:38 +01:00
|
|
|
public Guid Id => new Guid("5E8A34E8-4F1A-59E6-4BF7-7EA647063A76");
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2017-12-26 07:28:40 +00:00
|
|
|
public bool GetInformation(IMediaImage imagePlugin, out List<Partition> partitions, ulong sectorOffset)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
|
|
|
|
ulong counter = 0;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-12-21 14:30:38 +00:00
|
|
|
partitions = new List<Partition>();
|
2011-03-25 10:39:11 +00:00
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
if(imagePlugin.Info.SectorSize < 512) return false;
|
2014-06-07 17:32:14 +01:00
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
uint sectorSize = imagePlugin.Info.SectorSize;
|
2017-07-24 04:05:38 +01:00
|
|
|
// Divider of sector size in MBR between real sector size
|
|
|
|
|
ulong divider = 1;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2017-07-24 04:05:38 +01:00
|
|
|
sectorSize = 512;
|
2018-06-22 08:08:38 +01:00
|
|
|
divider = 4;
|
2017-07-24 04:05:38 +01:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2017-07-24 23:35:33 +01:00
|
|
|
byte[] sector = imagePlugin.ReadSector(sectorOffset);
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2017-07-24 04:05:38 +01:00
|
|
|
GCHandle handle = GCHandle.Alloc(sector, GCHandleType.Pinned);
|
2017-12-19 20:33:03 +00:00
|
|
|
MasterBootRecord mbr =
|
|
|
|
|
(MasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MasterBootRecord));
|
2017-12-24 03:11:33 +00:00
|
|
|
TimedMasterBootRecord mbrTime =
|
2017-12-19 20:33:03 +00:00
|
|
|
(TimedMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
|
|
|
|
|
typeof(TimedMasterBootRecord));
|
2017-12-24 03:11:33 +00:00
|
|
|
SerializedMasterBootRecord mbrSerial =
|
2017-12-19 20:33:03 +00:00
|
|
|
(SerializedMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
|
|
|
|
|
typeof(SerializedMasterBootRecord));
|
2017-12-24 03:11:33 +00:00
|
|
|
ModernMasterBootRecord mbrModern =
|
2017-12-19 20:33:03 +00:00
|
|
|
(ModernMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
|
|
|
|
|
typeof(ModernMasterBootRecord));
|
2017-12-24 03:11:33 +00:00
|
|
|
NecMasterBootRecord mbrNec =
|
2017-12-19 20:33:03 +00:00
|
|
|
(NecMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NecMasterBootRecord));
|
2017-12-24 03:11:33 +00:00
|
|
|
DiskManagerMasterBootRecord mbrOntrack =
|
2017-12-19 20:33:03 +00:00
|
|
|
(DiskManagerMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
|
|
|
|
|
typeof(DiskManagerMasterBootRecord));
|
2017-07-24 04:05:38 +01:00
|
|
|
handle.Free();
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "xmlmedia = {0}", imagePlugin.Info.XmlMediaType);
|
2017-07-24 23:35:33 +01:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "mbr.magic = {0:X4}", mbr.magic);
|
|
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
if(mbr.magic != MBR_MAGIC) return false; // Not MBR
|
2011-03-25 10:39:11 +00:00
|
|
|
|
2017-08-07 16:12:08 +01:00
|
|
|
byte[] hdrBytes = imagePlugin.ReadSector(1 + sectorOffset);
|
|
|
|
|
|
|
|
|
|
ulong signature = BitConverter.ToUInt64(hdrBytes, 0);
|
|
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("MBR Plugin", "gpt.signature = 0x{0:X16}", signature);
|
|
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
if(signature == GPT_MAGIC) return false;
|
2017-08-07 16:12:08 +01:00
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
if(signature != GPT_MAGIC && imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc)
|
2017-08-07 16:12:08 +01:00
|
|
|
{
|
2018-06-22 08:08:38 +01:00
|
|
|
hdrBytes = imagePlugin.ReadSector(sectorOffset);
|
2017-08-07 16:12:08 +01:00
|
|
|
signature = BitConverter.ToUInt64(hdrBytes, 512);
|
|
|
|
|
DicConsole.DebugWriteLine("MBR Plugin", "gpt.signature @ 0x200 = 0x{0:X16}", signature);
|
2017-12-24 03:11:33 +00:00
|
|
|
if(signature == GPT_MAGIC) return false;
|
2017-08-07 16:12:08 +01:00
|
|
|
}
|
|
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
MbrPartitionEntry[] entries;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
if(mbrOntrack.dm_magic == DM_MAGIC) entries = mbrOntrack.entries;
|
2017-12-24 03:11:33 +00:00
|
|
|
else if(mbrNec.nec_magic == NEC_MAGIC) entries = mbrNec.entries;
|
2018-06-22 08:08:38 +01:00
|
|
|
else entries = mbr.entries;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
foreach(MbrPartitionEntry entry in entries)
|
2017-07-24 04:05:38 +01:00
|
|
|
{
|
2018-06-22 08:08:38 +01:00
|
|
|
byte startSector = (byte)(entry.start_sector & 0x3F);
|
2017-12-24 03:11:33 +00:00
|
|
|
ushort startCylinder = (ushort)(((entry.start_sector & 0xC0) << 2) | entry.start_cylinder);
|
2018-06-22 08:08:38 +01:00
|
|
|
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;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
// Let's start the fun...
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
bool valid = true;
|
2014-04-14 01:14:20 +00:00
|
|
|
bool extended = false;
|
2018-06-22 08:08:38 +01:00
|
|
|
bool minix = false;
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if(entry.status != 0x00 && entry.status != 0x80) return false; // Maybe a FAT filesystem
|
|
|
|
|
|
2014-04-14 02:29:13 +00:00
|
|
|
valid &= entry.type != 0x00;
|
2017-12-19 20:33:03 +00:00
|
|
|
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)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2018-06-22 08:08:38 +01:00
|
|
|
valid = false;
|
2014-04-14 01:14:20 +00:00
|
|
|
extended = true; // Extended partition
|
|
|
|
|
}
|
2018-06-22 08:08:38 +01:00
|
|
|
|
2017-07-25 02:47:42 +01:00
|
|
|
minix |= entry.type == 0x81 || entry.type == 0x80; // MINIX partition
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
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;
|
2016-04-19 02:11:47 +01:00
|
|
|
if(entry.lba_start == 0 && entry.lba_sectors == 0 && valid)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2017-12-26 06:05:12 +00:00
|
|
|
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;
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
2011-03-25 10:39:11 +00:00
|
|
|
|
2017-07-24 04:05:38 +01:00
|
|
|
// For optical media
|
2018-06-22 08:08:38 +01:00
|
|
|
lbaStart /= divider;
|
2017-12-24 03:11:33 +00:00
|
|
|
lbaSectors /= divider;
|
2017-07-24 04:05:38 +01:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
if(minix && lbaStart == sectorOffset) minix = false;
|
2017-07-25 15:03:14 +01:00
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
if(lbaStart > imagePlugin.Info.Sectors)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2018-06-22 08:08:38 +01:00
|
|
|
valid = false;
|
2014-04-14 01:14:20 +00:00
|
|
|
extended = false;
|
|
|
|
|
}
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-07-24 04:05:38 +01:00
|
|
|
// Some buggy implementations do some rounding errors getting a few sectors beyond device size
|
2018-06-22 08:08:38 +01:00
|
|
|
if(lbaStart + lbaSectors > imagePlugin.Info.Sectors) lbaSectors = imagePlugin.Info.Sectors - lbaStart;
|
2017-07-24 04:05:38 +01:00
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
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);
|
2017-12-24 03:11:33 +00:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "entry.start_cylinder {0}", startCylinder);
|
2018-06-22 08:08:38 +01:00
|
|
|
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);
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-07-25 02:47:42 +01:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "entry.minix = {0}", minix);
|
|
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "lba_start {0}", lbaStart);
|
2017-12-24 03:11:33 +00:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "lba_sectors {0}", lbaSectors);
|
2017-07-25 15:03:14 +01:00
|
|
|
|
2017-07-25 02:47:42 +01:00
|
|
|
if(valid && minix) // Let's mix the fun
|
2017-12-24 03:11:33 +00:00
|
|
|
if(GetMinix(imagePlugin, lbaStart, divider, sectorOffset, sectorSize, out List<Partition> mnxParts))
|
|
|
|
|
partitions.AddRange(mnxParts);
|
2018-06-22 08:08:38 +01:00
|
|
|
else
|
|
|
|
|
minix = false;
|
2017-07-25 02:47:42 +01:00
|
|
|
|
|
|
|
|
if(valid && !minix)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2017-12-21 14:30:38 +00:00
|
|
|
Partition part = new Partition();
|
2018-06-22 08:08:38 +01:00
|
|
|
if((lbaStart > 0 || imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) && lbaSectors > 0)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2018-06-22 08:08:38 +01:00
|
|
|
part.Start = lbaStart + sectorOffset;
|
2017-12-24 03:11:33 +00:00
|
|
|
part.Length = lbaSectors;
|
2018-06-22 08:08:38 +01:00
|
|
|
part.Offset = part.Start * sectorSize;
|
|
|
|
|
part.Size = part.Length * sectorSize;
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
else valid = false;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
|
|
|
|
if(valid)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2018-06-22 08:08:38 +01:00
|
|
|
part.Type = $"0x{entry.type:X2}";
|
|
|
|
|
part.Name = DecodeMbrType(entry.type);
|
|
|
|
|
part.Sequence = counter;
|
2017-07-19 16:37:11 +01:00
|
|
|
part.Description = entry.status == 0x80 ? "Partition is bootable." : "";
|
2018-06-22 08:08:38 +01:00
|
|
|
part.Scheme = Name;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
counter++;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
partitions.Add(part);
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-07-24 04:05:38 +01:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "entry.extended = {0}", extended);
|
|
|
|
|
|
2017-12-21 06:06:19 +00:00
|
|
|
if(!extended) continue;
|
|
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
bool processingExtended = true;
|
|
|
|
|
ulong chainStart = lbaStart;
|
2017-12-21 06:06:19 +00:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
while(processingExtended)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2017-12-24 03:11:33 +00:00
|
|
|
sector = imagePlugin.ReadSector(lbaStart);
|
2017-12-21 06:06:19 +00:00
|
|
|
|
|
|
|
|
handle = GCHandle.Alloc(sector, GCHandleType.Pinned);
|
|
|
|
|
ExtendedBootRecord ebr =
|
|
|
|
|
(ExtendedBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
|
|
|
|
|
typeof(ExtendedBootRecord));
|
|
|
|
|
handle.Free();
|
|
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "ebr.magic == MBR_Magic = {0}", ebr.magic == MBR_MAGIC);
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
if(ebr.magic != MBR_MAGIC) break;
|
2017-12-21 06:06:19 +00:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
ulong nextStart = 0;
|
2017-12-21 06:06:19 +00:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
foreach(MbrPartitionEntry ebrEntry in ebr.entries)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2017-12-24 03:11:33 +00:00
|
|
|
bool extValid = true;
|
2018-06-22 08:08:38 +01:00
|
|
|
startSector = (byte)(ebrEntry.start_sector & 0x3F);
|
2017-12-24 03:11:33 +00:00
|
|
|
startCylinder = (ushort)(((ebrEntry.start_sector & 0xC0) << 2) | ebrEntry.start_cylinder);
|
2018-06-22 08:08:38 +01:00
|
|
|
endSector = (byte)(ebrEntry.end_sector & 0x3F);
|
|
|
|
|
endCylinder = (ushort)(((ebrEntry.end_sector & 0xC0) << 2) | ebrEntry.end_cylinder);
|
|
|
|
|
ulong extStart = ebrEntry.lba_start;
|
2017-12-24 03:11:33 +00:00
|
|
|
ulong extSectors = ebrEntry.lba_sectors;
|
2018-06-22 08:08:38 +01:00
|
|
|
bool extMinix = false;
|
2017-12-24 03:11:33 +00:00
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
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);
|
2017-12-24 03:11:33 +00:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.start_cylinder {0}", startCylinder);
|
2018-06-22 08:08:38 +01:00
|
|
|
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);
|
2017-12-21 06:06:19 +00:00
|
|
|
|
|
|
|
|
// Let's start the fun...
|
2017-12-24 03:11:33 +00:00
|
|
|
extValid &= ebrEntry.status == 0x00 || ebrEntry.status == 0x80;
|
|
|
|
|
extValid &= ebrEntry.type != 0x00;
|
2018-06-22 08:08:38 +01:00
|
|
|
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;
|
2017-12-24 03:11:33 +00:00
|
|
|
if(ebrEntry.lba_start == 0 && ebrEntry.lba_sectors == 0 && extValid)
|
2017-12-21 06:06:19 +00:00
|
|
|
{
|
2017-12-24 03:11:33 +00:00
|
|
|
extStart = CHS.ToLBA(startCylinder, ebrEntry.start_head, startSector,
|
2017-12-26 06:05:12 +00:00
|
|
|
imagePlugin.Info.Heads, imagePlugin.Info.SectorsPerTrack);
|
2017-12-24 03:11:33 +00:00
|
|
|
extSectors = CHS.ToLBA(endCylinder, ebrEntry.end_head, ebrEntry.end_sector,
|
2018-06-22 08:08:38 +01:00
|
|
|
imagePlugin.Info.Heads, imagePlugin.Info.SectorsPerTrack) - extStart;
|
2017-12-21 06:06:19 +00:00
|
|
|
}
|
2018-06-22 08:08:38 +01:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
extMinix |= ebrEntry.type == 0x81 || ebrEntry.type == 0x80;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-12-21 06:06:19 +00:00
|
|
|
// For optical media
|
2018-06-22 08:08:38 +01:00
|
|
|
extStart /= divider;
|
2017-12-24 03:11:33 +00:00
|
|
|
extSectors /= divider;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "ext_start {0}", extStart);
|
2017-12-24 03:11:33 +00:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "ext_sectors {0}", extSectors);
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
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)
|
2017-12-21 06:06:19 +00:00
|
|
|
{
|
2018-06-22 08:08:38 +01:00
|
|
|
extValid = false;
|
2017-12-24 03:11:33 +00:00
|
|
|
nextStart = chainStart + extStart;
|
2017-12-21 06:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
extStart += lbaStart;
|
2017-12-26 06:05:12 +00:00
|
|
|
extValid &= extStart <= imagePlugin.Info.Sectors;
|
2017-12-21 06:06:19 +00:00
|
|
|
|
|
|
|
|
// Some buggy implementations do some rounding errors getting a few sectors beyond device size
|
2017-12-26 06:05:12 +00:00
|
|
|
if(extStart + extSectors > imagePlugin.Info.Sectors)
|
|
|
|
|
extSectors = imagePlugin.Info.Sectors - extStart;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
if(extValid && extMinix) // Let's mix the fun
|
|
|
|
|
if(GetMinix(imagePlugin, lbaStart, divider, sectorOffset, sectorSize,
|
2018-06-22 08:08:38 +01:00
|
|
|
out List<Partition> mnxParts))
|
|
|
|
|
partitions.AddRange(mnxParts);
|
|
|
|
|
else
|
|
|
|
|
extMinix = false;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
if(!extValid || extMinix) continue;
|
2017-12-21 06:06:19 +00:00
|
|
|
|
|
|
|
|
Partition part = new Partition();
|
2017-12-24 03:11:33 +00:00
|
|
|
if(extStart > 0 && extSectors > 0)
|
2017-07-24 04:05:38 +01:00
|
|
|
{
|
2018-06-22 08:08:38 +01:00
|
|
|
part.Start = extStart + sectorOffset;
|
2017-12-24 03:11:33 +00:00
|
|
|
part.Length = extSectors;
|
2018-06-22 08:08:38 +01:00
|
|
|
part.Offset = part.Start * sectorSize;
|
|
|
|
|
part.Size = part.Length * sectorSize;
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
2017-12-24 03:11:33 +00:00
|
|
|
else extValid = false;
|
2017-12-21 06:06:19 +00:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
if(!extValid) continue;
|
2017-12-21 06:06:19 +00:00
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
part.Type = $"0x{ebrEntry.type:X2}";
|
|
|
|
|
part.Name = DecodeMbrType(ebrEntry.type);
|
|
|
|
|
part.Sequence = counter;
|
2017-12-24 03:11:33 +00:00
|
|
|
part.Description = ebrEntry.status == 0x80 ? "Partition is bootable." : "";
|
2018-06-22 08:08:38 +01:00
|
|
|
part.Scheme = Name;
|
2017-12-21 06:06:19 +00:00
|
|
|
counter++;
|
2017-07-24 04:05:38 +01:00
|
|
|
|
2017-12-21 06:06:19 +00:00
|
|
|
partitions.Add(part);
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
2017-12-21 06:06:19 +00:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "next_start {0}", nextStart);
|
|
|
|
|
processingExtended &= nextStart != 0;
|
2017-12-26 06:05:12 +00:00
|
|
|
processingExtended &= nextStart <= imagePlugin.Info.Sectors;
|
2018-06-22 08:08:38 +01:00
|
|
|
lbaStart = nextStart;
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
// An empty MBR may exist, NeXT creates one and then hardcodes its disklabel
|
2014-04-14 02:29:13 +00:00
|
|
|
return partitions.Count != 0;
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
static bool GetMinix(IMediaImage imagePlugin, ulong start, ulong divider, ulong sectorOffset,
|
|
|
|
|
uint sectorSize,
|
2017-12-19 20:33:03 +00:00
|
|
|
out List<Partition> partitions)
|
2017-07-25 02:47:42 +01:00
|
|
|
{
|
|
|
|
|
partitions = new List<Partition>();
|
|
|
|
|
|
2017-07-25 15:03:14 +01:00
|
|
|
byte[] sector = imagePlugin.ReadSector(start);
|
2017-07-25 02:47:42 +01:00
|
|
|
|
|
|
|
|
GCHandle handle = GCHandle.Alloc(sector, GCHandleType.Pinned);
|
2017-12-19 20:33:03 +00:00
|
|
|
ExtendedBootRecord mnx =
|
|
|
|
|
(ExtendedBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ExtendedBootRecord));
|
2017-07-25 02:47:42 +01:00
|
|
|
handle.Free();
|
|
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "mnx.magic == MBR_Magic = {0}", mnx.magic == MBR_MAGIC);
|
2017-07-25 02:47:42 +01:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
if(mnx.magic != MBR_MAGIC) return false;
|
2017-07-25 02:47:42 +01:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
bool anyMnx = false;
|
2017-07-25 02:47:42 +01:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
foreach(MbrPartitionEntry mnxEntry in mnx.entries)
|
2017-07-25 02:47:42 +01:00
|
|
|
{
|
2018-06-22 08:08:38 +01:00
|
|
|
bool mnxValid = true;
|
|
|
|
|
byte startSector = (byte)(mnxEntry.start_sector & 0x3F);
|
2017-12-24 03:11:33 +00:00
|
|
|
ushort startCylinder = (ushort)(((mnxEntry.start_sector & 0xC0) << 2) | mnxEntry.start_cylinder);
|
2018-06-22 08:08:38 +01:00
|
|
|
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);
|
2017-12-24 03:11:33 +00:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.start_cylinder {0}", startCylinder);
|
2018-06-22 08:08:38 +01:00
|
|
|
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);
|
2017-12-24 03:11:33 +00:00
|
|
|
|
|
|
|
|
mnxValid &= mnxEntry.status == 0x00 || mnxEntry.status == 0x80;
|
2018-06-22 08:08:38 +01:00
|
|
|
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;
|
2017-12-24 03:11:33 +00:00
|
|
|
if(mnxEntry.lba_start == 0 && mnxEntry.lba_sectors == 0 && mnxValid)
|
2017-07-25 02:47:42 +01:00
|
|
|
{
|
2017-12-26 06:05:12 +00:00
|
|
|
mnxStart = CHS.ToLBA(startCylinder, mnxEntry.start_head, startSector, imagePlugin.Info.Heads,
|
|
|
|
|
imagePlugin.Info.SectorsPerTrack);
|
2018-06-22 08:08:38 +01:00
|
|
|
mnxSectors = CHS.ToLBA(endCylinder, mnxEntry.end_head, mnxEntry.end_sector, imagePlugin.Info.Heads,
|
|
|
|
|
imagePlugin.Info.SectorsPerTrack) - mnxStart;
|
2017-07-25 02:47:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For optical media
|
2018-06-22 08:08:38 +01:00
|
|
|
mnxStart /= divider;
|
2017-12-24 03:11:33 +00:00
|
|
|
mnxSectors /= divider;
|
2017-07-25 15:03:14 +01:00
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "mnx_start {0}", mnxStart);
|
2017-12-24 03:11:33 +00:00
|
|
|
DicConsole.DebugWriteLine("MBR plugin", "mnx_sectors {0}", mnxSectors);
|
2017-07-25 02:47:42 +01:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
if(!mnxValid) continue;
|
2017-12-21 06:06:19 +00:00
|
|
|
|
2017-12-21 14:30:38 +00:00
|
|
|
Partition part = new Partition();
|
2017-12-24 03:11:33 +00:00
|
|
|
if(mnxStart > 0 && mnxSectors > 0)
|
2017-07-25 02:47:42 +01:00
|
|
|
{
|
2018-06-22 08:08:38 +01:00
|
|
|
part.Start = mnxStart + sectorOffset;
|
2017-12-24 03:11:33 +00:00
|
|
|
part.Length = mnxSectors;
|
2018-06-22 08:08:38 +01:00
|
|
|
part.Offset = part.Start * sectorSize;
|
|
|
|
|
part.Size = part.Length * sectorSize;
|
2017-12-21 06:06:19 +00:00
|
|
|
}
|
2017-12-24 03:11:33 +00:00
|
|
|
else mnxValid = false;
|
2017-07-25 02:47:42 +01:00
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
if(!mnxValid) continue;
|
2017-07-25 02:47:42 +01:00
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
anyMnx = true;
|
|
|
|
|
part.Type = "MINIX";
|
|
|
|
|
part.Name = "MINIX";
|
2017-12-24 03:11:33 +00:00
|
|
|
part.Description = mnxEntry.status == 0x80 ? "Partition is bootable." : "";
|
2018-06-22 08:08:38 +01:00
|
|
|
part.Scheme = "MINIX";
|
2017-12-21 06:06:19 +00:00
|
|
|
|
|
|
|
|
partitions.Add(part);
|
2017-07-25 02:47:42 +01:00
|
|
|
}
|
|
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
return anyMnx;
|
2017-07-25 02:47:42 +01:00
|
|
|
}
|
|
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
static string DecodeMbrType(byte type)
|
2017-12-19 20:33:03 +00:00
|
|
|
{
|
2017-12-24 03:11:33 +00:00
|
|
|
return MbrTypes[type];
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
2012-08-07 06:20:13 +00:00
|
|
|
|
2017-07-24 04:05:38 +01:00
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
2017-12-20 02:08:37 +00:00
|
|
|
struct MasterBootRecord
|
2017-07-24 04:05:38 +01:00
|
|
|
{
|
|
|
|
|
/// <summary>Boot code</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 446)]
|
|
|
|
|
public byte[] boot_code;
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Partitions</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
|
|
|
|
public MbrPartitionEntry[] entries;
|
2017-12-24 03:11:33 +00:00
|
|
|
/// <summary>
|
|
|
|
|
/// <see cref="MBR.MBR_MAGIC" />
|
|
|
|
|
/// </summary>
|
2017-07-24 04:05:38 +01:00
|
|
|
public ushort magic;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: IBM Boot Manager
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
2017-12-20 02:08:37 +00:00
|
|
|
struct ExtendedBootRecord
|
2017-07-24 04:05:38 +01:00
|
|
|
{
|
|
|
|
|
/// <summary>Boot code, almost always unused</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 446)]
|
|
|
|
|
public byte[] boot_code;
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Partitions or pointers</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
|
|
|
|
public MbrPartitionEntry[] entries;
|
2017-12-24 03:11:33 +00:00
|
|
|
/// <summary>
|
|
|
|
|
/// <see cref="MBR.MBR_MAGIC" />
|
|
|
|
|
/// </summary>
|
2017-07-24 04:05:38 +01:00
|
|
|
public ushort magic;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
2017-12-20 02:08:37 +00:00
|
|
|
struct TimedMasterBootRecord
|
2017-07-24 04:05:38 +01:00
|
|
|
{
|
|
|
|
|
/// <summary>Boot code</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 218)]
|
|
|
|
|
public byte[] boot_code;
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Set to 0</summary>
|
|
|
|
|
public ushort zero;
|
|
|
|
|
/// <summary>Original physical drive</summary>
|
|
|
|
|
public byte drive;
|
|
|
|
|
/// <summary>Disk timestamp, seconds</summary>
|
|
|
|
|
public byte seconds;
|
|
|
|
|
/// <summary>Disk timestamp, minutes</summary>
|
|
|
|
|
public byte minutes;
|
|
|
|
|
/// <summary>Disk timestamp, hours</summary>
|
|
|
|
|
public byte hours;
|
|
|
|
|
/// <summary>Boot code, continuation</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 222)]
|
|
|
|
|
public byte[] boot_code2;
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Partitions</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
|
|
|
|
public MbrPartitionEntry[] entries;
|
2017-12-24 03:11:33 +00:00
|
|
|
/// <summary>
|
|
|
|
|
/// <see cref="MBR.MBR_MAGIC" />
|
|
|
|
|
/// </summary>
|
2017-07-24 04:05:38 +01:00
|
|
|
public ushort magic;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
2017-12-20 02:08:37 +00:00
|
|
|
struct SerializedMasterBootRecord
|
2017-07-24 04:05:38 +01:00
|
|
|
{
|
|
|
|
|
/// <summary>Boot code</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 440)]
|
|
|
|
|
public byte[] boot_code;
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Disk serial number</summary>
|
|
|
|
|
public uint serial;
|
|
|
|
|
/// <summary>Set to 0</summary>
|
|
|
|
|
public ushort zero;
|
|
|
|
|
/// <summary>Partitions</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
|
|
|
|
public MbrPartitionEntry[] entries;
|
2017-12-24 03:11:33 +00:00
|
|
|
/// <summary>
|
|
|
|
|
/// <see cref="MBR.MBR_MAGIC" />
|
|
|
|
|
/// </summary>
|
2017-07-24 04:05:38 +01:00
|
|
|
public ushort magic;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
2017-12-20 02:08:37 +00:00
|
|
|
struct ModernMasterBootRecord
|
2017-07-24 04:05:38 +01:00
|
|
|
{
|
|
|
|
|
/// <summary>Boot code</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 218)]
|
|
|
|
|
public byte[] boot_code;
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Set to 0</summary>
|
|
|
|
|
public ushort zero;
|
|
|
|
|
/// <summary>Original physical drive</summary>
|
|
|
|
|
public byte drive;
|
|
|
|
|
/// <summary>Disk timestamp, seconds</summary>
|
|
|
|
|
public byte seconds;
|
|
|
|
|
/// <summary>Disk timestamp, minutes</summary>
|
|
|
|
|
public byte minutes;
|
|
|
|
|
/// <summary>Disk timestamp, hours</summary>
|
|
|
|
|
public byte hours;
|
|
|
|
|
/// <summary>Boot code, continuation</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 216)]
|
|
|
|
|
public byte[] boot_code2;
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Disk serial number</summary>
|
|
|
|
|
public uint serial;
|
|
|
|
|
/// <summary>Set to 0</summary>
|
|
|
|
|
public ushort zero2;
|
|
|
|
|
/// <summary>Partitions</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
|
|
|
|
public MbrPartitionEntry[] entries;
|
2017-12-24 03:11:33 +00:00
|
|
|
/// <summary>
|
|
|
|
|
/// <see cref="MBR.MBR_MAGIC" />
|
|
|
|
|
/// </summary>
|
2017-07-24 04:05:38 +01:00
|
|
|
public ushort magic;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
2017-12-20 02:08:37 +00:00
|
|
|
struct NecMasterBootRecord
|
2017-07-24 04:05:38 +01:00
|
|
|
{
|
|
|
|
|
/// <summary>Boot code</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 380)]
|
|
|
|
|
public byte[] boot_code;
|
2017-12-24 03:11:33 +00:00
|
|
|
/// <summary>
|
|
|
|
|
/// <see cref="MBR.NEC_MAGIC" />
|
|
|
|
|
/// </summary>
|
2017-07-24 04:05:38 +01:00
|
|
|
public ushort nec_magic;
|
|
|
|
|
/// <summary>Partitions</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
|
|
|
|
public MbrPartitionEntry[] entries;
|
2017-12-24 03:11:33 +00:00
|
|
|
/// <summary>
|
|
|
|
|
/// <see cref="MBR.MBR_MAGIC" />
|
|
|
|
|
/// </summary>
|
2017-07-24 04:05:38 +01:00
|
|
|
public ushort magic;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
2017-12-20 02:08:37 +00:00
|
|
|
struct DiskManagerMasterBootRecord
|
2017-07-24 04:05:38 +01:00
|
|
|
{
|
|
|
|
|
/// <summary>Boot code</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 252)]
|
|
|
|
|
public byte[] boot_code;
|
2017-12-24 03:11:33 +00:00
|
|
|
/// <summary>
|
|
|
|
|
/// <see cref="MBR.DM_MAGIC" />
|
|
|
|
|
/// </summary>
|
2017-07-24 04:05:38 +01:00
|
|
|
public ushort dm_magic;
|
|
|
|
|
/// <summary>Partitions</summary>
|
2018-06-22 08:08:38 +01:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
|
|
|
|
public MbrPartitionEntry[] entries;
|
2017-12-24 03:11:33 +00:00
|
|
|
/// <summary>
|
|
|
|
|
/// <see cref="MBR.MBR_MAGIC" />
|
|
|
|
|
/// </summary>
|
2017-07-24 04:05:38 +01:00
|
|
|
public ushort magic;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
2017-12-24 03:11:33 +00:00
|
|
|
struct MbrPartitionEntry
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Partition status, 0x80 or 0x00, else invalid</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public byte status;
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Starting head [0,254]</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public byte start_head;
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Starting sector [1,63]</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public byte start_sector;
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Starting cylinder [0,1023]</summary>
|
|
|
|
|
public byte start_cylinder;
|
|
|
|
|
/// <summary>Partition type</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public byte type;
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Ending head [0,254]</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public byte end_head;
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Ending sector [1,63]</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public byte end_sector;
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Ending cylinder [0,1023]</summary>
|
|
|
|
|
public byte end_cylinder;
|
|
|
|
|
/// <summary>Starting absolute sector</summary>
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint lba_start;
|
2017-07-24 04:05:38 +01:00
|
|
|
/// <summary>Total sectors</summary>
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint lba_sectors;
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-03-25 10:39:11 +00:00
|
|
|
}
|