/src/sleuthkit/tsk/vs/gpt.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * The Sleuth Kit |
3 | | * |
4 | | * Brian Carrier [carrier <at> sleuthkit [dot] org] |
5 | | * Copyright (c) 2006-2011 Brian Carrier, Basis Technology. All rights reserved |
6 | | * Copyright (c) 2004-2005 Brian Carrier. All rights reserved |
7 | | * |
8 | | * This software is distributed under the Common Public License 1.0 |
9 | | */ |
10 | | |
11 | | /** \file gpt.c |
12 | | * The internal functions required to process the GPT GUID Partiition Table. |
13 | | */ |
14 | | #include "tsk_vs_i.h" |
15 | | #include "tsk_gpt.h" |
16 | | #include "tsk_dos.h" |
17 | | |
18 | | |
19 | | /** |
20 | | * Check if GUID matches a given value. |
21 | | * |
22 | | * @param g The GUID to match. |
23 | | * @param d1 First 4 bytes of the given value. |
24 | | * @param d2 Next 2 bytes of the given value following d1. |
25 | | * @param d3 Next 2 bytes of the given value following d2. |
26 | | * @param d4 Next 8 bytes of the given value following d3. |
27 | | * @returns 1 if they match, 0 if they do not. |
28 | | * |
29 | | */ |
30 | | static int |
31 | | gpt_guid_match(gpt_guid * g, uint32_t d1, uint16_t d2, uint16_t d3, uint64_t d4) |
32 | 0 | { |
33 | 0 | if(g->data_1 != d1 || g->data_2 != d2 || g->data_3 != d3) |
34 | 0 | return 0; |
35 | | |
36 | 0 | uint64_t p4 = (uint64_t)g->data_4[0]; |
37 | 0 | int i; |
38 | 0 | for(i=1; i<8; ++i){ |
39 | 0 | p4 = p4 << 8; |
40 | 0 | p4 += (uint64_t)g->data_4[i]; |
41 | 0 | } |
42 | |
|
43 | 0 | if(p4 != d4) |
44 | 0 | return 0; |
45 | 0 | else |
46 | 0 | return 1; |
47 | 0 | } |
48 | | |
49 | | |
50 | | |
51 | | /** |
52 | | * |
53 | | * Get partition type by reading GUID value. |
54 | | * Source: https://en.wikipedia.org/wiki/GUID_Partition_Table |
55 | | * |
56 | | * @param desc C-string to store the description. |
57 | | * @param g Type GUID to compare. |
58 | | * @returns 1 if matched type found, 0 if not. |
59 | | * |
60 | | */ |
61 | | static int |
62 | | gpt_guid_type(char * desc, gpt_guid * g) |
63 | 0 | { |
64 | 0 | if(gpt_guid_match(g, 0, 0, 0, 0)) |
65 | 0 | snprintf(desc, GUID_DESC_LEN, "Unused entry"); |
66 | 0 | else if(gpt_guid_match(g, 0x024DEE41, 0x33E7, 0x11D3, 0x9D690008C781F39F)) |
67 | 0 | snprintf(desc, GUID_DESC_LEN, "MBR partition scheme"); |
68 | 0 | else if(gpt_guid_match(g, 0xC12A7328, 0xF81F, 0x11D2, 0xBA4B00A0C93EC93B)) |
69 | 0 | snprintf(desc, GUID_DESC_LEN, "EFI System partition"); |
70 | 0 | else if(gpt_guid_match(g, 0x21686148, 0x6449, 0x6E6F, 0x744E656564454649)) |
71 | 0 | snprintf(desc, GUID_DESC_LEN, "BIOS Boot partition"); |
72 | 0 | else if(gpt_guid_match(g, 0xD3BFE2DE, 0x3DAF, 0x11DF, 0xBA40E3A556D89593)) |
73 | 0 | snprintf(desc, GUID_DESC_LEN, "Intel Fast Flash partition"); |
74 | 0 | else if(gpt_guid_match(g, 0xF4019732, 0x066E, 0x4E12, 0x8273346C5641494F)) |
75 | 0 | snprintf(desc, GUID_DESC_LEN, "Sony boot partition"); |
76 | 0 | else if(gpt_guid_match(g, 0xBFBFAFE7, 0xA34F, 0x448A, 0x9A5B6213EB736C22)) |
77 | 0 | snprintf(desc, GUID_DESC_LEN, "Lenovo boot partition"); |
78 | | |
79 | 0 | else if(gpt_guid_match(g, 0xE3C9E316, 0x0B5C, 0x4DB8, 0x817DF92DF00215AE)) |
80 | 0 | snprintf(desc, GUID_DESC_LEN, "Microsoft Reserved Partition"); |
81 | 0 | else if(gpt_guid_match(g, 0xDE94BBA4, 0x06D1, 0x4D40, 0xA16ABFD50179D6AC)) |
82 | 0 | snprintf(desc, GUID_DESC_LEN, "Windows Recovery Environment"); |
83 | 0 | else if(gpt_guid_match(g, 0xEBD0A0A2, 0xB9E5, 0x4433, 0x87C068B6B72699C7)) |
84 | 0 | snprintf(desc, GUID_DESC_LEN, "Basic data partition"); |
85 | 0 | else if(gpt_guid_match(g, 0x5808C8AA, 0x7E8F, 0x42E0, 0x85D2E1E90434CFB3)) |
86 | 0 | snprintf(desc, GUID_DESC_LEN, "Logical Disk Manager metadata partition"); |
87 | 0 | else if(gpt_guid_match(g, 0xAF9B60A0, 0x1431, 0x4F62, 0xBC683311714A69AD)) |
88 | 0 | snprintf(desc, GUID_DESC_LEN, "Logical Disk Manager data partition"); |
89 | 0 | else if(gpt_guid_match(g, 0x37AFFC90, 0xEF7D, 0x4E96, 0x91C32D7AE055B174)) |
90 | 0 | snprintf(desc, GUID_DESC_LEN, "GPFS partition"); |
91 | 0 | else if(gpt_guid_match(g, 0xE75CAF8F, 0xF680, 0x4CEE, 0xAFA3B001E56EFC2D)) |
92 | 0 | snprintf(desc, GUID_DESC_LEN, "Storage Spaces partition"); |
93 | | |
94 | 0 | else if(gpt_guid_match(g, 0x75894C1E, 0x3AEB, 0x11D3, 0xB7C17B03A0000000)) |
95 | 0 | snprintf(desc, GUID_DESC_LEN, "HP-UX Data partition"); |
96 | 0 | else if(gpt_guid_match(g, 0xE2A1E728, 0x32E3, 0x11D6, 0xA6827B03A0000000)) |
97 | 0 | snprintf(desc, GUID_DESC_LEN, "HP-UX Data partition"); |
98 | | |
99 | 0 | else if(gpt_guid_match(g, 0x0FC63DAF, 0x8483, 0x4772, 0x8E793D69D8477DE4)) |
100 | 0 | snprintf(desc, GUID_DESC_LEN, "Linux filesystem data"); |
101 | 0 | else if(gpt_guid_match(g, 0xA19D880F, 0x05FC, 0x4D3B, 0xA006743F0F84911E)) |
102 | 0 | snprintf(desc, GUID_DESC_LEN, "Linux RAID partition"); |
103 | 0 | else if(gpt_guid_match(g, 0x44479540, 0xF297, 0x41B2, 0x9AF7D131D5F0458A)) |
104 | 0 | snprintf(desc, GUID_DESC_LEN, "Linux Root partition (x86)"); |
105 | 0 | else if(gpt_guid_match(g, 0x4F68BCE3, 0xE8CD, 0x4DB1, 0x96E7FBCAF984B709)) |
106 | 0 | snprintf(desc, GUID_DESC_LEN, "Linux Root partition (x86-64)"); |
107 | 0 | else if(gpt_guid_match(g, 0x69DAD710, 0x2CE4, 0x4E3C, 0xB16C21A1D49ABED3)) |
108 | 0 | snprintf(desc, GUID_DESC_LEN, "Linux Root partition (32-bit ARM)"); |
109 | 0 | else if(gpt_guid_match(g, 0x0657FD6D, 0xA4AB, 0x43C4, 0x84E50933C84B4F4F)) |
110 | 0 | snprintf(desc, GUID_DESC_LEN, "Linux swap partition"); |
111 | 0 | else if(gpt_guid_match(g, 0x933AC7E1, 0x2EB4, 0x4F13, 0xB8440E14E2AEF915)) |
112 | 0 | snprintf(desc, GUID_DESC_LEN, "Linux /home partition"); |
113 | 0 | else if(gpt_guid_match(g, 0x3B8F8425, 0x20E0, 0x4F3B, 0x907F1A25A76F98E8)) |
114 | 0 | snprintf(desc, GUID_DESC_LEN, "/srv (server data) partition"); |
115 | 0 | else if(gpt_guid_match(g, 0x7FFEC5C9, 0x2D00, 0x49B7, 0x89413EA10A5586B7)) |
116 | 0 | snprintf(desc, GUID_DESC_LEN, "Plain dm-crypt partition"); |
117 | 0 | else if(gpt_guid_match(g, 0xCA7D7CCB, 0x63ED, 0x4C53, 0x861C1742536059CC)) |
118 | 0 | snprintf(desc, GUID_DESC_LEN, "LUKS partition"); |
119 | 0 | else if(gpt_guid_match(g, 0x8DA63339, 0x0007, 0x60C0, 0xC436083AC8230908)) |
120 | 0 | snprintf(desc, GUID_DESC_LEN, "Reserved"); |
121 | | |
122 | 0 | else if(gpt_guid_match(g, 0x83BD6B9D, 0x7F41, 0x11DC, 0xBE0B001560B84F0F)) |
123 | 0 | snprintf(desc, GUID_DESC_LEN, "FreeBSD Boot partition"); |
124 | 0 | else if(gpt_guid_match(g, 0x516E7CB4, 0x6ECF, 0x11D6, 0x8FF800022D09712B)) |
125 | 0 | snprintf(desc, GUID_DESC_LEN, "FreeBSD Data partition"); |
126 | 0 | else if(gpt_guid_match(g, 0x516E7CB5, 0x6ECF, 0x11D6, 0x8FF800022D09712B)) |
127 | 0 | snprintf(desc, GUID_DESC_LEN, "FreeBSD Swap partition"); |
128 | 0 | else if(gpt_guid_match(g, 0x516E7CB6, 0x6ECF, 0x11D6, 0x8FF800022D09712B)) |
129 | 0 | snprintf(desc, GUID_DESC_LEN, "FreeBSD Unix File System (UFS) partition"); |
130 | 0 | else if(gpt_guid_match(g, 0x516E7CB8, 0x6ECF, 0x11D6, 0x8FF800022D09712B)) |
131 | 0 | snprintf(desc, GUID_DESC_LEN, "FreeBSD Vinum volume manager partition"); |
132 | 0 | else if(gpt_guid_match(g, 0x516E7CBA, 0x6ECF, 0x11D6, 0x8FF800022D09712B)) |
133 | 0 | snprintf(desc, GUID_DESC_LEN, "FreeBSD ZFS partition"); |
134 | | |
135 | 0 | else if(gpt_guid_match(g, 0x48465300, 0x0000, 0x11AA, 0xAA1100306543ECAC)) |
136 | 0 | snprintf(desc, GUID_DESC_LEN, "OS X Hierarchical File System Plus (HFS+) partition"); |
137 | 0 | else if(gpt_guid_match(g, 0x55465300, 0x0000, 0x11AA, 0xAA1100306543ECAC)) |
138 | 0 | snprintf(desc, GUID_DESC_LEN, "OS X Apple UFS"); |
139 | 0 | else if(gpt_guid_match(g, 0x6A898CC3, 0x1DD2, 0x11B2, 0x99A6080020736631)) |
140 | 0 | snprintf(desc, GUID_DESC_LEN, "OS X ZFS"); |
141 | 0 | else if(gpt_guid_match(g, 0x52414944, 0x0000, 0x11AA, 0xAA1100306543ECAC)) |
142 | 0 | snprintf(desc, GUID_DESC_LEN, "OS X Apple RAID partition"); |
143 | 0 | else if(gpt_guid_match(g, 0x52414944, 0x5F4F, 0x11AA, 0xAA1100306543ECAC)) |
144 | 0 | snprintf(desc, GUID_DESC_LEN, "OS X Apple RAID partition, offline"); |
145 | 0 | else if(gpt_guid_match(g, 0x426F6F74, 0x0000, 0x11AA, 0xAA1100306543ECAC)) |
146 | 0 | snprintf(desc, GUID_DESC_LEN, "OS X Apple Boot partition (Recovery HD)"); |
147 | 0 | else if(gpt_guid_match(g, 0x4C616265, 0x6C00, 0x11AA, 0xAA1100306543ECAC)) |
148 | 0 | snprintf(desc, GUID_DESC_LEN, "OS X Apple Label"); |
149 | 0 | else if(gpt_guid_match(g, 0x5265636F, 0x7665, 0x11AA, 0xAA1100306543ECAC)) |
150 | 0 | snprintf(desc, GUID_DESC_LEN, "OS X Apple TV Recovery partition"); |
151 | 0 | else if(gpt_guid_match(g, 0x53746F72, 0x6167, 0x11AA, 0xAA1100306543ECAC)) |
152 | 0 | snprintf(desc, GUID_DESC_LEN, "OS X Apple Core Storage (i.e. Lion FileVault) partition"); |
153 | 0 | else if(gpt_guid_match(g, 0x6A82CB45, 0x1DD2, 0x11B2, 0x99A6080020736631)) |
154 | | |
155 | 0 | snprintf(desc, GUID_DESC_LEN, "Solaris Boot partition"); |
156 | 0 | else if(gpt_guid_match(g, 0x6A85CF4D, 0x1DD2, 0x11B2, 0x99A6080020736631)) |
157 | 0 | snprintf(desc, GUID_DESC_LEN, "Solaris Root partition"); |
158 | 0 | else if(gpt_guid_match(g, 0x6A87C46F, 0x1DD2, 0x11B2, 0x99A6080020736631)) |
159 | 0 | snprintf(desc, GUID_DESC_LEN, "Solaris Swap partition"); |
160 | 0 | else if(gpt_guid_match(g, 0x6A8B642B, 0x1DD2, 0x11B2, 0x99A6080020736631)) |
161 | 0 | snprintf(desc, GUID_DESC_LEN, "Solaris Backup partition"); |
162 | 0 | else if(gpt_guid_match(g, 0x6A898CC3, 0x1DD2, 0x11B2, 0x99A6080020736631)) |
163 | 0 | snprintf(desc, GUID_DESC_LEN, "Solaris /usr partition"); |
164 | 0 | else if(gpt_guid_match(g, 0x6A8EF2E9, 0x1DD2, 0x11B2, 0x99A6080020736631)) |
165 | 0 | snprintf(desc, GUID_DESC_LEN, "Solaris /var partition"); |
166 | 0 | else if(gpt_guid_match(g, 0x6A90BA39, 0x1DD2, 0x11B2, 0x99A6080020736631)) |
167 | 0 | snprintf(desc, GUID_DESC_LEN, "Solaris /home partition"); |
168 | 0 | else if(gpt_guid_match(g, 0x6A9283A5, 0x1DD2, 0x11B2, 0x99A6080020736631)) |
169 | 0 | snprintf(desc, GUID_DESC_LEN, "Solaris Alternate sector"); |
170 | 0 | else if(gpt_guid_match(g, 0x6A945A3B, 0x1DD2, 0x11B2, 0x99A6080020736631)) |
171 | 0 | snprintf(desc, GUID_DESC_LEN, "Solaris Reserved partition"); |
172 | 0 | else if(gpt_guid_match(g, 0x6A9630D1, 0x1DD2, 0x11B2, 0x99A6080020736631)) |
173 | 0 | snprintf(desc, GUID_DESC_LEN, "Solaris Reserved partition"); |
174 | 0 | else if(gpt_guid_match(g, 0x6A980767, 0x1DD2, 0x11B2, 0x99A6080020736631)) |
175 | 0 | snprintf(desc, GUID_DESC_LEN, "Solaris Reserved partition"); |
176 | 0 | else if(gpt_guid_match(g, 0x6A96237F, 0x1DD2, 0x11B2, 0x99A6080020736631)) |
177 | 0 | snprintf(desc, GUID_DESC_LEN, "Solaris Reserved partition"); |
178 | 0 | else if(gpt_guid_match(g, 0x6A8D2AC7, 0x1DD2, 0x11B2, 0x99A6080020736631)) |
179 | 0 | snprintf(desc, GUID_DESC_LEN, "Solaris Reserved partition"); |
180 | | |
181 | 0 | else if(gpt_guid_match(g, 0x49F48D32, 0xB10E, 0x11DC, 0xB99B0019D1879648)) |
182 | 0 | snprintf(desc, GUID_DESC_LEN, "NetBSD Swap partition"); |
183 | 0 | else if(gpt_guid_match(g, 0x49F48D5A, 0xB10E, 0x11DC, 0xB99B0019D1879648)) |
184 | 0 | snprintf(desc, GUID_DESC_LEN, "NetBSD FFS partition"); |
185 | 0 | else if(gpt_guid_match(g, 0x49F48D82, 0xB10E, 0x11DC, 0xB99B0019D1879648)) |
186 | 0 | snprintf(desc, GUID_DESC_LEN, "NetBSD LFS partition"); |
187 | 0 | else if(gpt_guid_match(g, 0x49F48DAA, 0xB10E, 0x11DC, 0xB99B0019D1879648)) |
188 | 0 | snprintf(desc, GUID_DESC_LEN, "NetBSD RAID partition"); |
189 | 0 | else if(gpt_guid_match(g, 0x2DB519C4, 0xB10F, 0x11DC, 0xB99B0019D1879648)) |
190 | 0 | snprintf(desc, GUID_DESC_LEN, "NetBSD Concatenated partition"); |
191 | 0 | else if(gpt_guid_match(g, 0x2DB519EC, 0xB10F, 0x11DC, 0xB99B0019D1879648)) |
192 | 0 | snprintf(desc, GUID_DESC_LEN, "NetBSD Encrypted partition"); |
193 | | |
194 | 0 | else if(gpt_guid_match(g, 0xFE3A2A5D, 0x4F32, 0x41A7, 0xB725ACCC3285A309)) |
195 | 0 | snprintf(desc, GUID_DESC_LEN, "ChromeOS kernel"); |
196 | 0 | else if(gpt_guid_match(g, 0x3CB8E202, 0x3B7E, 0x47DD, 0x8A3C7FF2A13CFCEC)) |
197 | 0 | snprintf(desc, GUID_DESC_LEN, "ChromeOS rootfs"); |
198 | 0 | else if(gpt_guid_match(g, 0x2E0A753D, 0x9E48, 0x43B0, 0x8337B15192CB1B5E)) |
199 | 0 | snprintf(desc, GUID_DESC_LEN, "ChromeOS future use"); |
200 | | |
201 | 0 | else if(gpt_guid_match(g, 0x42465331, 0x3BA3, 0x10F1, 0x802A4861696B7521)) |
202 | 0 | snprintf(desc, GUID_DESC_LEN, "Haiku BFS"); |
203 | | |
204 | 0 | else if(gpt_guid_match(g, 0x85D5E45E, 0x237C, 0x11E1, 0xB4B3E89A8F7FC3A7)) |
205 | 0 | snprintf(desc, GUID_DESC_LEN, "MidnightBSD Boot partition"); |
206 | 0 | else if(gpt_guid_match(g, 0x85D5E45A, 0x237C, 0x11E1, 0xB4B3E89A8F7FC3A7)) |
207 | 0 | snprintf(desc, GUID_DESC_LEN, "MidnightBSD Data partition"); |
208 | 0 | else if(gpt_guid_match(g, 0x85D5E45B, 0x237C, 0x11E1, 0xB4B3E89A8F7FC3A7)) |
209 | 0 | snprintf(desc, GUID_DESC_LEN, "MidnightBSD Swap partition"); |
210 | 0 | else if(gpt_guid_match(g, 0x0394EF8B, 0x237E, 0x11E1, 0xB4B3E89A8F7FC3A7)) |
211 | 0 | snprintf(desc, GUID_DESC_LEN, "MidnightBSD Unix File System (UFS) partition"); |
212 | 0 | else if(gpt_guid_match(g, 0x85D5E45C, 0x237C, 0x11E1, 0xB4B3E89A8F7FC3A7)) |
213 | 0 | snprintf(desc, GUID_DESC_LEN, "MidnightBSD Vinum volume manager partition"); |
214 | 0 | else if(gpt_guid_match(g, 0x85D5E45D, 0x237C, 0x11E1, 0xB4B3E89A8F7FC3A7)) |
215 | 0 | snprintf(desc, GUID_DESC_LEN, "MidnightBSD ZFS partition"); |
216 | | |
217 | 0 | else if(gpt_guid_match(g, 0x45B0969E, 0x9B03, 0x4F30, 0xB4C6B4B80CEFF106)) |
218 | 0 | snprintf(desc, GUID_DESC_LEN, "Ceph Journal"); |
219 | 0 | else if(gpt_guid_match(g, 0x45B0969E, 0x9B03, 0x4F30, 0xB4C65EC00CEFF106)) |
220 | 0 | snprintf(desc, GUID_DESC_LEN, "Ceph dm-crypt Encrypted Journal"); |
221 | 0 | else if(gpt_guid_match(g, 0x4FBD7E29, 0x9D25, 0x41B8, 0xAFD0062C0CEFF05D)) |
222 | 0 | snprintf(desc, GUID_DESC_LEN, "Ceph OSD"); |
223 | 0 | else if(gpt_guid_match(g, 0x4FBD7E29, 0x9D25, 0x41B8, 0xAFD05EC00CEFF05D)) |
224 | 0 | snprintf(desc, GUID_DESC_LEN, "Ceph dm-crypt OSD"); |
225 | 0 | else if(gpt_guid_match(g, 0x89C57F98, 0x2FE5, 0x4DC0, 0x89C1F3AD0CEFF2BE)) |
226 | 0 | snprintf(desc, GUID_DESC_LEN, "Ceph disk in creation"); |
227 | 0 | else if(gpt_guid_match(g, 0x89C57F98, 0x2FE5, 0x4DC0, 0x89C15EC00CEFF2BE)) |
228 | 0 | snprintf(desc, GUID_DESC_LEN, "Ceph dm-crypt disk in creation"); |
229 | | |
230 | 0 | else if(gpt_guid_match(g, 0x824CC7A0, 0x36A8, 0x11E3, 0x890A952519AD3F61)) |
231 | 0 | snprintf(desc, GUID_DESC_LEN, "OpenBSD Data partition"); |
232 | | |
233 | 0 | else if(gpt_guid_match(g, 0xCEF5A9AD, 0x73BC, 0x4601, 0x89F3CDEEEEE321A1)) |
234 | 0 | snprintf(desc, GUID_DESC_LEN, "QNX Power-safe (QNX6) file system"); |
235 | | |
236 | 0 | else if(gpt_guid_match(g, 0xC91818F9, 0x8025, 0x47AF, 0x89D2F030D7000C2C)) |
237 | 0 | snprintf(desc, GUID_DESC_LEN, "Plan 9 partition"); |
238 | 0 | else if(gpt_guid_match(g, 0x9D275380, 0x40AD, 0x11DB, 0xBF97000C2911D1B8)) |
239 | 0 | snprintf(desc, GUID_DESC_LEN, "vmkcore (coredump partition)"); |
240 | 0 | else if(gpt_guid_match(g, 0xAA31E02A, 0x400F, 0x11DB, 0x9590000C2911D1B8)) |
241 | 0 | snprintf(desc, GUID_DESC_LEN, "VMFS filesystem partition"); |
242 | 0 | else if(gpt_guid_match(g, 0x9198EFFC, 0x31C0, 0x11DB, 0x8F78000C2911D1B8)) |
243 | 0 | snprintf(desc, GUID_DESC_LEN, "VMware Reserved"); |
244 | | |
245 | 0 | else if(gpt_guid_match(g, 0x2568845D, 0x2332, 0x4675, 0xBC398FA5A4748D15)) |
246 | 0 | snprintf(desc, GUID_DESC_LEN, "Android-IA Bootloader"); |
247 | 0 | else if(gpt_guid_match(g, 0x114EAFFE, 0x1552, 0x4022, 0xB26E9B053604CF84)) |
248 | 0 | snprintf(desc, GUID_DESC_LEN, "Android-IA Bootloader2"); |
249 | 0 | else if(gpt_guid_match(g, 0x49A4D17F, 0x93A3, 0x45C1, 0xA0DEF50B2EBE2599)) |
250 | 0 | snprintf(desc, GUID_DESC_LEN, "Android-IA Boot"); |
251 | 0 | else if(gpt_guid_match(g, 0x4177C722, 0x9E92, 0x4AAB, 0x864443502BFD5506)) |
252 | 0 | snprintf(desc, GUID_DESC_LEN, "Android-IA Recovery"); |
253 | 0 | else if(gpt_guid_match(g, 0xEF32A33B, 0xA409, 0x486C, 0x91419FFB711F6266)) |
254 | 0 | snprintf(desc, GUID_DESC_LEN, "Android-IA Misc"); |
255 | 0 | else if(gpt_guid_match(g, 0x20AC26BE, 0x20B7, 0x11E3, 0x84C56CFDB94711E9)) |
256 | 0 | snprintf(desc, GUID_DESC_LEN, "Android-IA Metadata"); |
257 | 0 | else if(gpt_guid_match(g, 0x38F428E6, 0xD326, 0x425D, 0x91406E0EA133647C)) |
258 | 0 | snprintf(desc, GUID_DESC_LEN, "Android-IA System"); |
259 | 0 | else if(gpt_guid_match(g, 0xA893EF21, 0xE428, 0x470A, 0x9E550668FD91A2D9)) |
260 | 0 | snprintf(desc, GUID_DESC_LEN, "Android-IA Cache"); |
261 | 0 | else if(gpt_guid_match(g, 0xDC76DDA9, 0x5AC1, 0x491C, 0xAF42A82591580C0D)) |
262 | 0 | snprintf(desc, GUID_DESC_LEN, "Android-IA Data"); |
263 | 0 | else if(gpt_guid_match(g, 0xEBC597D0, 0x2053, 0x4B15, 0x8B64E0AAC75F4DB1)) |
264 | 0 | snprintf(desc, GUID_DESC_LEN, "Android-IA Persistent"); |
265 | 0 | else if(gpt_guid_match(g, 0x8F68CC74, 0xC5E5, 0x48DA, 0xBE91A0C8C15E9C80)) |
266 | 0 | snprintf(desc, GUID_DESC_LEN, "Android-IA Factory"); |
267 | 0 | else if(gpt_guid_match(g, 0x767941D0, 0x2085, 0x11E3, 0xAD3B6CFDB94711E9)) |
268 | 0 | snprintf(desc, GUID_DESC_LEN, "Android-IA Fastboot / Tertiary"); |
269 | 0 | else if(gpt_guid_match(g, 0xAC6D7924, 0xEB71, 0x4DF8, 0xB48DE267B27148FF)) |
270 | 0 | snprintf(desc, GUID_DESC_LEN, "Android-IA OEM"); |
271 | | |
272 | 0 | else if(gpt_guid_match(g, 0x7412F7D5, 0xA156, 0x4B13, 0x81DC867174929325)) |
273 | 0 | snprintf(desc, GUID_DESC_LEN, "ONIE Boot"); |
274 | 0 | else if(gpt_guid_match(g, 0xD4E6E2CD, 0x4469, 0x46F3, 0xB5CB1BFF57AFC149)) |
275 | 0 | snprintf(desc, GUID_DESC_LEN, "ONIE Config"); |
276 | | |
277 | 0 | else if(gpt_guid_match(g, 0x9E1A2D38, 0xC612, 0x4316, 0xAA268B49521E5A8B)) |
278 | 0 | snprintf(desc, GUID_DESC_LEN, "PowerPC PReP boot"); |
279 | | |
280 | 0 | else if(gpt_guid_match(g, 0xBC13C2FF, 0x59E6, 0x4262, 0xA352B275FD6F7172)) |
281 | 0 | snprintf(desc, GUID_DESC_LEN, "Freedesktop Extended Boot Partition ($BOOT)"); |
282 | | |
283 | 0 | else { |
284 | 0 | snprintf(desc, GUID_DESC_LEN, "[Unkown type]"); |
285 | 0 | return 0; |
286 | 0 | } |
287 | | |
288 | 0 | return 1; |
289 | 0 | } |
290 | | |
291 | | |
292 | | /* |
293 | | * Process the partition table at the sector address |
294 | | * |
295 | | * It is loaded into the internal sorted list |
296 | | */ |
297 | | static uint8_t |
298 | | gpt_load_table(TSK_VS_INFO * vs, GPT_LOCATION_ENUM gpt_type) |
299 | 0 | { |
300 | 0 | gpt_head *head; |
301 | 0 | gpt_entry *ent; |
302 | 0 | dos_sect *dos_part; |
303 | 0 | unsigned int i, a; |
304 | 0 | uint32_t ent_size; |
305 | 0 | char *safe_str, *head_str, *tab_str, *ent_buf; |
306 | 0 | ssize_t cnt; |
307 | 0 | char *sect_buf; |
308 | 0 | TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size; // max sector |
309 | 0 | TSK_DADDR_T gpt_relative_addr; |
310 | 0 | TSK_DADDR_T gpt_absolute_addr; |
311 | |
|
312 | 0 | if(gpt_type == PRIMARY_TABLE){ |
313 | 0 | gpt_relative_addr = GPT_PART_SOFFSET + 1; |
314 | 0 | gpt_absolute_addr = vs->offset / vs->block_size + GPT_PART_SOFFSET + 1; |
315 | 0 | } else { |
316 | 0 | gpt_relative_addr = ((vs->img_info->size - vs->offset) / vs->block_size) - 1; |
317 | 0 | gpt_absolute_addr = (vs->img_info->size / vs->block_size) - 1; |
318 | 0 | } |
319 | |
|
320 | 0 | if (tsk_verbose) |
321 | 0 | tsk_fprintf(stderr, "gpt_load_table: Sector: %" PRIuDADDR "\n", |
322 | 0 | gpt_absolute_addr); |
323 | |
|
324 | 0 | if ((sect_buf = tsk_malloc(vs->block_size)) == NULL) |
325 | 0 | return 1; |
326 | | |
327 | 0 | if(gpt_type == PRIMARY_TABLE){ |
328 | 0 | TSK_DADDR_T dos_sect_relative_addr = GPT_PART_SOFFSET; |
329 | 0 | TSK_DADDR_T dos_sect_absolute_addr = vs->offset / vs->block_size + GPT_PART_SOFFSET; |
330 | 0 | dos_part = (dos_sect *) sect_buf; |
331 | |
|
332 | 0 | cnt = tsk_vs_read_block |
333 | 0 | (vs, dos_sect_relative_addr, sect_buf, vs->block_size); |
334 | | /* if -1, then tsk_errno is already set */ |
335 | 0 | if (cnt != vs->block_size) { |
336 | 0 | if (cnt >= 0) { |
337 | 0 | tsk_error_reset(); |
338 | 0 | tsk_error_set_errno(TSK_ERR_VS_READ); |
339 | 0 | } |
340 | 0 | tsk_error_set_errstr2 |
341 | 0 | ("Error reading DOS safety partition table in Sector: %" |
342 | 0 | PRIuDADDR, dos_sect_absolute_addr); |
343 | 0 | free(sect_buf); |
344 | 0 | return 1; |
345 | 0 | } |
346 | | |
347 | | /* Sanity Check */ |
348 | 0 | if (tsk_vs_guessu16(vs, dos_part->magic, DOS_MAGIC)) { |
349 | 0 | tsk_error_reset(); |
350 | 0 | tsk_error_set_errno(TSK_ERR_VS_MAGIC); |
351 | 0 | tsk_error_set_errstr |
352 | 0 | ("Missing DOS safety partition (invalid magic) (Sector: %" |
353 | 0 | PRIuDADDR ")", dos_sect_absolute_addr); |
354 | 0 | free(sect_buf); |
355 | 0 | return 1; |
356 | 0 | } |
357 | | |
358 | 0 | if (dos_part->ptable[0].ptype != GPT_DOS_TYPE) { |
359 | 0 | tsk_error_reset(); |
360 | 0 | tsk_error_set_errno(TSK_ERR_VS_MAGIC); |
361 | 0 | tsk_error_set_errstr |
362 | 0 | ("Missing DOS safety partition (invalid type in table: %d)", |
363 | 0 | dos_part->ptable[0].ptype); |
364 | 0 | free(sect_buf); |
365 | 0 | return 1; |
366 | 0 | } |
367 | 0 | } |
368 | | |
369 | | /* Read the GPT header */ |
370 | 0 | head = (gpt_head *) sect_buf; |
371 | 0 | cnt = tsk_vs_read_block |
372 | 0 | (vs, gpt_relative_addr, sect_buf, vs->block_size); |
373 | 0 | if (cnt != vs->block_size) { |
374 | 0 | if (cnt >= 0) { |
375 | 0 | tsk_error_reset(); |
376 | 0 | tsk_error_set_errno(TSK_ERR_VS_READ); |
377 | 0 | } |
378 | 0 | tsk_error_set_errstr2("GPT Header structure in Sector: %" |
379 | 0 | PRIuDADDR, gpt_absolute_addr); |
380 | 0 | free(sect_buf); |
381 | 0 | return 1; |
382 | 0 | } |
383 | | |
384 | | /* Do the endianness test for the secondary table since the test in the dos safety table was skipped */ |
385 | 0 | if(gpt_type == SECONDARY_TABLE){ |
386 | 0 | if (tsk_vs_guessu64(vs, head->signature, GPT_HEAD_SIG)) { |
387 | 0 | tsk_error_reset(); |
388 | 0 | tsk_error_set_errno(TSK_ERR_VS_MAGIC); |
389 | 0 | tsk_error_set_errstr("GPT Header: %" PRIx64, tsk_getu64(vs->endian, |
390 | 0 | &head->signature)); |
391 | 0 | free(sect_buf); |
392 | 0 | return 1; |
393 | 0 | } |
394 | 0 | } |
395 | | |
396 | 0 | if (tsk_getu64(vs->endian, &head->signature) != GPT_HEAD_SIG) { |
397 | 0 | tsk_error_reset(); |
398 | 0 | tsk_error_set_errno(TSK_ERR_VS_MAGIC); |
399 | 0 | tsk_error_set_errstr("GPT Header: %" PRIx64, tsk_getu64(vs->endian, |
400 | 0 | &head->signature)); |
401 | 0 | free(sect_buf); |
402 | 0 | return 1; |
403 | 0 | } |
404 | | |
405 | | // now that we checked the sig, lets make the meta entries |
406 | 0 | if (gpt_type == PRIMARY_TABLE) { |
407 | 0 | if ((safe_str = tsk_malloc(16)) == NULL) { |
408 | 0 | free(sect_buf); |
409 | 0 | return 1; |
410 | 0 | } |
411 | 0 | snprintf(safe_str, 16, "Safety Table"); |
412 | 0 | if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) 0, (TSK_DADDR_T) 1, |
413 | 0 | TSK_VS_PART_FLAG_META, safe_str, -1, -1)) { |
414 | 0 | free(sect_buf); |
415 | 0 | return 1; |
416 | 0 | } |
417 | 0 | } |
418 | | |
419 | 0 | if ((head_str = tsk_malloc(16)) == NULL) { |
420 | 0 | free(sect_buf); |
421 | 0 | return 1; |
422 | 0 | } |
423 | | |
424 | 0 | snprintf(head_str, 16, "GPT Header"); |
425 | 0 | if (NULL == tsk_vs_part_add(vs, gpt_relative_addr, |
426 | 0 | (TSK_DADDR_T) ((tsk_getu32(vs->endian, |
427 | 0 | &head->head_size_b) + (vs->block_size - |
428 | 0 | 1)) / vs->block_size), TSK_VS_PART_FLAG_META, |
429 | 0 | head_str, -1, -1)) { |
430 | 0 | free(sect_buf); |
431 | 0 | return 1; |
432 | 0 | } |
433 | | |
434 | | /* Allocate a buffer for each table entry */ |
435 | 0 | ent_size = tsk_getu32(vs->endian, &head->tab_size_b); |
436 | 0 | if (ent_size < sizeof(gpt_entry)) { |
437 | 0 | tsk_error_reset(); |
438 | 0 | tsk_error_set_errno(TSK_ERR_VS_MAGIC); |
439 | 0 | tsk_error_set_errstr("Header reports partition entry size of %" |
440 | 0 | PRIu32 " and not %" PRIuSIZE "", ent_size, sizeof(gpt_entry)); |
441 | 0 | free(sect_buf); |
442 | 0 | return 1; |
443 | 0 | } |
444 | | |
445 | 0 | if ((tab_str = tsk_malloc(20)) == NULL) { |
446 | 0 | free(sect_buf); |
447 | 0 | return 1; |
448 | 0 | } |
449 | | |
450 | 0 | snprintf(tab_str, 20, "Partition Table"); |
451 | 0 | if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) tsk_getu64(vs->endian, |
452 | 0 | &head->tab_start_lba), |
453 | 0 | (TSK_DADDR_T) ((ent_size * tsk_getu32(vs->endian, |
454 | 0 | &head->tab_num_ent) + (vs->block_size - |
455 | 0 | 1)) / vs->block_size), TSK_VS_PART_FLAG_META, |
456 | 0 | tab_str, -1, -1)) { |
457 | 0 | free(sect_buf); |
458 | 0 | return 1; |
459 | 0 | } |
460 | | |
461 | | |
462 | | /* Process the partition table */ |
463 | 0 | if ((ent_buf = tsk_malloc(vs->block_size)) == NULL) { |
464 | 0 | free(sect_buf); |
465 | 0 | return 1; |
466 | 0 | } |
467 | | |
468 | 0 | i = 0; |
469 | 0 | for (a = 0; i < tsk_getu32(vs->endian, &head->tab_num_ent); a++) { |
470 | 0 | char *name; |
471 | | |
472 | | /* Read a sector */ |
473 | 0 | cnt = tsk_vs_read_block(vs, |
474 | 0 | tsk_getu64(vs->endian, &head->tab_start_lba) + a, |
475 | 0 | ent_buf, vs->block_size); |
476 | 0 | if (cnt != vs->block_size) { |
477 | 0 | if (cnt >= 0) { |
478 | 0 | tsk_error_reset(); |
479 | 0 | tsk_error_set_errno(TSK_ERR_VS_READ); |
480 | 0 | } |
481 | 0 | tsk_error_set_errstr2 |
482 | 0 | ("Error reading GPT partition table sector : %" PRIuDADDR, |
483 | 0 | tsk_getu64(vs->endian, &head->tab_start_lba) + a); |
484 | 0 | free(ent_buf); |
485 | 0 | free(sect_buf); |
486 | 0 | return 1; |
487 | 0 | } |
488 | | |
489 | | /* Process the sector */ |
490 | 0 | ent = (gpt_entry *) ent_buf; |
491 | 0 | for (; (uintptr_t) ent < (uintptr_t) ent_buf + vs->block_size && |
492 | 0 | i < tsk_getu32(vs->endian, &head->tab_num_ent); i++) { |
493 | |
|
494 | 0 | UTF16 *name16; |
495 | 0 | UTF8 *name8; |
496 | 0 | int retVal; |
497 | |
|
498 | 0 | if (tsk_verbose) |
499 | 0 | tsk_fprintf(stderr, |
500 | 0 | "gpt_load: %d Starting Sector: %" PRIu64 |
501 | 0 | " End: %" PRIu64 " Flag: %" PRIx64 "\n", i, |
502 | 0 | tsk_getu64(vs->endian, ent->start_lba), |
503 | 0 | tsk_getu64(vs->endian, ent->end_lba), |
504 | 0 | tsk_getu64(vs->endian, ent->flags)); |
505 | | |
506 | |
|
507 | 0 | if (tsk_getu64(vs->endian, ent->start_lba) == 0) { |
508 | 0 | ent++; |
509 | 0 | continue; |
510 | 0 | } |
511 | | |
512 | | // make sure the first couple are in the image bounds |
513 | 0 | if ((i < 2) |
514 | 0 | && (tsk_getu64(vs->endian, ent->start_lba) > max_addr)) { |
515 | 0 | tsk_error_reset(); |
516 | 0 | tsk_error_set_errno(TSK_ERR_VS_BLK_NUM); |
517 | 0 | tsk_error_set_errstr |
518 | 0 | ("gpt_load_table: Starting sector too large for image"); |
519 | 0 | free(sect_buf); |
520 | 0 | free(ent_buf); |
521 | 0 | return 1; |
522 | 0 | } |
523 | | |
524 | | |
525 | 0 | if ((name = tsk_malloc(GUID_DESC_LEN)) == NULL) { |
526 | 0 | free(sect_buf); |
527 | 0 | free(ent_buf); |
528 | 0 | return 1; |
529 | 0 | } |
530 | | |
531 | | |
532 | | /*Find GUID partition type and use as description.*/ |
533 | | /*If GUID type is unknown, use description stored in gpt entry.*/ |
534 | 0 | if( ! gpt_guid_type(name, &(ent->type_guid))) { |
535 | 0 | name16 = (UTF16 *) ((uintptr_t) ent->name); |
536 | 0 | name8 = (UTF8 *) name; |
537 | |
|
538 | 0 | retVal = |
539 | 0 | tsk_UTF16toUTF8(vs->endian, (const UTF16 **) &name16, |
540 | 0 | (UTF16 *) ((uintptr_t) name16 + sizeof(ent->name)), |
541 | 0 | &name8, |
542 | 0 | (UTF8 *) ((uintptr_t) name8 + 256), TSKlenientConversion); |
543 | |
|
544 | 0 | if (retVal != TSKconversionOK) { |
545 | 0 | if (tsk_verbose) |
546 | 0 | tsk_fprintf(stderr, |
547 | 0 | "gpt_load_table: Error converting name to UTF8: %d\n", |
548 | 0 | retVal); |
549 | 0 | *name = '\0'; |
550 | 0 | } |
551 | 0 | } |
552 | | |
553 | |
|
554 | 0 | if (NULL == tsk_vs_part_add(vs, |
555 | 0 | (TSK_DADDR_T) tsk_getu64(vs->endian, ent->start_lba), |
556 | 0 | (TSK_DADDR_T) (tsk_getu64(vs->endian, |
557 | 0 | ent->end_lba) - tsk_getu64(vs->endian, |
558 | 0 | ent->start_lba) + 1), TSK_VS_PART_FLAG_ALLOC, |
559 | 0 | name, -1, i)) { |
560 | 0 | free(sect_buf); |
561 | 0 | free(ent_buf); |
562 | 0 | return 1; |
563 | 0 | } |
564 | | |
565 | 0 | ent++; |
566 | 0 | } |
567 | 0 | } |
568 | | |
569 | 0 | free(sect_buf); |
570 | 0 | free(ent_buf); |
571 | 0 | return 0; |
572 | 0 | } |
573 | | |
574 | | static void |
575 | | gpt_close(TSK_VS_INFO * vs) |
576 | 0 | { |
577 | 0 | vs->tag = 0; |
578 | 0 | tsk_vs_part_free(vs); |
579 | 0 | free(vs); |
580 | 0 | } |
581 | | |
582 | | TSK_VS_INFO * |
583 | | tsk_vs_gpt_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset) |
584 | 0 | { |
585 | 0 | TSK_VS_INFO *vs; |
586 | | |
587 | | // clean up any errors that are lying around |
588 | 0 | tsk_error_reset(); |
589 | |
|
590 | 0 | if (img_info->sector_size == 0) { |
591 | 0 | tsk_error_reset(); |
592 | 0 | tsk_error_set_errno(TSK_ERR_VS_ARG); |
593 | 0 | tsk_error_set_errstr("tsk_vs_gpt_open: sector size is 0"); |
594 | 0 | return NULL; |
595 | 0 | } |
596 | | |
597 | 0 | vs = (TSK_VS_INFO *) tsk_malloc(sizeof(*vs)); |
598 | 0 | if (vs == NULL) |
599 | 0 | return NULL; |
600 | | |
601 | 0 | vs->img_info = img_info; |
602 | 0 | vs->vstype = TSK_VS_TYPE_GPT; |
603 | 0 | vs->tag = TSK_VS_INFO_TAG; |
604 | | |
605 | | /* If an offset was given, then use that too */ |
606 | 0 | vs->offset = offset; |
607 | | |
608 | | /* initialize settings */ |
609 | 0 | vs->part_list = NULL; |
610 | 0 | vs->part_count = 0; |
611 | 0 | vs->endian = 0; |
612 | 0 | vs->block_size = img_info->sector_size; |
613 | 0 | vs->is_backup = 0; |
614 | | |
615 | | /* Assign functions */ |
616 | 0 | vs->close = gpt_close; |
617 | | |
618 | | /* Load the partitions into the sorted list */ |
619 | 0 | if (gpt_load_table(vs, PRIMARY_TABLE)) { |
620 | 0 | tsk_vs_part_free(vs); |
621 | 0 | int found = 0; |
622 | 0 | if (tsk_verbose) |
623 | 0 | tsk_fprintf(stderr, "gpt_open: Trying other sector sizes\n"); |
624 | | |
625 | | /* Before we give up, lets try some other sector sizes */ |
626 | 0 | vs->block_size = 512; |
627 | 0 | while (vs->block_size <= 8192) { |
628 | 0 | if (tsk_verbose) |
629 | 0 | tsk_fprintf(stderr, "gpt_open: Trying sector size: %d\n", |
630 | 0 | vs->block_size); |
631 | |
|
632 | 0 | if (gpt_load_table(vs, PRIMARY_TABLE)) { |
633 | 0 | tsk_vs_part_free(vs); |
634 | 0 | vs->block_size *= 2; |
635 | 0 | continue; |
636 | 0 | } |
637 | 0 | found = 1; |
638 | 0 | break; |
639 | 0 | } |
640 | |
|
641 | 0 | if (found == 0) { |
642 | | /* Look for the secondary GPT at the end of the image */ |
643 | 0 | if (tsk_verbose) |
644 | 0 | tsk_fprintf(stderr, "gpt_open: Trying secondary table\n"); |
645 | 0 | vs->block_size = img_info->sector_size; |
646 | 0 | vs->is_backup = 1; |
647 | 0 | if(gpt_load_table(vs, SECONDARY_TABLE)){ |
648 | | |
649 | | /* Try other sector sizes again */ |
650 | 0 | tsk_vs_part_free(vs); |
651 | 0 | vs->block_size = 512; |
652 | 0 | while (vs->block_size <= 8192) { |
653 | 0 | if (tsk_verbose) |
654 | 0 | tsk_fprintf(stderr, "gpt_open: Trying secondary table sector size: %d\n", |
655 | 0 | vs->block_size); |
656 | |
|
657 | 0 | if (gpt_load_table(vs, SECONDARY_TABLE)) { |
658 | 0 | tsk_vs_part_free(vs); |
659 | 0 | vs->block_size *= 2; |
660 | 0 | continue; |
661 | 0 | } |
662 | 0 | found = 1; |
663 | 0 | break; |
664 | 0 | } |
665 | |
|
666 | 0 | if(found == 0){ |
667 | 0 | gpt_close(vs); |
668 | 0 | return NULL; |
669 | 0 | } |
670 | 0 | } |
671 | |
|
672 | 0 | } |
673 | 0 | } |
674 | | |
675 | | |
676 | | /* fill in the sorted list with the 'unknown' values */ |
677 | 0 | if (tsk_vs_part_unused(vs)) { |
678 | 0 | gpt_close(vs); |
679 | 0 | return NULL; |
680 | 0 | } |
681 | | |
682 | 0 | return vs; |
683 | 0 | } |