Coverage Report

Created: 2025-07-18 07:03

/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
}