blob: 85ce6b0c778b2cb3f006bb6bbb612317dca2d7b4 [file] [log] [blame]
srs5694e7b4ff92009-08-18 13:16:10 -04001// parttypes.cc
2// Class to manage partition type codes -- a slight variant on MBR type
3// codes, GUID type codes, and associated names.
4
srs5694221e0872009-08-29 15:00:31 -04005/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
6 under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
7
srs5694e7b4ff92009-08-18 13:16:10 -04008#define __STDC_LIMIT_MACROS
9#define __STDC_CONSTANT_MACROS
10
11#include <string.h>
12#include <stdint.h>
13#include <stdio.h>
srs5694fed16d02010-01-27 23:03:40 -050014#include <iostream>
srs5694e7b4ff92009-08-18 13:16:10 -040015#include "parttypes.h"
16
17using namespace std;
18
19int PartTypes::numInstances = 0;
20AType* PartTypes::allTypes = NULL;
21AType* PartTypes::lastType = NULL;
22
23// Constructor. Its main task is to initialize the data list, but only
24// if this is the first instance, since it's a static linked list.
25// Partition type codes are MBR type codes multiplied by 0x0100, with
26// additional related codes taking on following numbers. For instance,
27// the FreeBSD disklabel code in MBR is 0xa5; here, it's 0xa500, with
28// additional FreeBSD codes being 0xa501, 0xa502, and so on. This gives
29// related codes similar numbers and (given appropriate entry positions
30// in the linked list) keeps them together in the listings generated
31// by typing "L" at the main gdisk menu.
32// See http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
33// for a list of MBR partition type codes.
34PartTypes::PartTypes(void) {
35
36 numInstances++;
37 if (numInstances == 1) {
38
39 // Start with the "unused entry," which should normally appear only
40 // on empty partition table entries....
41 AddType(0x0000, UINT64_C(0x0000000000000000), UINT64_C(0x0000000000000000),
42 "Unused entry", 0);
43
44 // DOS/Windows partition types, which confusingly Linux also uses in GPT
45 AddType(0x0100, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
46 "Linux/Windows data", 0); // FAT-12
47 AddType(0x0400, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
48 "Linux/Windows data", 0); // FAT-16 < 32M
49 AddType(0x0600, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
50 "Linux/Windows data", 0); // FAT-16
51 AddType(0x0700, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
52 "Linux/Windows data", 1); // NTFS (or could be HPFS)
53 AddType(0x0b00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
54 "Linux/Windows data", 0); // FAT-32
55 AddType(0x0c00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
56 "Linux/Windows data", 0); // FAT-32 LBA
57 AddType(0x0c01, UINT64_C(0x4DB80B5CE3C9E316), UINT64_C(0xAE1502F02DF97D81),
58 "Microsoft Reserved"); // Microsoft reserved
59 AddType(0x0e00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
60 "Linux/Windows data", 0); // FAT-16 LBA
61 AddType(0x1100, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
62 "Linux/Windows data", 0); // Hidden FAT-12
63 AddType(0x1400, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
64 "Linux/Windows data", 0); // Hidden FAT-16 < 32M
65 AddType(0x1600, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
66 "Linux/Windows data", 0); // Hidden FAT-16
67 AddType(0x1700, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
68 "Linux/Windows data", 0); // Hidden NTFS (or could be HPFS)
69 AddType(0x1b00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
70 "Linux/Windows data", 0); // Hidden FAT-32
71 AddType(0x1c00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
72 "Linux/Windows data", 0); // Hidden FAT-32 LBA
73 AddType(0x1e00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
74 "Linux/Windows data", 0); // Hidden FAT-16 LBA
75 AddType(0x2700, UINT64_C(0x4D4006D1DE94BBA4), UINT64_C(0xACD67901D5BF6AA1),
76 "Windows RE"); // Windows RE
77 AddType(0x4200, UINT64_C(0x4F621431Af9B60A0), UINT64_C(0xAD694A71113368BC),
78 "Windows LDM data"); // Logical disk manager
79 AddType(0x4201, UINT64_C(0x42E07E8F5808C8AA), UINT64_C(0xB3CF3404E9E1D285),
80 "Windows LDM metadata"); // Logical disk manager
81
82 // Linux-specific partition types....
83 AddType(0x8200, UINT64_C(0x43C4A4AB0657FD6D), UINT64_C(0x4F4F4BC83309E584),
84 "Linux swap"); // Linux swap (or could be Solaris)
85 AddType(0x8300, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
86 "Linux/Windows data", 0); // Linux native
87 AddType(0x8301, UINT64_C(0x60C000078DA63339), UINT64_C(0x080923C83A0836C4),
88 "Linux Reserved"); // Linux reserved
89 AddType(0x8e00, UINT64_C(0x44C2F507E6D6D379), UINT64_C(0x28F93D2A8F233CA2),
90 "Linux LVM"); // Linux LVM
91
92 // FreeBSD partition types....
93 // Note: Rather than extract FreeBSD disklabel data, convert FreeBSD
94 // partitions in-place, and let FreeBSD sort out the details....
95 AddType(0xa500, UINT64_C(0x11D66ECF516E7CB4), UINT64_C(0x2B71092D0200F88F),
96 "FreeBSD disklabel"); // FreeBSD disklabel
97 AddType(0xa501, UINT64_C(0x11DC7F4183BD6B9D), UINT64_C(0x0F4FB86015000BBE),
98 "FreeBSD boot"); // FreeBSD boot
99 AddType(0xa502, UINT64_C(0x11D66ECF516E7CB5), UINT64_C(0x2B71092D0200F88F),
100 "FreeBSD swap"); // FreeBSD swap
101 AddType(0xa503, UINT64_C(0x11D66ECF516E7CB6), UINT64_C(0x2B71092D0200F88F),
102 "FreeBSD UFS"); // FreeBSD UFS
103 AddType(0xa504, UINT64_C(0x11D66ECF516E7CBA), UINT64_C(0x2B71092D0200F88F),
104 "FreeBSD ZFS"); // FreeBSD ZFS
105 AddType(0xa505, UINT64_C(0x11D66ECF516E7CB8), UINT64_C(0x2B71092D0200F88F),
106 "FreeBSD Vinum/RAID"); // FreeBSD Vinum
107
108 // A MacOS partition type, separated from others by NetBSD partition types...
109 AddType(0xa800, UINT64_C(0x11AA000055465300), UINT64_C(0xACEC4365300011AA),
110 "Apple UFS"); // MacOS X
111
112 // NetBSD partition types. Note that the main entry sets it up as a
113 // FreeBSD disklabel. I'm not 100% certain this is the correct behavior.
114 AddType(0xa900, UINT64_C(0x11D66ECF516E7CB4), UINT64_C(0x2B71092D0200F88F),
115 "FreeBSD disklabel", 0); // NetBSD disklabel
116 AddType(0xa901, UINT64_C(0x11DCB10E49F48D32), UINT64_C(0x489687D119009BB9),
117 "NetBSD swap");
118 AddType(0xa902, UINT64_C(0x11DCB10E49F48D5A), UINT64_C(0x489687D119009BB9),
119 "NetBSD FFS");
120 AddType(0xa903, UINT64_C(0x11DCB10E49F48D82), UINT64_C(0x489687D119009BB9),
121 "NetBSD LFS");
122 AddType(0xa903, UINT64_C(0x11DCB10E49F48DAA), UINT64_C(0x489687D119009BB9),
123 "NetBSD RAID");
124 AddType(0xa904, UINT64_C(0x11DCB10F2DB519C4), UINT64_C(0x489687D119009BB9),
125 "NetBSD concatenated");
126 AddType(0xa905, UINT64_C(0x11DCB10F2DB519EC), UINT64_C(0x489687D119009BB9),
127 "NetBSD encrypted");
128
129 // MacOS partition types (See also 0xa800, above)....
130 AddType(0xab00, UINT64_C(0x11AA0000426F6F74), UINT64_C(0xACEC4365300011AA),
131 "Apple boot"); // MacOS X
132 AddType(0xaf00, UINT64_C(0x11AA000048465300), UINT64_C(0xACEC4365300011AA),
133 "Apple HFS/HFS+"); // MacOS X
134 AddType(0xaf01, UINT64_C(0x11AA000052414944), UINT64_C(0xACEC4365300011AA),
135 "Apple RAID"); // MacOS X
136 AddType(0xaf02, UINT64_C(0x11AA5F4F52414944), UINT64_C(0xACEC4365300011AA),
137 "Apple RAID offline"); // MacOS X
138 AddType(0xaf03, UINT64_C(0x11AA6C004C616265), UINT64_C(0xACEC4365300011AA),
139 "Apple label"); // MacOS X
140 AddType(0xaf04, UINT64_C(0x11AA76655265636F), UINT64_C(0xACEC4365300011AA),
141 "AppleTV recovery"); // MacOS X
142
143 // Solaris partition types (one of which is shared with MacOS)
144 AddType(0xbe00, UINT64_C(0x11B21DD26A82CB45), UINT64_C(0x316673200008A699),
145 "Solaris boot"); // Solaris boot
146 AddType(0xbf00, UINT64_C(0x11B21DD26a85CF4D), UINT64_C(0x316673200008A699),
147 "Solaris root"); // Solaris root
148 AddType(0xbf01, UINT64_C(0x11B21DD26A898CC3), UINT64_C(0x316673200008A699),
149 "Solaris /usr & Mac ZFS"); // MacOS X & Solaris
150 AddType(0xbf02, UINT64_C(0x11B21DD26A87C46F), UINT64_C(0x316673200008A699),
151 "Solaris swap");
152 AddType(0xbf03, UINT64_C(0x11B21DD26A8B642B), UINT64_C(0x316673200008A699),
153 "Solaris backup");
154 AddType(0xbf04, UINT64_C(0x11B21DD26A8EF2E9), UINT64_C(0x316673200008A699),
155 "Solaris /var");
156 AddType(0xbf05, UINT64_C(0x11B21DD26A90BA39), UINT64_C(0x316673200008A699),
157 "Solaris /home");
158 AddType(0xbf05, UINT64_C(0x11B21DD26A9283A5), UINT64_C(0x316673200008A699),
159 "Solaris EFI_ALTSCTR");
160 AddType(0xbf06, UINT64_C(0x11B21DD26A945A3B), UINT64_C(0x316673200008A699),
161 "Solaris Reserved 1");
162 AddType(0xbf07, UINT64_C(0x11B21DD26A9630D1), UINT64_C(0x316673200008A699),
163 "Solaris Reserved 2");
164 AddType(0xbf08, UINT64_C(0x11B21DD26A980767), UINT64_C(0x316673200008A699),
165 "Solaris Reserved 3");
166 AddType(0xbf09, UINT64_C(0x11B21DD26A96237F), UINT64_C(0x316673200008A699),
167 "Solaris Reserved 4");
168 AddType(0xbf0a, UINT64_C(0x11B21DD26A8D2AC7), UINT64_C(0x316673200008A699),
169 "Solaris Reserved 5");
170
171 // I can find no MBR equivalents for these, but they're on the
172 // Wikipedia page for GPT, so here we go....
173 AddType(0xc001, UINT64_C(0x11D33AEB75894C1E), UINT64_C(0x000000A0037BC1B7),
174 "HP-UX data");
175 AddType(0xc002, UINT64_C(0x11D632E3E2A1E728), UINT64_C(0x000000A0037B82A6),
176 "HP-UX service");
177
178 // EFI system and related partitions
179 AddType(0xEF00, UINT64_C(0x11d2f81fc12a7328), UINT64_C(0x3bc93ec9a0004bba),
180 "EFI System"); // EFI System (parted marks Linux boot
181 // partitions like this)
182 AddType(0xEF01, UINT64_C(0x11d333e7024dee41), UINT64_C(0x9FF381C70800699d),
srs5694978041c2009-09-21 20:51:47 -0400183 "MBR partition scheme"); // Used to nest an MBR table on a GPT disk
srs5694e7b4ff92009-08-18 13:16:10 -0400184 AddType(0xEF02, UINT64_C(0x6E6F644921686148), UINT64_C(0x4946456465654E74),
185 "BIOS boot partition"); //
186
187 // A straggler Linux partition type....
188 AddType(0xfd00, UINT64_C(0x4D3B05FCA19D880F), UINT64_C(0x1E91840F3F7406A0),
189 "Linux RAID"); // Linux RAID
190 } // if
191} // default constructor
192
193PartTypes::~PartTypes(void) {
194 AType* tempType;
195
196 numInstances--;
197 if (numInstances == 0) {
198 while (allTypes != NULL) {
199 tempType = allTypes;
200 allTypes = allTypes->next;
201 delete tempType;
202 } // while
203 } // if
204} // destructor
205
206// Add a single type to the linked list of types. Returns 1 if operation
srs5694e321d442010-01-29 17:44:04 -0500207// succeeds, 0 otherwise.
srs5694e7b4ff92009-08-18 13:16:10 -0400208int PartTypes::AddType(uint16_t mbrType, uint64_t guidData1, uint64_t guidData2,
srs5694e321d442010-01-29 17:44:04 -0500209 const char * n, int toDisplay) {
srs5694e7b4ff92009-08-18 13:16:10 -0400210 AType* tempType;
211 int allOK = 1;
212
213 tempType = new AType;
214 if (tempType != NULL) {
215 tempType->MBRType = mbrType;
216 tempType->GUIDType.data1 = guidData1;
217 tempType->GUIDType.data2 = guidData2;
srs5694e321d442010-01-29 17:44:04 -0500218 tempType->name = n;
srs5694e7b4ff92009-08-18 13:16:10 -0400219 tempType->display = toDisplay;
220 tempType->next = NULL;
221 if (allTypes == NULL) { // first entry
222 allTypes = tempType;
223 } else {
224 lastType->next = tempType;
225 } // if/else
226 lastType = tempType;
227 } else {
228 allOK = 0;
229 } // if/else
230 return allOK;
231} // PartTypes::AddType()
232
233// Displays the available types and my extended MBR codes for same....
234// Note: This function assumes an 80-column display. On wider displays,
235// it stops at under 80 columns; on narrower displays, lines will wrap
236// in an ugly way.
237void PartTypes::ShowTypes(void) {
238 int colCount = 1; // column count
srs5694e321d442010-01-29 17:44:04 -0500239 size_t i;
srs5694e7b4ff92009-08-18 13:16:10 -0400240 AType* thisType = allTypes;
srs5694e7b4ff92009-08-18 13:16:10 -0400241
srs5694fed16d02010-01-27 23:03:40 -0500242 cout.unsetf(ios::uppercase);
srs5694e7b4ff92009-08-18 13:16:10 -0400243 while (thisType != NULL) {
244 if (thisType->display == 1) { // show it
srs5694fed16d02010-01-27 23:03:40 -0500245 cout.fill('0');
246 cout.width(4);
247 cout << hex << thisType->MBRType << " ";
srs5694e321d442010-01-29 17:44:04 -0500248 cout << thisType->name.substr(0, 20);
249 for (i = 0; i < (20 - (thisType->name.substr(0, 20).length())); i++) cout << " ";
srs5694e7b4ff92009-08-18 13:16:10 -0400250 if ((colCount % 3) == 0)
srs5694fed16d02010-01-27 23:03:40 -0500251 cout << "\n";
srs5694e321d442010-01-29 17:44:04 -0500252 else
253 cout << " ";
srs5694e7b4ff92009-08-18 13:16:10 -0400254 colCount++;
255 } // if
256 thisType = thisType->next;
257 } // while
srs56940a697312010-01-28 21:10:52 -0500258 cout.fill(' ');
259 cout << "\n" << dec;
srs5694e7b4ff92009-08-18 13:16:10 -0400260} // PartTypes::ShowTypes()
261
262// Returns 1 if code is a valid extended MBR code, 0 if it's not
263int PartTypes::Valid(uint16_t code) {
264 AType* thisType = allTypes;
265 int found = 0;
266
267 while ((thisType != NULL) && (!found)) {
268 if (thisType->MBRType == code) {
269 found = 1;
270 } // if
271 thisType = thisType->next;
272 } // while
273 return found;
274} // PartTypes::Valid()
275
276// Convert a GUID code to a name.
srs5694fed16d02010-01-27 23:03:40 -0500277string PartTypes::GUIDToName(struct GUIDData typeCode) {
srs5694e7b4ff92009-08-18 13:16:10 -0400278 AType* theItem = allTypes;
279 int found = 0;
srs5694fed16d02010-01-27 23:03:40 -0500280 string typeName;
srs5694e7b4ff92009-08-18 13:16:10 -0400281
282 while ((theItem != NULL) && (!found)) {
283 if ((theItem->GUIDType.data1 == typeCode.data1) &&
284 (theItem->GUIDType.data2 == typeCode.data2)) { // found it!
srs5694fed16d02010-01-27 23:03:40 -0500285 typeName = theItem->name;
srs5694e7b4ff92009-08-18 13:16:10 -0400286 found = 1;
287 } else {
288 theItem = theItem->next;
289 } // if/else
290 } // while
291 if (!found) {
srs5694fed16d02010-01-27 23:03:40 -0500292 typeName = "Unknown";
srs5694e7b4ff92009-08-18 13:16:10 -0400293 } // if (!found)
294 return typeName;
295} // PartTypes::GUIDToName()
296
297// This function takes a variant of the MBR partition type code and
298// converts it to a GUID type code
299struct GUIDData PartTypes::IDToGUID(uint16_t ID) {
300 AType* theItem = allTypes;
301 int found = 0;
302 struct GUIDData theGUID;
303
srs5694e35eb1b2009-09-14 00:29:34 -0400304 // Start by assigning a default GUID for the return value. Done
305 // "raw" to avoid the necessity for a recursive call and the
306 // remote possibility of an infinite recursive loop that this
307 // approach would present....
308 theGUID.data1 = UINT64_C(0x4433B9E5EBD0A0A2);
309 theGUID.data2 = UINT64_C(0xC79926B7B668C087);
310
311 // Now search the type list for a match to the ID....
srs5694e7b4ff92009-08-18 13:16:10 -0400312 while ((theItem != NULL) && (!found)) {
313 if (theItem->MBRType == ID) { // found it!
314 theGUID = theItem->GUIDType;
315 found = 1;
316 } else {
317 theItem = theItem->next;
318 } // if/else
319 } // while
320 if (!found) {
srs5694fed16d02010-01-27 23:03:40 -0500321 cout.setf(ios::uppercase);
322 cout.fill('0');
323 cout << "Exact type match not found for type code ";
324 cout.width(4);
325 cout << hex << ID << "; assigning type code for\n'Linux/Windows data'\n" << dec;
srs56940a697312010-01-28 21:10:52 -0500326 cout.fill(' ');
srs5694e7b4ff92009-08-18 13:16:10 -0400327 } // if (!found)
328 return theGUID;
329} // PartTypes::IDToGUID()
330
331// Convert a GUID to a 16-bit variant of the MBR ID number.
332// Note that this function ignores entries for which the display variable
333// is set to 0. This enables control of which values get returned when
334// there are multiple possibilities, but opens the algorithm up to the
335// potential for problems should the data in the list be bad.
336uint16_t PartTypes::GUIDToID(struct GUIDData typeCode) {
337 AType* theItem = allTypes;
338 int found = 0;
srs5694e35eb1b2009-09-14 00:29:34 -0400339 uint16_t theID = 0xFFFF;
srs5694e7b4ff92009-08-18 13:16:10 -0400340
341 while ((theItem != NULL) && (!found)) {
342 if ((theItem->GUIDType.data1 == typeCode.data1) &&
343 (theItem->GUIDType.data2 == typeCode.data2) &&
344 (theItem->display == 1)) { // found it!
345 theID = theItem->MBRType;
346 found = 1;
347 } else {
348 theItem = theItem->next;
349 } // if/else
350 } // while
351 if (!found) {
352 theID = 0xFFFF;
353 } // if (!found)
354 return theID;
355} // PartTypes::GUIDToID()