1*6ba1b8a5Skrw /* $OpenBSD: part.c,v 1.144 2023/03/30 22:53:39 krw Exp $ */ 2a1705421Sweingart 3a1705421Sweingart /* 4a1705421Sweingart * Copyright (c) 1997 Tobias Weingartner 5a1705421Sweingart * 610a68084Skrw * Permission to use, copy, modify, and distribute this software for any 710a68084Skrw * purpose with or without fee is hereby granted, provided that the above 810a68084Skrw * copyright notice and this permission notice appear in all copies. 9a1705421Sweingart * 1010a68084Skrw * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1110a68084Skrw * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1210a68084Skrw * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1310a68084Skrw * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1410a68084Skrw * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1510a68084Skrw * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1610a68084Skrw * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17a1705421Sweingart */ 18a1705421Sweingart 19a7568474Sderaadt #include <sys/types.h> 20a7568474Sderaadt #include <sys/disklabel.h> 21729290c0Skrw 22e8252b55Skrw #include <err.h> 2398952941Skrw #include <stdint.h> 24a1705421Sweingart #include <stdio.h> 25fba7235cSkrw #include <stdlib.h> 26184a329bSmillert #include <string.h> 27fba7235cSkrw #include <uuid.h> 28abc6f793Skrw 29199eafeaSkrw #include "part.h" 30a5472107Skrw #include "disk.h" 31a1705421Sweingart #include "misc.h" 3265deb39bSkrw #include "gpt.h" 33a1705421Sweingart 345308a554Skrw struct mbr_type { 355308a554Skrw int mt_type; 3624a7e0ddSkrw char *mt_name; 375308a554Skrw }; 385308a554Skrw 39290491cbSkrw /* 40290491cbSkrw * MBR type sources: 41290491cbSkrw * OpenBSD Historical usage 42290491cbSkrw * https://en.wikipedia.org/wiki/Partition_type#List_of_partition_IDs 43290491cbSkrw * https://www.win.tue.nl/~aeb/partitions/partition_types-1.html 44290491cbSkrw */ 455308a554Skrw const struct mbr_type mbr_types[] = { 465308a554Skrw { 0x00, "unused" }, /* unused */ 475308a554Skrw { 0x01, "DOS FAT-12" }, /* Primary DOS with 12 bit FAT */ 48764d6d49Stom { 0x02, "XENIX /" }, /* XENIX / filesystem */ 49764d6d49Stom { 0x03, "XENIX /usr" }, /* XENIX /usr filesystem */ 505308a554Skrw { 0x04, "DOS FAT-16" }, /* Primary DOS with 16 bit FAT */ 51764d6d49Stom { 0x05, "Extended DOS" }, /* Extended DOS */ 525308a554Skrw { 0x06, "DOS > 32MB" }, /* Primary 'big' DOS (> 32MB) */ 535308a554Skrw { 0x07, "NTFS" }, /* NTFS */ 54764d6d49Stom { 0x08, "AIX fs" }, /* AIX filesystem */ 55764d6d49Stom { 0x09, "AIX/Coherent" }, /* AIX boot partition or Coherent */ 56764d6d49Stom { 0x0A, "OS/2 Bootmgr" }, /* OS/2 Boot Manager or OPUS */ 575308a554Skrw { 0x0B, "Win95 FAT-32" }, /* Primary Win95 w/ 32-bit FAT */ 585308a554Skrw { 0x0C, "Win95 FAT32L" }, /* Primary Win95 w/ 32-bit FAT LBA-mapped */ 595308a554Skrw { 0x0E, "DOS FAT-16" }, /* Primary DOS w/ 16-bit FAT, CHS-mapped */ 60764d6d49Stom { 0x0F, "Extended LBA" }, /* Extended DOS LBA-mapped */ 61764d6d49Stom { 0x10, "OPUS" }, /* OPUS */ 625308a554Skrw { 0x11, "OS/2 hidden" }, /* OS/2 BM: hidden DOS 12-bit FAT */ 6372c8f31dSkrw { 0x12, "Compaq Diag" }, /* Compaq Diagnostics */ 645308a554Skrw { 0x14, "OS/2 hidden" }, /* OS/2 BM: hidden DOS 16-bit FAT <32M or Novell DOS 7.0 bug */ 655308a554Skrw { 0x16, "OS/2 hidden" }, /* OS/2 BM: hidden DOS 16-bit FAT >=32M */ 665308a554Skrw { 0x17, "OS/2 hidden" }, /* OS/2 BM: hidden IFS */ 67764d6d49Stom { 0x18, "AST swap" }, /* AST Windows swapfile */ 68764d6d49Stom { 0x19, "Willowtech" }, /* Willowtech Photon coS */ 695308a554Skrw { 0x1C, "ThinkPad Rec" }, /* IBM ThinkPad recovery partition */ 70fba7235cSkrw { 0x20, "Willowsoft" }, /* Willowsoft OFS1 */ 715308a554Skrw { 0x24, "NEC DOS" }, /* NEC DOS */ 725308a554Skrw { 0x27, "Win Recovery" }, /* Windows hidden Recovery Partition */ 73764d6d49Stom { 0x38, "Theos" }, /* Theos */ 74764d6d49Stom { 0x39, "Plan 9" }, /* Plan 9 */ 75764d6d49Stom { 0x40, "VENIX 286" }, /* VENIX 286 or LynxOS */ 76764d6d49Stom { 0x41, "Lin/Minux DR" }, /* Linux/MINIX (sharing disk with DRDOS) or Personal RISC boot */ 775308a554Skrw { 0x42, "LinuxSwap DR" }, /* SFS or Linux swap (sharing disk with DRDOS) */ 78764d6d49Stom { 0x43, "Linux DR" }, /* Linux native (sharing disk with DRDOS) */ 79764d6d49Stom { 0x4D, "QNX 4.2 Pri" }, /* QNX 4.2 Primary */ 80764d6d49Stom { 0x4E, "QNX 4.2 Sec" }, /* QNX 4.2 Secondary */ 81764d6d49Stom { 0x4F, "QNX 4.2 Ter" }, /* QNX 4.2 Tertiary */ 82764d6d49Stom { 0x50, "DM" }, /* DM (disk manager) */ 83764d6d49Stom { 0x51, "DM" }, /* DM6 Aux1 (or Novell) */ 84764d6d49Stom { 0x52, "CP/M or SysV" }, /* CP/M or Microport SysV/AT */ 85764d6d49Stom { 0x53, "DM" }, /* DM6 Aux3 */ 86764d6d49Stom { 0x54, "Ontrack" }, /* Ontrack */ 87764d6d49Stom { 0x55, "EZ-Drive" }, /* EZ-Drive (disk manager) */ 88764d6d49Stom { 0x56, "Golden Bow" }, /* Golden Bow (disk manager) */ 89764d6d49Stom { 0x5C, "Priam" }, /* Priam Edisk (disk manager) */ 90764d6d49Stom { 0x61, "SpeedStor" }, /* SpeedStor */ 91764d6d49Stom { 0x63, "ISC, HURD, *" }, /* ISC, System V/386, GNU HURD or Mach */ 92764d6d49Stom { 0x64, "NetWare 2.xx" }, /* Novell NetWare 2.xx */ 93764d6d49Stom { 0x65, "NetWare 3.xx" }, /* Novell NetWare 3.xx */ 94764d6d49Stom { 0x66, "NetWare 386" }, /* Novell 386 NetWare */ 95764d6d49Stom { 0x67, "Novell" }, /* Novell */ 96764d6d49Stom { 0x68, "Novell" }, /* Novell */ 97764d6d49Stom { 0x69, "Novell" }, /* Novell */ 98764d6d49Stom { 0x70, "DiskSecure" }, /* DiskSecure Multi-Boot */ 99764d6d49Stom { 0x75, "PCIX" }, /* PCIX */ 100764d6d49Stom { 0x80, "Minix (old)" }, /* Minix 1.1 ... 1.4a */ 101764d6d49Stom { 0x81, "Minix (new)" }, /* Minix 1.4b ... 1.5.10 */ 1025308a554Skrw { 0x82, "Linux swap" }, /* Linux swap */ 1035308a554Skrw { 0x83, "Linux files*" }, /* Linux filesystem */ 104764d6d49Stom { 0x84, "OS/2 hidden" }, /* OS/2 hidden C: drive */ 105764d6d49Stom { 0x85, "Linux ext." }, /* Linux extended */ 106764d6d49Stom { 0x86, "NT FAT VS" }, /* NT FAT volume set */ 107764d6d49Stom { 0x87, "NTFS VS" }, /* NTFS volume set or HPFS mirrored */ 1085308a554Skrw { 0x8E, "Linux LVM" }, /* Linux LVM */ 109764d6d49Stom { 0x93, "Amoeba FS" }, /* Amoeba filesystem */ 110764d6d49Stom { 0x94, "Amoeba BBT" }, /* Amoeba bad block table */ 111764d6d49Stom { 0x99, "Mylex" }, /* Mylex EISA SCSI */ 112764d6d49Stom { 0x9F, "BSDI" }, /* BSDI BSD/OS */ 113764d6d49Stom { 0xA0, "NotebookSave" }, /* Phoenix NoteBIOS save-to-disk */ 1145308a554Skrw { 0xA5, "FreeBSD" }, /* FreeBSD */ 1155308a554Skrw { 0xA6, "OpenBSD" }, /* OpenBSD */ 116764d6d49Stom { 0xA7, "NEXTSTEP" }, /* NEXTSTEP */ 1175308a554Skrw { 0xA8, "MacOS X" }, /* MacOS X main partition */ 1185308a554Skrw { 0xA9, "NetBSD" }, /* NetBSD */ 1195308a554Skrw { 0xAB, "MacOS X boot" }, /* MacOS X boot partition */ 1205308a554Skrw { 0xAF, "MacOS X HFS+" }, /* MacOS X HFS+ partition */ 121764d6d49Stom { 0xB7, "BSDI filesy*" }, /* BSDI BSD/386 filesystem */ 122764d6d49Stom { 0xB8, "BSDI swap" }, /* BSDI BSD/386 swap */ 1235308a554Skrw { 0xBF, "Solaris" }, /* Solaris */ 124764d6d49Stom { 0xC0, "CTOS" }, /* CTOS */ 125764d6d49Stom { 0xC1, "DRDOSs FAT12" }, /* DRDOS/sec (FAT-12) */ 126764d6d49Stom { 0xC4, "DRDOSs < 32M" }, /* DRDOS/sec (FAT-16, < 32M) */ 127764d6d49Stom { 0xC6, "DRDOSs >=32M" }, /* DRDOS/sec (FAT-16, >= 32M) */ 128764d6d49Stom { 0xC7, "HPFS Disbled" }, /* Syrinx (Cyrnix?) or HPFS disabled */ 129764d6d49Stom { 0xDB, "CPM/C.DOS/C*" }, /* Concurrent CPM or C.DOS or CTOS */ 130764d6d49Stom { 0xDE, "Dell Maint" }, /* Dell maintenance partition */ 131764d6d49Stom { 0xE1, "SpeedStor" }, /* DOS access or SpeedStor 12-bit FAT extended partition */ 132764d6d49Stom { 0xE3, "SpeedStor" }, /* DOS R/O or SpeedStor or Storage Dimensions */ 133764d6d49Stom { 0xE4, "SpeedStor" }, /* SpeedStor 16-bit FAT extended partition < 1024 cyl. */ 1345308a554Skrw { 0xEB, "BeOS/i386" }, /* BeOS for Intel */ 1352d874a94Sderaadt { 0xEE, "EFI GPT" }, /* EFI Protective Partition */ 1365308a554Skrw { 0xEF, "EFI Sys" }, /* EFI System Partition */ 137764d6d49Stom { 0xF1, "SpeedStor" }, /* SpeedStor or Storage Dimensions */ 138764d6d49Stom { 0xF2, "DOS 3.3+ Sec" }, /* DOS 3.3+ Secondary */ 139764d6d49Stom { 0xF4, "SpeedStor" }, /* SpeedStor >1024 cyl. or LANstep or IBM PS/2 IML */ 140764d6d49Stom { 0xFF, "Xenix BBT" }, /* Xenix Bad Block Table */ 141a1705421Sweingart }; 142a1705421Sweingart 1435308a554Skrw struct gpt_type { 144e3f6ba90Skrw int gt_menuid; 145f458660aSkrw int gt_attr; 146f458660aSkrw #define GTATTR_PROTECT (1 << 0) 147f458660aSkrw #define GTATTR_PROTECT_EFISYS (1 << 1) 14824a7e0ddSkrw char *gt_name; 149*6ba1b8a5Skrw char *gt_guid; 1505308a554Skrw }; 1515308a554Skrw 152290491cbSkrw /* 153290491cbSkrw * GPT GUID sources: 154290491cbSkrw * 155290491cbSkrw * UEFI: UEFI Specification 2.9, March 2021, Section 5.3.3, Table 5.7 156290491cbSkrw * Wikipedia: https://en.wikipedia.org/wiki/GUID_Partition_Table 157290491cbSkrw * NetBSD: /usr/src/sys/sys/disklabel_gpt.h 158290491cbSkrw * FreeBSD: /usr/src/sys/sys/disk/gpt.h. 159290491cbSkrw * DragonFlyBSD: /usr/src/sys/sys/disk/gpt.h. 160290491cbSkrw * Systemd:https://uapi-group.org/specifications/specs/discoverable_partitions_specification/ 161290491cbSkrw * https://www.freedesktop.org/software/systemd/man/systemd-gpt-auto-generator.html 162290491cbSkrw */ 163d6ffd808Skrw 164*6ba1b8a5Skrw char * const EFI_SYSTEM_PARTITION_GUID = "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"; 165*6ba1b8a5Skrw char * const MICROSOFT_BASIC_DATA_GUID = "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7"; 166d6ffd808Skrw 1675308a554Skrw const struct gpt_type gpt_types[] = { 168c96c378cSkrw { 0x00, 0, "unused", 169c96c378cSkrw "00000000-0000-0000-0000-000000000000" }, 170c96c378cSkrw { 0x01, 0, "FAT12", 171d6ffd808Skrw MICROSOFT_BASIC_DATA_GUID }, 172c96c378cSkrw { 0x04, 0, "FAT16S", 173d6ffd808Skrw MICROSOFT_BASIC_DATA_GUID }, 174c96c378cSkrw { 0x06, 0, "FAT16B", 175d6ffd808Skrw MICROSOFT_BASIC_DATA_GUID }, 176c96c378cSkrw { 0x07, 0, "NTFS", 177d6ffd808Skrw MICROSOFT_BASIC_DATA_GUID }, 178c96c378cSkrw { 0x0B, 0, "FAT32", 179d6ffd808Skrw MICROSOFT_BASIC_DATA_GUID }, 180c96c378cSkrw { 0x0C, 0, "FAT32L", 181d6ffd808Skrw MICROSOFT_BASIC_DATA_GUID }, 182f458660aSkrw { 0x0D, GTATTR_PROTECT, "BIOS Boot", 183c96c378cSkrw "21686148-6449-6e6f-744e-656564454649" }, 184c96c378cSkrw { 0x0E, 0, "FAT16L", 185d6ffd808Skrw MICROSOFT_BASIC_DATA_GUID }, 186c96c378cSkrw { 0x11, 0, "OS/2 hidden", 187d6ffd808Skrw MICROSOFT_BASIC_DATA_GUID }, 188c96c378cSkrw { 0x14, 0, "OS/2 hidden", 189d6ffd808Skrw MICROSOFT_BASIC_DATA_GUID }, 190c96c378cSkrw { 0x16, 0, "OS/2 hidden", 191d6ffd808Skrw MICROSOFT_BASIC_DATA_GUID }, 192c96c378cSkrw { 0x17, 0, "OS/2 hidden", 193d6ffd808Skrw MICROSOFT_BASIC_DATA_GUID }, 194c96c378cSkrw { 0x1C, 0, "ThinkPad Rec", 195d6ffd808Skrw MICROSOFT_BASIC_DATA_GUID }, 196c96c378cSkrw { 0x27, 0, "Win Recovery", 197c96c378cSkrw "de94bba4-06d1-4d40-a16a-bfd50179d6ac" }, 198c96c378cSkrw { 0x42, 0, "LinuxSwap DR", 199c96c378cSkrw "af9b60a0-1431-4f62-bc68-3311714a69ad" }, 200c96c378cSkrw { 0x7f, 0, "ChromeKernel", 201c96c378cSkrw "fe3a2a5d-4f32-41a7-b725-accc3285a309" }, 202c96c378cSkrw { 0x82, 0, "Linux swap", 203c96c378cSkrw "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f" }, 204c96c378cSkrw { 0x83, 0, "Linux files*", 205c96c378cSkrw "0fc63daf-8483-4772-8e79-3d69d8477de4" }, 206c96c378cSkrw { 0x8E, 0, "Linux LVM", 207c96c378cSkrw "e6d6d379-f507-44c2-a23c-238f2a3df928" }, 208c96c378cSkrw { 0xA5, 0, "FreeBSD", 209c96c378cSkrw "516e7cb4-6ecf-11d6-8ff8-00022d09712b" }, 210c96c378cSkrw { 0xA6, 0, "OpenBSD", 211c96c378cSkrw "824cc7a0-36a8-11e3-890a-952519ad3f61" }, 212c96c378cSkrw { 0xA8, 0, "MacOS X", 213c96c378cSkrw "55465300-0000-11aa-aa11-00306543ecac" }, 214c96c378cSkrw { 0xA9, 0, "NetBSD", 21565c111ddSkrw "49f48d5a-b10e-11dc-b99b-0019d1879648" }, 216c96c378cSkrw { 0xAB, 0, "MacOS X boot", 217c96c378cSkrw "426f6f74-0000-11aa-aa11-00306543ecac" }, 218c96c378cSkrw { 0xAF, 0, "MacOS X HFS+", 219c96c378cSkrw "48465300-0000-11aa-aa11-00306543ecac" }, 220f458660aSkrw { 0xB0, GTATTR_PROTECT | GTATTR_PROTECT_EFISYS, "APFS", 221c96c378cSkrw "7c3457ef-0000-11aa-aa11-00306543ecac" }, 222f458660aSkrw { 0xB1, GTATTR_PROTECT | GTATTR_PROTECT_EFISYS, "APFS ISC", 223c96c378cSkrw "69646961-6700-11aa-aa11-00306543ecac" }, 224f458660aSkrw { 0xB2, GTATTR_PROTECT | GTATTR_PROTECT_EFISYS, "APFS Recovery", 225c96c378cSkrw "52637672-7900-11aa-aa11-00306543ecac" }, 226f458660aSkrw { 0xB3, GTATTR_PROTECT, "HiFive FSBL", 227c96c378cSkrw "5b193300-fc78-40cd-8002-e86c45580b47" }, 228f458660aSkrw { 0xB4, GTATTR_PROTECT, "HiFive BBL", 229c96c378cSkrw "2e54b353-1271-4842-806f-e436d6af6985" }, 230c96c378cSkrw { 0xBF, 0, "Solaris", 231c96c378cSkrw "6a85cf4d-1dd2-11b2-99a6-080020736631" }, 232c96c378cSkrw { 0xEB, 0, "BeOS/i386", 233c96c378cSkrw "42465331-3ba3-10f1-802a-4861696b7521" }, 23465c111ddSkrw { 0xEC, 0, "Legacy MBR", 23565c111ddSkrw "024dee41-33e7-11d3-9d69-0008c781f39f" }, 236c96c378cSkrw { 0xEF, 0, "EFI Sys", 237e92bde66Skrw EFI_SYSTEM_PARTITION_GUID }, 23895e8765cSkrw }; 23995e8765cSkrw 240f2ec1a13Skrw const struct gpt_type *find_gpt_type(const struct uuid *); 241867d4347Skrw const struct mbr_type *find_mbr_type(const int); 242f458660aSkrw int uuid_attr(const struct uuid *); 243c96c378cSkrw 244c96c378cSkrw const struct gpt_type * 245c96c378cSkrw find_gpt_type(const struct uuid *uuid) 246c96c378cSkrw { 247c96c378cSkrw char *uuidstr = NULL; 248c96c378cSkrw unsigned int i; 249c96c378cSkrw uint32_t status; 250c96c378cSkrw 251c96c378cSkrw uuid_to_string(uuid, &uuidstr, &status); 252c96c378cSkrw if (status == uuid_s_ok) { 253c96c378cSkrw for (i = 0; i < nitems(gpt_types); i++) { 254*6ba1b8a5Skrw if (strcasecmp(gpt_types[i].gt_guid, uuidstr) == 0) 255c96c378cSkrw break; 256c96c378cSkrw } 257c96c378cSkrw } else 258c96c378cSkrw i = nitems(gpt_types); 259c96c378cSkrw free(uuidstr); 260c96c378cSkrw 261c96c378cSkrw if (i < nitems(gpt_types)) 262c96c378cSkrw return &gpt_types[i]; 263c96c378cSkrw else 264c96c378cSkrw return NULL; 265c96c378cSkrw } 266c96c378cSkrw 267867d4347Skrw const struct mbr_type * 268867d4347Skrw find_mbr_type(const int id) 269c96c378cSkrw { 270867d4347Skrw unsigned int i; 271c96c378cSkrw 272c96c378cSkrw for (i = 0; i < nitems(mbr_types); i++) { 273c96c378cSkrw if (mbr_types[i].mt_type == id) 274867d4347Skrw return &mbr_types[i]; 275c96c378cSkrw } 276c96c378cSkrw 277867d4347Skrw return NULL; 278c96c378cSkrw } 279c96c378cSkrw 280f458660aSkrw int 281f458660aSkrw uuid_attr(const struct uuid *uuid) 282f458660aSkrw { 283f458660aSkrw const struct gpt_type *gt; 284f458660aSkrw 285f458660aSkrw gt = find_gpt_type(uuid); 286f458660aSkrw if (gt == NULL) 287f458660aSkrw return 0; 288f458660aSkrw else 289f458660aSkrw return gt->gt_attr; 290f458660aSkrw } 291f2ec1a13Skrw 29295e8765cSkrw int 2932ea83235Skrw PRT_protected_guid(const struct uuid *uuid) 29495e8765cSkrw { 295f458660aSkrw const struct gpt_type *gt; 2968e294713Skrw unsigned int pn; 2978e294713Skrw 298f458660aSkrw gt = find_gpt_type(uuid); 299f458660aSkrw if (gt && gt->gt_attr & GTATTR_PROTECT) 300f458660aSkrw return 1; 30195e8765cSkrw 302e92bde66Skrw if (gt && strcasecmp(gt->gt_guid, EFI_SYSTEM_PARTITION_GUID) == 0) { 3032de77560Skrw for (pn = 0; pn < gh.gh_part_num; pn++) { 304f458660aSkrw if (uuid_attr(&gp[pn].gp_type) & GTATTR_PROTECT_EFISYS) 305f458660aSkrw return 1; 30695e8765cSkrw } 30765deb39bSkrw } 30895e8765cSkrw 3098e294713Skrw return 0; 31095e8765cSkrw } 31195e8765cSkrw 3124b464610Sderaadt void 313a0193349Skrw PRT_print_mbrmenu(char *lbuf, size_t lbuflen) 3144b464610Sderaadt { 31572c8f31dSkrw unsigned int cidx, i, idrows; 316d20bdfc6Skrw 3175308a554Skrw idrows = (nitems(mbr_types) + 3) / 4; 3184b464610Sderaadt 319c2ad5584Sderaadt printf("Choose from the following Partition id values:\n"); 320d20bdfc6Skrw for (i = 0; i < idrows; i++) { 32172c8f31dSkrw for (cidx = i; cidx < i + idrows * 3; cidx += idrows) { 32224a7e0ddSkrw printf("%02X %-15s", mbr_types[cidx].mt_type, 323934b6408Skrw mbr_types[cidx].mt_name); 32472c8f31dSkrw } 32572c8f31dSkrw if (cidx < nitems(mbr_types)) 32672c8f31dSkrw printf("%02X %s", mbr_types[cidx].mt_type, 327934b6408Skrw mbr_types[cidx].mt_name); 3285308a554Skrw printf("\n"); 3295308a554Skrw } 330a0193349Skrw 331a0193349Skrw memset(lbuf, 0, lbuflen); /* Just continue. */ 3325308a554Skrw } 3335308a554Skrw 3345308a554Skrw void 335a0193349Skrw PRT_print_gptmenu(char *lbuf, size_t lbuflen) 3365308a554Skrw { 33772c8f31dSkrw unsigned int cidx, i, idrows; 3385308a554Skrw 3395308a554Skrw idrows = (nitems(gpt_types) + 3) / 4; 3405308a554Skrw 3415308a554Skrw printf("Choose from the following Partition id values:\n"); 3425308a554Skrw for (i = 0; i < idrows; i++) { 34372c8f31dSkrw for (cidx = i; cidx < i + idrows * 3; cidx += idrows) { 344e3f6ba90Skrw printf("%02X %-15s", gpt_types[cidx].gt_menuid, 345934b6408Skrw gpt_types[cidx].gt_name); 34672c8f31dSkrw } 34772c8f31dSkrw if (cidx < nitems(gpt_types)) 348e3f6ba90Skrw printf("%02X %s", gpt_types[cidx].gt_menuid, 349934b6408Skrw gpt_types[cidx].gt_name); 3504b464610Sderaadt printf("\n"); 3514b464610Sderaadt } 352a0193349Skrw 353a0193349Skrw memset(lbuf, 0, lbuflen); /* Just continue. */ 354d20bdfc6Skrw } 355a1705421Sweingart 356a1705421Sweingart void 3570cd9e2afSkrw PRT_parse(const struct dos_partition *dp, const uint64_t lba_self, 3580cd9e2afSkrw const uint64_t lba_firstembr, struct prt *prt) 359a1705421Sweingart { 360ca2e86e1Sprovos off_t off; 361b87d3542Skrw uint32_t t; 362a1705421Sweingart 363ee38fe33Skrw prt->prt_flag = dp->dp_flag; 364ee38fe33Skrw prt->prt_id = dp->dp_typ; 365a1705421Sweingart 366ee38fe33Skrw if ((prt->prt_id == DOSPTYP_EXTEND) || (prt->prt_id == DOSPTYP_EXTENDL)) 367061e6e0aSkrw off = lba_firstembr; 368c3e3230dSderaadt else 369061e6e0aSkrw off = lba_self; 370ca2e86e1Sprovos 371ee38fe33Skrw memcpy(&t, &dp->dp_start, sizeof(uint32_t)); 372ee38fe33Skrw prt->prt_bs = letoh32(t) + off; 373ee38fe33Skrw memcpy(&t, &dp->dp_size, sizeof(uint32_t)); 374ee38fe33Skrw prt->prt_ns = letoh32(t); 375ee38fe33Skrw if (prt->prt_id == DOSPTYP_EFI && prt->prt_ns == UINT32_MAX) 376ee38fe33Skrw prt->prt_ns = DL_GETDSIZE(&dl) - prt->prt_bs; 3774ed7cd7eSrahnds } 37849241bdaSkrw 379a1705421Sweingart void 38099e0469cSkrw PRT_make(const struct prt *prt, const uint64_t lba_self, 38199e0469cSkrw const uint64_t lba_firstembr, struct dos_partition *dp) 382a1705421Sweingart { 38377392607Skrw struct chs start, end; 3840cd9e2afSkrw uint64_t off, t; 385c3e3230dSderaadt 3866aca8866Skrw if (prt->prt_ns == 0 || prt->prt_id == DOSPTYP_UNUSED) { 3876aca8866Skrw memset(dp, 0, sizeof(*dp)); 3886aca8866Skrw return; 3896aca8866Skrw } 3906aca8866Skrw 391ee38fe33Skrw if ((prt->prt_id == DOSPTYP_EXTEND) || (prt->prt_id == DOSPTYP_EXTENDL)) 392ee38fe33Skrw off = lba_firstembr; 393c3e3230dSderaadt else 394ee38fe33Skrw off = lba_self; 395a1705421Sweingart 39677392607Skrw if (PRT_lba_to_chs(prt, &start, &end) == 0) { 39777392607Skrw dp->dp_shd = start.chs_head & 0xFF; 39877392607Skrw dp->dp_ssect = (start.chs_sect & 0x3F) | ((start.chs_cyl & 0x300) >> 2); 39977392607Skrw dp->dp_scyl = start.chs_cyl & 0xFF; 40077392607Skrw dp->dp_ehd = end.chs_head & 0xFF; 40177392607Skrw dp->dp_esect = (end.chs_sect & 0x3F) | ((end.chs_cyl & 0x300) >> 2); 40277392607Skrw dp->dp_ecyl = end.chs_cyl & 0xFF; 4034ed7cd7eSrahnds } else { 404ee38fe33Skrw memset(dp, 0xFF, sizeof(*dp)); 4054ed7cd7eSrahnds } 406a1705421Sweingart 407ee38fe33Skrw dp->dp_flag = prt->prt_flag & 0xFF; 408ee38fe33Skrw dp->dp_typ = prt->prt_id & 0xFF; 40940b0f5f3Skrw 410ee38fe33Skrw t = htole64(prt->prt_bs - off); 411ee38fe33Skrw memcpy(&dp->dp_start, &t, sizeof(uint32_t)); 412ee38fe33Skrw if (prt->prt_id == DOSPTYP_EFI && (prt->prt_bs + prt->prt_ns) > 41398952941Skrw DL_GETDSIZE(&dl)) 41498952941Skrw t = htole64(UINT32_MAX); 41598952941Skrw else 416ee38fe33Skrw t = htole64(prt->prt_ns); 417ee38fe33Skrw memcpy(&dp->dp_size, &t, sizeof(uint32_t)); 4186d5e103bSkjell } 419a1705421Sweingart 420a1705421Sweingart void 4217b70791fSkrw PRT_print_parthdr(void) 422a1705421Sweingart { 423ba49db25Skrw printf(" Starting Ending " 424ba49db25Skrw " LBA Info:\n"); 425ba49db25Skrw printf(" #: id C H S - C H S " 426ba49db25Skrw "[ start: size ]\n"); 427ba49db25Skrw printf("---------------------------------------" 428ba49db25Skrw "----------------------------------------\n"); 4297b70791fSkrw } 4307b70791fSkrw 4317b70791fSkrw void 4327b70791fSkrw PRT_print_part(const int num, const struct prt *prt, const char *units) 4337b70791fSkrw { 4347b70791fSkrw const struct unit_type *ut; 435867d4347Skrw const struct mbr_type *mt; 43677392607Skrw struct chs start, end; 4377b70791fSkrw double size; 4387b70791fSkrw 4393e9b7d6bSkrw size = units_size(units, prt->prt_ns, &ut); 44077392607Skrw PRT_lba_to_chs(prt, &start, &end); 441867d4347Skrw mt = find_mbr_type(prt->prt_id); 44277392607Skrw 44377392607Skrw printf("%c%1d: %.2X %6llu %3u %3u - %6llu %3u %3u " 444ba49db25Skrw "[%12llu:%12.0f%s] %s\n", 445ee38fe33Skrw (prt->prt_flag == DOSACTIVE)?'*':' ', 446ee38fe33Skrw num, prt->prt_id, 44777392607Skrw start.chs_cyl, start.chs_head, start.chs_sect, 44877392607Skrw end.chs_cyl, end.chs_head, end.chs_sect, 449867d4347Skrw prt->prt_bs, size, ut->ut_abbr, mt ? mt->mt_name : "<Unknown ID>"); 45062718823Skrw 45162718823Skrw if (prt->prt_bs >= DL_GETDSIZE(&dl)) 45262718823Skrw printf("partition %d starts beyond the end of %s\n", num, 45362718823Skrw disk.dk_name); 45462718823Skrw else if (prt->prt_bs + prt->prt_ns > DL_GETDSIZE(&dl)) 45562718823Skrw printf("partition %d extends beyond the end of %s\n", num, 45662718823Skrw disk.dk_name); 457a1705421Sweingart } 458a1705421Sweingart 45977392607Skrw int 46077392607Skrw PRT_lba_to_chs(const struct prt *prt, struct chs *start, struct chs *end) 461a1705421Sweingart { 46277392607Skrw uint64_t lba; 463a1705421Sweingart 46477392607Skrw if (prt->prt_ns == 0 || prt->prt_id == DOSPTYP_UNUSED) { 46577392607Skrw memset(start, 0, sizeof(*start)); 46677392607Skrw memset(end, 0, sizeof(*end)); 46777392607Skrw return -1; 468eb4cb19dSkjell } 469eb4cb19dSkjell 47077392607Skrw /* 47177392607Skrw * C = LBA ÷ (HPC × SPT) 47277392607Skrw * H = (LBA ÷ SPT) mod HPC 47377392607Skrw * S = (LBA mod SPT) + 1 47477392607Skrw */ 475a1705421Sweingart 47677392607Skrw lba = prt->prt_bs; 47777392607Skrw start->chs_cyl = lba / (disk.dk_sectors * disk.dk_heads); 47877392607Skrw start->chs_head = (lba / disk.dk_sectors) % disk.dk_heads; 47977392607Skrw start->chs_sect = (lba % disk.dk_sectors) + 1; 480a1705421Sweingart 48177392607Skrw lba = prt->prt_bs + prt->prt_ns - 1; 48277392607Skrw end->chs_cyl = lba / (disk.dk_sectors * disk.dk_heads); 48377392607Skrw end->chs_head = (lba / disk.dk_sectors) % disk.dk_heads; 48477392607Skrw end->chs_sect = (lba % disk.dk_sectors) + 1; 485a1705421Sweingart 48677392607Skrw if (start->chs_head > 255 || end->chs_head > 255 || 48777392607Skrw start->chs_sect > 63 || end->chs_sect > 63 || 48877392607Skrw start->chs_cyl > 1023 || end->chs_cyl > 1023) 48977392607Skrw return -1; 490a1705421Sweingart 49177392607Skrw return 0; 492a1705421Sweingart } 493fba7235cSkrw 494f2ec1a13Skrw const char * 495934b6408Skrw PRT_uuid_to_name(const struct uuid *uuid) 496f2ec1a13Skrw { 497f2ec1a13Skrw static char typename[UUID_STR_LEN + 1]; 4985c01edd6Skrw const uint8_t gpt_uuid_msdos[] = GPT_UUID_MSDOS; 4995c01edd6Skrw struct uuid uuid_msdos; 500f2ec1a13Skrw const struct gpt_type *gt; 501f2ec1a13Skrw char *uuidstr; 502351f0068Skrw uint32_t status; 503f2ec1a13Skrw 5045c01edd6Skrw uuid_dec_be(gpt_uuid_msdos, &uuid_msdos); 5055c01edd6Skrw if (uuid_compare(&uuid_msdos, uuid, NULL) == 0) 5065c01edd6Skrw return "Microsoft basic data"; 507f2ec1a13Skrw 508f2ec1a13Skrw gt = find_gpt_type(uuid); 5095c01edd6Skrw if (gt != NULL) 510934b6408Skrw return gt->gt_name; 5115c01edd6Skrw 512f2ec1a13Skrw uuid_to_string(uuid, &uuidstr, &status); 513f2ec1a13Skrw if (status == uuid_s_ok) 514f2ec1a13Skrw strlcpy(typename, uuidstr, sizeof(typename)); 5155c01edd6Skrw else 5165c01edd6Skrw typename[0] = '\0'; 517f2ec1a13Skrw free(uuidstr); 518f2ec1a13Skrw 519f2ec1a13Skrw return typename; 520fba7235cSkrw } 521fba7235cSkrw 522145e5a87Stim int 523e3f6ba90Skrw PRT_uuid_to_menuid(const struct uuid *uuid) 524145e5a87Stim { 525f2ec1a13Skrw const struct gpt_type *gt; 526145e5a87Stim 527f2ec1a13Skrw gt = find_gpt_type(uuid); 528f2ec1a13Skrw if (gt == NULL) 52943277e5dSkrw return -1; 530f2ec1a13Skrw else 531e3f6ba90Skrw return gt->gt_menuid; 532145e5a87Stim } 533145e5a87Stim 534e48f25a4Skrw const struct uuid * 535e3f6ba90Skrw PRT_menuid_to_guid(const int menuid) 536fba7235cSkrw { 537fba7235cSkrw static struct uuid guid; 5387403d590Skrw int i; 539351f0068Skrw uint32_t status = uuid_s_ok; 540fba7235cSkrw 5417403d590Skrw for (i = 0; i < nitems(gpt_types); i++) { 5427403d590Skrw if (gpt_types[i].gt_menuid == menuid) { 5437403d590Skrw uuid_from_string(gpt_types[i].gt_guid, &guid, &status); 544fba7235cSkrw break; 545fba7235cSkrw } 5467403d590Skrw } 5477403d590Skrw if (i == nitems(gpt_types) || status != uuid_s_ok) 548482578bcSkrw uuid_create_nil(&guid, NULL); 549fba7235cSkrw 5502a536aa2Skrw return &guid; 551fba7235cSkrw } 552