From 6b8779e75a2101fa09d0d60325b9f111af247c0d Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sun, 30 Jul 2017 15:53:42 +0100 Subject: [PATCH] Added support for pre-VTOC Sun disklabel (used in sun1/sun2/sun3 ???), added support for 16 entries VTOC (used in i86pc) and corrected structures for 8 entries VTOC (used in sun4). --- DiscImageChef.Partitions/Sun.cs | 828 +++++++++++++++++++++----------- 1 file changed, 538 insertions(+), 290 deletions(-) diff --git a/DiscImageChef.Partitions/Sun.cs b/DiscImageChef.Partitions/Sun.cs index ca3f4ac3..1e84f775 100644 --- a/DiscImageChef.Partitions/Sun.cs +++ b/DiscImageChef.Partitions/Sun.cs @@ -39,10 +39,35 @@ namespace DiscImageChef.PartPlugins { public class SunDisklabel : PartPlugin { - const ushort SUN_MAGIC = 0xDABE; - const uint VTOC_MAGIC = 0x600DDEEE; + /// Sun disklabel magic number + const ushort DKL_MAGIC = 0xDABE; + /// Sun VTOC magic number + const uint VTOC_SANE = 0x600DDEEE; + /// Sun disklabel magic number, byte-swapped + const ushort DKL_CIGAM = 0xBEDA; + /// Sun VTOC magic number, byte-swapped + const uint VTOC_ENAS = 0xEEDE0D60; + /// # of logical partitions + const int NDKMAP = 8; + /// # of logical partitions + const int NDKMAP16 = 16; + /// Disk label size + const int DK_LABEL_SIZE = 512; + /// Volume label size + const int LEN_DKL_ASCII = 128; + /// Length of v_volume + const int LEN_DKL_VVOL = 8; + /// Size of padding in SunOS disk label + const int LEN_DKL_PAD = DK_LABEL_SIZE - (LEN_DKL_ASCII + NDKMAP * 8 + 14 * 2); + /// Size of padding in Solaris disk label with 8 partitions + const int LEN_DKL_PAD8 = DK_LABEL_SIZE - (LEN_DKL_ASCII + + 136 + // sizeof(dk_vtoc8) + (NDKMAP * 8) + 14 * 2 + 2 * 2); + const int LEN_DKL_PAD16 = DK_LABEL_SIZE - + (456 + // sizeof(dk_vtoc16) + 4 * 4 + 12 * 2 + 2 * 2); - public enum SunTypes : ushort + public enum SunTag : ushort { SunEmpty = 0x0000, SunBoot = 0x0001, @@ -55,6 +80,7 @@ namespace DiscImageChef.PartPlugins SunHome = 0x0008, SunAlt = 0x0009, SunCache = 0x000A, + SunReserved = 0x000B, VxVmPublic = 0x000E, VxVmPrivate = 0x000F, LinuxSwap = 0x0082, @@ -89,148 +115,283 @@ namespace DiscImageChef.PartPlugins if(imagePlugin.GetSectorSize() < 512) return false; + bool useDkl = false, useDkl8 = false, useDkl16 = false; + byte[] sunSector = imagePlugin.ReadSector(sectorOffset); - byte[] tmpString; - SunDiskLabel sdl = new SunDiskLabel + + GCHandle handle = GCHandle.Alloc(sunSector, GCHandleType.Pinned); + dk_label dkl = (dk_label)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(dk_label)); + dk_label8 dkl8 = (dk_label8)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(dk_label8)); + dk_label16 dkl16 = (dk_label16)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(dk_label16)); + handle.Free(); + + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_magic = 0x{0:X4}", dkl.dkl_magic); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_sanity = 0x{0:X8}", dkl8.dkl_vtoc.v_sanity); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_sanity = 0x{0:X8}", dkl16.dkl_vtoc.v_sanity); + + + if(dkl.dkl_magic == DKL_MAGIC || dkl.dkl_magic == DKL_CIGAM) { - spare = new byte[148], - vtoc = new SunVTOC - { - infos = new SunInfo[8], - bootinfo = new uint[3], - reserved = new byte[40], - timestamp = new uint[8] - }, - partitions = new SunPartition[8] - }; - BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; - - tmpString = new byte[128]; - Array.Copy(sunSector, 0, tmpString, 0, 128); - sdl.info = StringHandlers.CToString(tmpString); - sdl.vtoc.version = BigEndianBitConverter.ToUInt32(sunSector, 0x80 + 0x00); - - tmpString = new byte[8]; - Array.Copy(sunSector, 0x80 + 0x04, tmpString, 0, 8); - sdl.vtoc.volname = StringHandlers.CToString(tmpString); - sdl.vtoc.nparts = BigEndianBitConverter.ToUInt16(sunSector, 0x80 + 0x0C); - for(int i = 0; i < 8; i++) - { - sdl.vtoc.infos[i] = new SunInfo - { - id = BigEndianBitConverter.ToUInt16(sunSector, 0x80 + 0x0E + i * 4 + 0x00), - flags = BigEndianBitConverter.ToUInt16(sunSector, 0x80 + 0x0E + i * 4 + 0x02) - }; - } - sdl.vtoc.padding = BigEndianBitConverter.ToUInt16(sunSector, 0x80 + 0x2E); - for(int i = 0; i < 3; i++) - sdl.vtoc.bootinfo[i] = BigEndianBitConverter.ToUInt32(sunSector, 0x80 + 0x30 + i * 4); - sdl.vtoc.sanity = BigEndianBitConverter.ToUInt32(sunSector, 0x80 + 0x3C); - Array.Copy(sunSector, 0x80 + 0x40, sdl.vtoc.reserved, 0, 40); - for(int i = 0; i < 8; i++) - sdl.vtoc.timestamp[i] = BigEndianBitConverter.ToUInt32(sunSector, 0x80 + 0x68 + i * 4); - - sdl.write_reinstruct = BigEndianBitConverter.ToUInt32(sunSector, 0x108); - sdl.read_reinstruct = BigEndianBitConverter.ToUInt32(sunSector, 0x10C); - Array.Copy(sunSector, 0x110, sdl.spare, 0, 148); - sdl.rspeed = BigEndianBitConverter.ToUInt16(sunSector, 0x1A4); - sdl.pcylcount = BigEndianBitConverter.ToUInt16(sunSector, 0x1A6); - sdl.sparecyl = BigEndianBitConverter.ToUInt16(sunSector, 0x1A8); - sdl.gap1 = BigEndianBitConverter.ToUInt16(sunSector, 0x1AA); - sdl.gap2 = BigEndianBitConverter.ToUInt16(sunSector, 0x1AC); - sdl.ilfact = BigEndianBitConverter.ToUInt16(sunSector, 0x1AE); - sdl.ncyl = BigEndianBitConverter.ToUInt16(sunSector, 0x1B0); - sdl.nacyl = BigEndianBitConverter.ToUInt16(sunSector, 0x1B2); - sdl.ntrks = BigEndianBitConverter.ToUInt16(sunSector, 0x1B4); - sdl.nsect = BigEndianBitConverter.ToUInt16(sunSector, 0x1B6); - sdl.bhead = BigEndianBitConverter.ToUInt16(sunSector, 0x1B8); - sdl.ppart = BigEndianBitConverter.ToUInt16(sunSector, 0x1BA); - - for(int i = 0; i < 8; i++) - { - sdl.partitions[i] = new SunPartition - { - start_cylinder = BigEndianBitConverter.ToUInt32(sunSector, 0x1BC + i * 8 + 0x00), - num_sectors = BigEndianBitConverter.ToUInt32(sunSector, 0x1BC + i * 8 + 0x04) - }; + if(dkl16.dkl_vtoc.v_sanity == VTOC_SANE || dkl16.dkl_vtoc.v_sanity == VTOC_ENAS) + useDkl16 = true; + else if(dkl8.dkl_vtoc.v_sanity == VTOC_SANE || dkl8.dkl_vtoc.v_sanity == VTOC_ENAS) + useDkl8 = true; + else + useDkl = true; } - sdl.magic = BigEndianBitConverter.ToUInt16(sunSector, 0x1FC); - sdl.csum = BigEndianBitConverter.ToUInt16(sunSector, 0x1FE); - - ushort csum = 0; - for(int i = 0; i < 510; i += 2) - csum ^= BigEndianBitConverter.ToUInt16(sunSector, i); - - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.info = {0}", sdl.info); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.vtoc.version = {0}", sdl.vtoc.version); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.vtoc.volname = {0}", sdl.vtoc.volname); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.vtoc.nparts = {0}", sdl.vtoc.nparts); - for(int i = 0; i < 8; i++) + if(!useDkl && !useDkl8 && !useDkl16) { - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.vtoc.infos[{1}].id = 0x{0:X4}", sdl.vtoc.infos[i].id, i); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.vtoc.infos[{1}].flags = 0x{0:X4}", sdl.vtoc.infos[i].flags, i); - } - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.vtoc.padding = 0x{0:X4}", sdl.vtoc.padding); - for(int i = 0; i < 3; i++) - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.vtoc.bootinfo[{1}].id = 0x{0:X8}", sdl.vtoc.bootinfo[i], i); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.vtoc.sanity = 0x{0:X8}", sdl.vtoc.sanity); - for(int i = 0; i < 8; i++) - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.vtoc.timestamp[{1}] = 0x{0:X8}", sdl.vtoc.timestamp[i], i); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.rspeed = {0}", sdl.rspeed); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.pcylcount = {0}", sdl.pcylcount); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.sparecyl = {0}", sdl.sparecyl); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.gap1 = {0}", sdl.gap1); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.gap2 = {0}", sdl.gap2); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.ilfact = {0}", sdl.ilfact); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.ncyl = {0}", sdl.ncyl); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.nacyl = {0}", sdl.nacyl); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.ntrks = {0}", sdl.ntrks); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.nsect = {0}", sdl.nsect); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.bhead = {0}", sdl.bhead); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.ppart = {0}", sdl.ppart); - for(int i = 0; i < 8; i++) - { - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.partitions[{1}].start_cylinder = {0}", sdl.partitions[i].start_cylinder, i); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.partitions[{1}].num_sectors = {0}", sdl.partitions[i].num_sectors, i); - } - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.magic = 0x{0:X4}", sdl.magic); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "sdl.csum = 0x{0:X4}", sdl.csum); - DicConsole.DebugWriteLine("Sun Disklabel plugin", "csum = 0x{0:X4}", csum); + sunSector = imagePlugin.ReadSector(sectorOffset + 1); - ulong sectorsPerCylinder = (ulong)(sdl.nsect * sdl.ntrks); + handle = GCHandle.Alloc(sunSector, GCHandleType.Pinned); + dkl = (dk_label)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(dk_label)); + dkl8 = (dk_label8)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(dk_label8)); + dkl16 = (dk_label16)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(dk_label16)); + handle.Free(); - if(sectorsPerCylinder == 0 || sectorsPerCylinder * sdl.pcylcount > imagePlugin.GetSectors() || sdl.magic != SUN_MAGIC) - return false; - - for(int i = 0; i < 8; i++) - { - if((SunTypes)sdl.vtoc.infos[i].id != SunTypes.SunWholeDisk && sdl.partitions[i].num_sectors > 0) + if(dkl.dkl_magic == DKL_MAGIC || dkl.dkl_magic == DKL_CIGAM) { - CommonTypes.Partition part = new CommonTypes.Partition - { - Description = SunFlagsToString((SunFlags)sdl.vtoc.infos[i].flags), -#pragma warning disable IDE0004 // Remove Unnecessary Cast - Size = (ulong)sdl.partitions[i].num_sectors * (ulong)imagePlugin.GetSectorSize(), -#pragma warning restore IDE0004 // Remove Unnecessary Cast - Name = "", - Length = sdl.partitions[i].num_sectors, - Sequence = (ulong)i, -#pragma warning disable IDE0004 // Remove Unnecessary Cast - Offset = (ulong)sdl.partitions[i].start_cylinder * (ulong)sectorsPerCylinder * (ulong)imagePlugin.GetSectorSize(), -#pragma warning restore IDE0004 // Remove Unnecessary Cast - Start = sdl.partitions[i].start_cylinder * sectorsPerCylinder, - Type = SunIdToString((SunTypes)sdl.vtoc.infos[i].id), - Scheme = Name - }; - if(part.Start > imagePlugin.GetSectors() || (part.Start + part.Length) > imagePlugin.GetSectors()) - return false; - - partitions.Add(part); + if(dkl16.dkl_vtoc.v_sanity == VTOC_SANE || dkl16.dkl_vtoc.v_sanity == VTOC_ENAS) + useDkl16 = true; + else if(dkl8.dkl_vtoc.v_sanity == VTOC_SANE || dkl8.dkl_vtoc.v_sanity == VTOC_ENAS) + useDkl8 = true; + else + useDkl = true; } } - return true; + if(!useDkl && !useDkl8 && !useDkl16) + return false; + + if(useDkl16 && dkl16.dkl_magic == DKL_CIGAM) + dkl16 = SwapDiskLabel(dkl16); + else if(useDkl8 && dkl8.dkl_magic == DKL_CIGAM) + dkl8 = SwapDiskLabel(dkl8); + else if(useDkl && dkl.dkl_magic == DKL_CIGAM) + dkl = SwapDiskLabel(dkl); + + if(useDkl) + { + ulong sectorsPerCylinder = (ulong)(dkl.dkl_nsect * dkl.dkl_nhead); + + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_asciilabel = \"{0}\"", StringHandlers.CToString(dkl.dkl_asciilabel)); + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_rpm = {0}", dkl.dkl_rpm); + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_pcyl = {0}", dkl.dkl_pcyl); + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_apc = {0}", dkl.dkl_apc); + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_gap1 = {0}", dkl.dkl_gap1); + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_gap2 = {0}", dkl.dkl_gap2); + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_intrlv = {0}", dkl.dkl_intrlv); + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_ncyl = {0}", dkl.dkl_ncyl); + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_acyl = {0}", dkl.dkl_acyl); + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_nhead = {0}", dkl.dkl_nhead); + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_nsect = {0}", dkl.dkl_nsect); + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_bhead = {0}", dkl.dkl_bhead); + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_ppart = {0}", dkl.dkl_ppart); + for(int i = 0; i < NDKMAP; i++) + { + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_map[{0}].dkl_cylno = {1}", i, dkl.dkl_map[i].dkl_cylno); + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_map[{0}].dkl_nblk = {1}", i, dkl.dkl_map[i].dkl_nblk); + } + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_magic = 0x{0:X4}", dkl.dkl_magic); + DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_cksum = 0x{0:X4}", dkl.dkl_cksum); + DicConsole.DebugWriteLine("Sun plugin", "sectorsPerCylinder = {0}", sectorsPerCylinder); + + for(int i = 0; i < NDKMAP; i++) + { + if(dkl.dkl_map[i].dkl_cylno > 0 && dkl.dkl_map[i].dkl_nblk > 0) + { + CommonTypes.Partition part = new CommonTypes.Partition + { + Size = (ulong)dkl.dkl_map[i].dkl_nblk * DK_LABEL_SIZE, + Length = (ulong)((dkl.dkl_map[i].dkl_nblk * DK_LABEL_SIZE) / imagePlugin.GetSectorSize()), + Sequence = (ulong)i, + Offset = ((ulong)dkl.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) * DK_LABEL_SIZE, + Start = (((ulong)dkl.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) * DK_LABEL_SIZE) / imagePlugin.GetSectorSize(), + Type = "SunOS partition", + Scheme = Name + }; + if(part.Start < imagePlugin.GetSectors() && part.End <= imagePlugin.GetSectors()) + partitions.Add(part); + } + } + } + else if(useDkl8) + { + ulong sectorsPerCylinder = (ulong)(dkl8.dkl_nsect * dkl8.dkl_nhead); + + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_asciilabel = \"{0}\"", StringHandlers.CToString(dkl8.dkl_asciilabel)); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_version = {0}", dkl8.dkl_vtoc.v_version); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_volume = \"{0}\"", StringHandlers.CToString(dkl8.dkl_vtoc.v_volume)); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_nparts = {0}", dkl8.dkl_vtoc.v_nparts); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_sanity = 0x{0:X8}", dkl8.dkl_vtoc.v_sanity); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_write_reinstruct = {0}", dkl8.dkl_write_reinstruct); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_read_reinstruct = {0}", dkl8.dkl_read_reinstruct); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_rpm = {0}", dkl8.dkl_rpm); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_pcyl = {0}", dkl8.dkl_pcyl); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_apc = {0}", dkl8.dkl_apc); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_obs1 = {0}", dkl8.dkl_obs1); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_obs2 = {0}", dkl8.dkl_obs2); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_intrlv = {0}", dkl8.dkl_intrlv); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_ncyl = {0}", dkl8.dkl_ncyl); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_acyl = {0}", dkl8.dkl_acyl); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_nhead = {0}", dkl8.dkl_nhead); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_nsect = {0}", dkl8.dkl_nsect); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_obs3 = {0}", dkl8.dkl_obs3); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_obs4 = {0}", dkl8.dkl_obs4); + for(int i = 0; i < NDKMAP; i++) + { + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_map[{0}].dkl_cylno = {1}", i, dkl8.dkl_map[i].dkl_cylno); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_map[{0}].dkl_nblk = {1}", i, dkl8.dkl_map[i].dkl_nblk); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_part[{0}].p_tag = {1} ({2})", i, dkl8.dkl_vtoc.v_part[i].p_tag, (ushort)dkl8.dkl_vtoc.v_part[i].p_tag); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_part[{0}].p_flag = {1} ({2})", i, dkl8.dkl_vtoc.v_part[i].p_flag, (ushort)dkl8.dkl_vtoc.v_part[i].p_flag); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_timestamp[{0}] = {1}", i, DateHandlers.UNIXToDateTime(dkl8.dkl_vtoc.v_timestamp[i])); + } + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_magic = 0x{0:X4}", dkl8.dkl_magic); + DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_cksum = 0x{0:X4}", dkl8.dkl_cksum); + DicConsole.DebugWriteLine("Sun plugin", "sectorsPerCylinder = {0}", sectorsPerCylinder); + + if(dkl8.dkl_vtoc.v_nparts > NDKMAP) + return false; + + for(int i = 0; i < dkl8.dkl_vtoc.v_nparts; i++) + { + if(dkl8.dkl_map[i].dkl_nblk > 0 && + dkl8.dkl_vtoc.v_part[i].p_tag != SunTag.SunEmpty && dkl8.dkl_vtoc.v_part[i].p_tag != SunTag.SunWholeDisk) + { + CommonTypes.Partition part = new CommonTypes.Partition + { + Description = SunFlagsToString(dkl8.dkl_vtoc.v_part[i].p_flag), + Size = (ulong)dkl8.dkl_map[i].dkl_nblk * DK_LABEL_SIZE, + Length = (ulong)((dkl8.dkl_map[i].dkl_nblk * DK_LABEL_SIZE) / imagePlugin.GetSectorSize()), + Sequence = (ulong)i, + Offset = ((ulong)dkl8.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) * DK_LABEL_SIZE, + Start = (((ulong)dkl8.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) * DK_LABEL_SIZE) / imagePlugin.GetSectorSize(), + Type = SunIdToString(dkl8.dkl_vtoc.v_part[i].p_tag), + Scheme = Name + }; + if(dkl8.dkl_vtoc.v_timestamp[i] != 0) + part.Description += string.Format("\nPartition timestamped on {0}", DateHandlers.UNIXToDateTime(dkl8.dkl_vtoc.v_timestamp[i])); + + if(part.Start < imagePlugin.GetSectors() && part.End <= imagePlugin.GetSectors()) + partitions.Add(part); + } + } + } + else if(useDkl16) + { + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_sanity = 0x{0:X8}", dkl16.dkl_vtoc.v_sanity); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_version = {0}", dkl16.dkl_vtoc.v_version); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_volume = \"{0}\"", StringHandlers.CToString(dkl16.dkl_vtoc.v_volume)); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_sectorsz = {0}", dkl16.dkl_vtoc.v_sectorsz); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_nparts = {0}", dkl16.dkl_vtoc.v_nparts); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_asciilabel = \"{0}\"", StringHandlers.CToString(dkl16.dkl_vtoc.v_asciilabel)); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_pcyl = {0}", dkl16.dkl_pcyl); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_ncyl = {0}", dkl16.dkl_ncyl); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_acyl = {0}", dkl16.dkl_acyl); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_bcyl = {0}", dkl16.dkl_bcyl); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_nhead = {0}", dkl16.dkl_nhead); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_nsect = {0}", dkl16.dkl_nsect); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_intrlv = {0}", dkl16.dkl_intrlv); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_skew = {0}", dkl16.dkl_skew); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_apc = {0}", dkl16.dkl_apc); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_rpm = {0}", dkl16.dkl_rpm); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_write_reinstruct = {0}", dkl16.dkl_write_reinstruct); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_read_reinstruct = {0}", dkl16.dkl_read_reinstruct); + for(int i = 0; i < NDKMAP16; i++) + { + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_part[{0}].p_start = {1}", i, dkl16.dkl_vtoc.v_part[i].p_start); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_part[{0}].p_size = {1}", i, dkl16.dkl_vtoc.v_part[i].p_size); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_part[{0}].p_tag = {1} ({2})", i, dkl16.dkl_vtoc.v_part[i].p_tag, (ushort)dkl16.dkl_vtoc.v_part[i].p_tag); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_part[{0}].p_flag = {1} ({2})", i, dkl16.dkl_vtoc.v_part[i].p_flag, (ushort)dkl16.dkl_vtoc.v_part[i].p_flag); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_timestamp[{0}] = {1}", i, DateHandlers.UNIXToDateTime(dkl16.dkl_vtoc.v_timestamp[i])); + } + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_magic = 0x{0:X4}", dkl16.dkl_magic); + DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_cksum = 0x{0:X4}", dkl16.dkl_cksum); + + if(dkl16.dkl_vtoc.v_nparts > NDKMAP16) + return false; + + for(int i = 0; i < dkl16.dkl_vtoc.v_nparts; i++) + { + if(dkl16.dkl_vtoc.v_part[i].p_size > 0 && + dkl16.dkl_vtoc.v_part[i].p_tag != SunTag.SunEmpty && dkl16.dkl_vtoc.v_part[i].p_tag != SunTag.SunWholeDisk) + { + CommonTypes.Partition part = new CommonTypes.Partition + { + Description = SunFlagsToString(dkl16.dkl_vtoc.v_part[i].p_flag), + Size = (ulong)dkl16.dkl_vtoc.v_part[i].p_size * dkl16.dkl_vtoc.v_sectorsz, + Length = (ulong)((dkl16.dkl_vtoc.v_part[i].p_size * dkl16.dkl_vtoc.v_sectorsz) / imagePlugin.GetSectorSize()), + Sequence = (ulong)i, + Offset = ((ulong)dkl16.dkl_vtoc.v_part[i].p_start + sectorOffset) * dkl16.dkl_vtoc.v_sectorsz, + Start = (((ulong)dkl16.dkl_vtoc.v_part[i].p_start + sectorOffset) * dkl16.dkl_vtoc.v_sectorsz) / imagePlugin.GetSectorSize(), + Type = SunIdToString(dkl16.dkl_vtoc.v_part[i].p_tag), + Scheme = Name + }; + if(dkl16.dkl_vtoc.v_timestamp[i] != 0) + part.Description += string.Format("\nPartition timestamped on {0}", DateHandlers.UNIXToDateTime(dkl16.dkl_vtoc.v_timestamp[i])); + if(part.Start < imagePlugin.GetSectors() && part.End <= imagePlugin.GetSectors()) + partitions.Add(part); + } + } + } + + return + partitions.Count > 0; + } + + static dk_label SwapDiskLabel(dk_label label) + { + DicConsole.DebugWriteLine("Sun plugin", "Swapping dk_label"); + dk_label lebal = BigEndianMarshal.SwapStructureMembersEndian(label); + for(int i = 0; i < label.dkl_map.Length; i++) + lebal.dkl_map[i] = BigEndianMarshal.SwapStructureMembersEndian(label.dkl_map[i]); + + return lebal; + } + + static dk_label8 SwapDiskLabel(dk_label8 label) + { + DicConsole.DebugWriteLine("Sun plugin", "Swapping dk_label8"); + dk_label8 lebal = BigEndianMarshal.SwapStructureMembersEndian(label); + lebal.dkl_vtoc = BigEndianMarshal.SwapStructureMembersEndian(label.dkl_vtoc); + for(int i = 0; i < label.dkl_map.Length; i++) + lebal.dkl_map[i] = BigEndianMarshal.SwapStructureMembersEndian(label.dkl_map[i]); + for(int i = 0; i < label.dkl_vtoc.v_bootinfo.Length; i++) + lebal.dkl_vtoc.v_bootinfo[i] = Swapping.Swap(label.dkl_vtoc.v_bootinfo[i]); + for(int i = 0; i < label.dkl_vtoc.v_part.Length; i++) + { + lebal.dkl_vtoc.v_part[i].p_flag = (SunFlags)Swapping.Swap((ushort)label.dkl_vtoc.v_part[i].p_flag); + lebal.dkl_vtoc.v_part[i].p_tag = (SunTag)Swapping.Swap((ushort)label.dkl_vtoc.v_part[i].p_tag); + } + for(int i = 0; i < label.dkl_vtoc.v_timestamp.Length; i++) + lebal.dkl_vtoc.v_timestamp[i] = Swapping.Swap(label.dkl_vtoc.v_timestamp[i]); + for(int i = 0; i < label.dkl_vtoc.v_reserved.Length; i++) + lebal.dkl_vtoc.v_reserved[i] = Swapping.Swap(label.dkl_vtoc.v_reserved[i]); + + return lebal; + } + + static dk_label16 SwapDiskLabel(dk_label16 label) + { + DicConsole.DebugWriteLine("Sun plugin", "Swapping dk_label16"); + dk_label16 lebal = BigEndianMarshal.SwapStructureMembersEndian(label); + lebal.dkl_vtoc = BigEndianMarshal.SwapStructureMembersEndian(label.dkl_vtoc); + for(int i = 0; i < label.dkl_vtoc.v_bootinfo.Length; i++) + lebal.dkl_vtoc.v_bootinfo[i] = Swapping.Swap(label.dkl_vtoc.v_bootinfo[i]); + for(int i = 0; i < label.dkl_vtoc.v_part.Length; i++) + { + lebal.dkl_vtoc.v_part[i].p_flag = (SunFlags)Swapping.Swap((ushort)label.dkl_vtoc.v_part[i].p_flag); + lebal.dkl_vtoc.v_part[i].p_tag = (SunTag)Swapping.Swap((ushort)label.dkl_vtoc.v_part[i].p_tag); + lebal.dkl_vtoc.v_part[i].p_size = Swapping.Swap(label.dkl_vtoc.v_part[i].p_size); + lebal.dkl_vtoc.v_part[i].p_start = Swapping.Swap(label.dkl_vtoc.v_part[i].p_start); + } + for(int i = 0; i < label.dkl_vtoc.v_timestamp.Length; i++) + lebal.dkl_vtoc.v_timestamp[i] = Swapping.Swap(label.dkl_vtoc.v_timestamp[i]); + for(int i = 0; i < label.dkl_vtoc.v_reserved.Length; i++) + lebal.dkl_vtoc.v_reserved[i] = Swapping.Swap(label.dkl_vtoc.v_reserved[i]); + + return lebal; } public static string SunFlagsToString(SunFlags flags) @@ -243,199 +404,286 @@ namespace DiscImageChef.PartPlugins return sb.ToString(); } - public static string SunIdToString(SunTypes id) + public static string SunIdToString(SunTag id) { switch(id) { - case SunTypes.Linux: + case SunTag.Linux: return "Linux"; - case SunTypes.LinuxRaid: + case SunTag.LinuxRaid: return "Linux RAID"; - case SunTypes.LinuxSwap: + case SunTag.LinuxSwap: return "Linux swap"; - case SunTypes.LVM: + case SunTag.LVM: return "LVM"; - case SunTypes.SunBoot: + case SunTag.SunBoot: return "Sun boot"; - case SunTypes.SunEmpty: + case SunTag.SunEmpty: return "Empty"; - case SunTypes.SunHome: + case SunTag.SunHome: return "Sun /home"; - case SunTypes.SunRoot: + case SunTag.SunRoot: return "Sun /"; - case SunTypes.SunStand: + case SunTag.SunStand: return "Sun /stand"; - case SunTypes.SunSwap: + case SunTag.SunSwap: return "Sun swap"; - case SunTypes.SunUsr: + case SunTag.SunUsr: return "Sun /usr"; - case SunTypes.SunVar: + case SunTag.SunVar: return "Sun /var"; - case SunTypes.SunWholeDisk: + case SunTag.SunWholeDisk: return "Whole disk"; + case SunTag.SunAlt: + return "Replacement sectors"; + case SunTag.SunCache: + return "Sun cachefs"; + case SunTag.SunReserved: + return "Reserved for SMI"; + case SunTag.VxVmPublic: + return "Veritas public"; + case SunTag.VxVmPrivate: + return "Veritas private"; + case SunTag.NetBSD: + return "NetBSD"; + case SunTag.FreeBSD_Swap: + return "FreeBSD swap"; + case SunTag.FreeBSD_UFS: + return "FreeBSD"; + case SunTag.FreeBSD_Vinum: + return "Vinum"; + case SunTag.FreeBSD_ZFS: + return "FreeBSD ZFS"; + case SunTag.FreeBSD_NANDFS: + return "FreeBSD nandfs"; default: return "Unknown"; } } + /// SunOS logical partitions [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct SunDiskLabel + struct dk_map { - /// - /// Offset 0x000: Informative string, 128 bytes - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] - public string info; - /// - /// Offset 0x080: Volume Table Of Contents - /// - public SunVTOC vtoc; - /// - /// Offset 0x108: Sectors to skip on writes - /// - public uint write_reinstruct; - /// - /// Offset 0x10C: Sectors to skip in reads - /// - public uint read_reinstruct; - /// - /// Offset 0x110: Unused, 148 bytes - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 148)] - public byte[] spare; - /// - /// Offset 0x1A4: Rotational speed - /// - public ushort rspeed; - /// - /// Offset 0x1A6: Physical cylinder count - /// - public ushort pcylcount; - /// - /// Offset 0x1A8: Extra sectors per cylinder - /// - public ushort sparecyl; - /// - /// Offset 0x1AA: Obsolete, gap - /// - public ushort gap1; - /// - /// Offset 0x1AC: Obsolete, gap - /// - public ushort gap2; - /// - /// Offset 0x1AE: Interleave factor - /// - public ushort ilfact; - /// - /// Offset 0x1B0: Cylinders - /// - public ushort ncyl; - /// - /// Offset 0x1B2: Alternate cylinders - /// - public ushort nacyl; - /// - /// Offset 0x1B4: Tracks per cylinder - /// - public ushort ntrks; - /// - /// Offset 0x1B6: Sectors per track - /// - public ushort nsect; - /// - /// Offset 0x1B8: Label head offset - /// - public ushort bhead; - /// - /// Offset 0x1BA: Physical partition - /// - public ushort ppart; - /// - /// Offset 0x1BC: Partitions - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public SunPartition[] partitions; - /// - /// Offset 0x1FC: - /// - public ushort magic; - /// - /// Offset 0x1FE: XOR of label - /// - public ushort csum; + /// starting cylinder + public int dkl_cylno; + /// number of blocks + public int dkl_nblk; + } + + /// SunOS disk label + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct dk_label + { + /// Informative string + [MarshalAs(UnmanagedType.ByValArray, SizeConst = LEN_DKL_ASCII)] + public byte[] dkl_asciilabel; + /// Padding + [MarshalAs(UnmanagedType.ByValArray, SizeConst = LEN_DKL_PAD)] + public byte[] dkl_pad; + /// rotations per minute + public ushort dkl_rpm; + /// # physical cylinders + public ushort dkl_pcyl; + /// alternates per cylinder + public ushort dkl_apc; + /// size of gap 1 + public ushort dkl_gap1; + /// size of gap 2 + public ushort dkl_gap2; + /// interleave factor + public ushort dkl_intrlv; + /// # of data cylinders + public ushort dkl_ncyl; + /// # of alternate cylinders + public ushort dkl_acyl; + /// # of heads in this partition + public ushort dkl_nhead; + /// # of 512 byte sectors per track + public ushort dkl_nsect; + /// identifies proper label location + public ushort dkl_bhead; + /// physical partition # + public ushort dkl_ppart; + /// Logical partitions + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NDKMAP)] + public dk_map[] dkl_map; + /// identifies this label format + public ushort dkl_magic; + /// xor checksum of sector + public ushort dkl_cksum; + } + + /// Solaris logical partition for small disk label + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct dk_map2 + { + /// ID tag of partition + public SunTag p_tag; + /// permission flag + public SunFlags p_flag; + } + + /// Solaris logical partition + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct dkl_partition + { + /// ID tag of partition + public SunTag p_tag; + /// permision flags + public SunFlags p_flag; + /// start sector no of partition + public int p_start; + /// # of blocks in partition + public int p_size; } [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct SunVTOC + struct dk_vtoc8 { - /// - /// Offset 0x00: VTOC version - /// - public uint version; - /// - /// Offset 0x04: Volume name, 8 bytes - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public string volname; - /// - /// Offset 0x0C: Number of partitions - /// - public ushort nparts; - /// - /// Offset 0x0E: Partition information, 8 entries - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public SunInfo[] infos; - /// - /// Offset 0x2E: Padding - /// + /// layout version + public uint v_version; + /// volume name + [MarshalAs(UnmanagedType.ByValArray, SizeConst = LEN_DKL_VVOL)] + public byte[] v_volume; + /// number of partitions + public ushort v_nparts; + /// partition hdrs, sec 2 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NDKMAP)] + public dk_map2[] v_part; + /// Alignment public ushort padding; - /// - /// Offset 0x30: Information needed by mboot, 3 entries - /// + /// info needed by mboot [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - public uint[] bootinfo; - /// - /// Offset 0x3C: VTOC magic - /// - public uint sanity; - /// - /// Offset 0x40: Reserved, 40 bytes - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] - public byte[] reserved; - /// - /// Offset 0x68: Partition timestamps, 8 entries - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public uint[] timestamp; + public uint[] v_bootinfo; + /// to verify vtoc sanity + public uint v_sanity; + /// free space + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] + public uint[] v_reserved; + /// partition timestamp + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NDKMAP)] + public int[] v_timestamp; } [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct SunInfo + struct dk_vtoc16 { - /// - /// Offset 0x00: Partition ID - /// - public ushort id; - /// - /// Offset 0x02: Partition flags - /// - public ushort flags; + /// info needed by mboot + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public uint[] v_bootinfo; + /// to verify vtoc sanity + public uint v_sanity; + /// layout version + public uint v_version; + /// volume name + [MarshalAs(UnmanagedType.ByValArray, SizeConst = LEN_DKL_VVOL)] + public byte[] v_volume; + /// sector size in bytes + public ushort v_sectorsz; + /// number of partitions + public ushort v_nparts; + /// free space + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] + public uint[] v_reserved; + /// partition headers + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NDKMAP16)] + public dkl_partition[] v_part; + /// partition timestamp + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NDKMAP16)] + public int[] v_timestamp; + /// for compatibility + [MarshalAs(UnmanagedType.ByValArray, SizeConst = LEN_DKL_ASCII)] + public byte[] v_asciilabel; } [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct SunPartition + struct dk_label8 { - /// - /// Offset 0x00: Starting cylinder - /// - public uint start_cylinder; - /// - /// Offset 0x02: Sectors - /// - public uint num_sectors; + /// for compatibility + [MarshalAs(UnmanagedType.ByValArray, SizeConst = LEN_DKL_ASCII)] + public byte[] dkl_asciilabel; + /// vtoc inclusions from AT&T SVr4 + public dk_vtoc8 dkl_vtoc; + /// # sectors to skip, writes + public ushort dkl_write_reinstruct; + /// # sectors to skip, reads + public ushort dkl_read_reinstruct; + /// unused part of 512 bytes + [MarshalAs(UnmanagedType.ByValArray, SizeConst = LEN_DKL_PAD8)] + public byte[] dkl_pad; + /// rotations per minute + public ushort dkl_rpm; + /// # physical cylinders + public ushort dkl_pcyl; + /// alternates per cylinder + public ushort dkl_apc; + /// obsolete + public ushort dkl_obs1; + /// obsolete + public ushort dkl_obs2; + /// interleave factor + public ushort dkl_intrlv; + /// # of data cylinders + public ushort dkl_ncyl; + /// # of alternate cylinders + public ushort dkl_acyl; + /// # of heads in this partition + public ushort dkl_nhead; + /// # of 512 byte sectors per track + public ushort dkl_nsect; + /// obsolete + public ushort dkl_obs3; + /// obsolete + public ushort dkl_obs4; + /// logical partition headers + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NDKMAP)] + public dk_map[] dkl_map; + /// identifies this label format + public ushort dkl_magic; + /// xor checksum of sector + public ushort dkl_cksum; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct dk_label16 + { + /// vtoc inclusions from AT&T SVr4 + public dk_vtoc16 dkl_vtoc; + /// # of physical cylinders + public uint dkl_pcyl; + /// # of data cylinders + public uint dkl_ncyl; + /// # of alternate cylinders + public ushort dkl_acyl; + /// cyl offset (for fixed head area) + public ushort dkl_bcyl; + /// # of heads + public uint dkl_nhead; + /// # of data sectors per track + public uint dkl_nsect; + /// interleave factor + public ushort dkl_intrlv; + /// skew factor + public ushort dkl_skew; + /// alternates per cyl (SCSI only) + public ushort dkl_apc; + /// revolutions per minute + public ushort dkl_rpm; + /// # sectors to skip, writes + public ushort dkl_write_reinstruct; + /// # sectors to skip, reads + public ushort dkl_read_reinstruct; + /// for compatible expansion + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public ushort[] dkl_extra; + /// unused part of 512 bytes + [MarshalAs(UnmanagedType.ByValArray, SizeConst = LEN_DKL_PAD16)] + public byte[] dkl_pad; + /// identifies this label format + public ushort dkl_magic; + /// xor checksum of sector + public ushort dkl_cksum; } } } \ No newline at end of file