File: | 3rdparty/vboot/firmware/lib/gpt_misc.c |
Warning: | line 35, column 40 Result of 'malloc' is converted to a pointer of type 'uint8_t', which is incompatible with sizeof operand type 'GptEntry' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Copyright 2013 The ChromiumOS Authors |
2 | * Use of this source code is governed by a BSD-style license that can be |
3 | * found in the LICENSE file. |
4 | */ |
5 | |
6 | #include "2common.h" |
7 | #include "2sysincludes.h" |
8 | #include "cgptlib.h" |
9 | #include "cgptlib_internal.h" |
10 | #include "crc32.h" |
11 | #include "gpt.h" |
12 | #include "vboot_api.h" |
13 | |
14 | /** |
15 | * Allocate and read GPT data from the drive. |
16 | * |
17 | * The sector_bytes and gpt_drive_sectors fields should be filled on input. The |
18 | * primary and secondary header and entries are filled on output. |
19 | * |
20 | * Returns 0 if successful, 1 if error. |
21 | */ |
22 | int AllocAndReadGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata) |
23 | { |
24 | int primary_valid = 0, secondary_valid = 0; |
25 | |
26 | /* No data to be written yet */ |
27 | gptdata->modified = 0; |
28 | /* This should get overwritten by GptInit() */ |
29 | gptdata->ignored = 0; |
30 | |
31 | /* Allocate all buffers */ |
32 | gptdata->primary_header = (uint8_t *)malloc(gptdata->sector_bytes); |
33 | gptdata->secondary_header = |
34 | (uint8_t *)malloc(gptdata->sector_bytes); |
35 | gptdata->primary_entries = (uint8_t *)malloc(GPT_ENTRIES_ALLOC_SIZE(128 * sizeof(GptEntry))); |
Result of 'malloc' is converted to a pointer of type 'uint8_t', which is incompatible with sizeof operand type 'GptEntry' | |
36 | gptdata->secondary_entries = (uint8_t *)malloc(GPT_ENTRIES_ALLOC_SIZE(128 * sizeof(GptEntry))); |
37 | |
38 | /* In some cases we try to validate header1 with entries2 or vice versa, |
39 | so make sure the entries buffers always got fully initialized. */ |
40 | memset(gptdata->primary_entries, 0, GPT_ENTRIES_ALLOC_SIZE(128 * sizeof(GptEntry))); |
41 | memset(gptdata->secondary_entries, 0, GPT_ENTRIES_ALLOC_SIZE(128 * sizeof(GptEntry))); |
42 | |
43 | if (gptdata->primary_header == NULL((void*)0) || |
44 | gptdata->secondary_header == NULL((void*)0) || |
45 | gptdata->primary_entries == NULL((void*)0) || |
46 | gptdata->secondary_entries == NULL((void*)0)) |
47 | return 1; |
48 | |
49 | /* Read primary header from the drive, skipping the protective MBR */ |
50 | if (0 != VbExDiskRead(disk_handle, 1, 1, gptdata->primary_header)) { |
51 | VB2_DEBUG("Read error in primary GPT header\n")vb2ex_printf(__func__, "Read error in primary GPT header\n"); |
52 | memset(gptdata->primary_header, 0, gptdata->sector_bytes); |
53 | } |
54 | |
55 | /* Only read primary GPT if the primary header is valid */ |
56 | GptHeader* primary_header = (GptHeader*)gptdata->primary_header; |
57 | if (0 == CheckHeader(primary_header, 0, |
58 | gptdata->streaming_drive_sectors, |
59 | gptdata->gpt_drive_sectors, |
60 | gptdata->flags, |
61 | gptdata->sector_bytes)) { |
62 | primary_valid = 1; |
63 | uint64_t entries_bytes = |
64 | (uint64_t)primary_header->number_of_entries |
65 | * primary_header->size_of_entry; |
66 | uint64_t entries_sectors = |
67 | (entries_bytes + gptdata->sector_bytes - 1) |
68 | / gptdata->sector_bytes; |
69 | if (0 != VbExDiskRead(disk_handle, |
70 | primary_header->entries_lba, |
71 | entries_sectors, |
72 | gptdata->primary_entries)) { |
73 | VB2_DEBUG("Read error in primary GPT entries\n")vb2ex_printf(__func__, "Read error in primary GPT entries\n"); |
74 | primary_valid = 0; |
75 | } |
76 | } else { |
77 | VB2_DEBUG("Primary GPT header is %s\n",vb2ex_printf(__func__, "Primary GPT header is %s\n", memcmp(primary_header ->signature, "IGNOREME", 8) ? "invalid" : "being ignored") |
78 | memcmp(primary_header->signature,vb2ex_printf(__func__, "Primary GPT header is %s\n", memcmp(primary_header ->signature, "IGNOREME", 8) ? "invalid" : "being ignored") |
79 | GPT_HEADER_SIGNATURE_IGNORED,vb2ex_printf(__func__, "Primary GPT header is %s\n", memcmp(primary_header ->signature, "IGNOREME", 8) ? "invalid" : "being ignored") |
80 | GPT_HEADER_SIGNATURE_SIZE)vb2ex_printf(__func__, "Primary GPT header is %s\n", memcmp(primary_header ->signature, "IGNOREME", 8) ? "invalid" : "being ignored") |
81 | ? "invalid" : "being ignored")vb2ex_printf(__func__, "Primary GPT header is %s\n", memcmp(primary_header ->signature, "IGNOREME", 8) ? "invalid" : "being ignored"); |
82 | } |
83 | |
84 | /* Read secondary header from the end of the drive */ |
85 | if (0 != VbExDiskRead(disk_handle, gptdata->gpt_drive_sectors - 1, 1, |
86 | gptdata->secondary_header)) { |
87 | VB2_DEBUG("Read error in secondary GPT header\n")vb2ex_printf(__func__, "Read error in secondary GPT header\n" ); |
88 | memset(gptdata->secondary_header, 0, gptdata->sector_bytes); |
89 | } |
90 | |
91 | /* Only read secondary GPT if the secondary header is valid */ |
92 | GptHeader* secondary_header = (GptHeader*)gptdata->secondary_header; |
93 | if (0 == CheckHeader(secondary_header, 1, |
94 | gptdata->streaming_drive_sectors, |
95 | gptdata->gpt_drive_sectors, |
96 | gptdata->flags, |
97 | gptdata->sector_bytes)) { |
98 | secondary_valid = 1; |
99 | uint64_t entries_bytes = |
100 | (uint64_t)secondary_header->number_of_entries |
101 | * secondary_header->size_of_entry; |
102 | uint64_t entries_sectors = |
103 | (entries_bytes + gptdata->sector_bytes - 1) |
104 | / gptdata->sector_bytes; |
105 | if (0 != VbExDiskRead(disk_handle, |
106 | secondary_header->entries_lba, |
107 | entries_sectors, |
108 | gptdata->secondary_entries)) { |
109 | VB2_DEBUG("Read error in secondary GPT entries\n")vb2ex_printf(__func__, "Read error in secondary GPT entries\n" ); |
110 | secondary_valid = 0; |
111 | } |
112 | } else { |
113 | VB2_DEBUG("Secondary GPT header is %s\n",vb2ex_printf(__func__, "Secondary GPT header is %s\n", memcmp (secondary_header->signature, "IGNOREME", 8) ? "invalid" : "being ignored") |
114 | memcmp(secondary_header->signature,vb2ex_printf(__func__, "Secondary GPT header is %s\n", memcmp (secondary_header->signature, "IGNOREME", 8) ? "invalid" : "being ignored") |
115 | GPT_HEADER_SIGNATURE_IGNORED,vb2ex_printf(__func__, "Secondary GPT header is %s\n", memcmp (secondary_header->signature, "IGNOREME", 8) ? "invalid" : "being ignored") |
116 | GPT_HEADER_SIGNATURE_SIZE)vb2ex_printf(__func__, "Secondary GPT header is %s\n", memcmp (secondary_header->signature, "IGNOREME", 8) ? "invalid" : "being ignored") |
117 | ? "invalid" : "being ignored")vb2ex_printf(__func__, "Secondary GPT header is %s\n", memcmp (secondary_header->signature, "IGNOREME", 8) ? "invalid" : "being ignored"); |
118 | } |
119 | |
120 | /* Return 0 if least one GPT header was valid */ |
121 | return (primary_valid || secondary_valid) ? 0 : 1; |
122 | } |
123 | |
124 | /** |
125 | * Write any changes for the GPT data back to the drive, then free the buffers. |
126 | * |
127 | * Returns 0 if successful, 1 if error. |
128 | */ |
129 | int WriteAndFreeGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata) |
130 | { |
131 | int skip_primary = 0; |
132 | GptHeader *header; |
133 | uint64_t entries_bytes, entries_sectors; |
134 | int ret = 1; |
135 | |
136 | header = (GptHeader *)gptdata->primary_header; |
137 | if (!header) |
138 | header = (GptHeader *)gptdata->secondary_header; |
139 | if (!header) |
140 | return 1; /* No headers at all, so nothing to write */ |
141 | |
142 | entries_bytes = (uint64_t)header->number_of_entries |
143 | * header->size_of_entry; |
144 | entries_sectors = entries_bytes / gptdata->sector_bytes; |
145 | |
146 | /* |
147 | * TODO(namnguyen): Preserve padding between primary GPT header and |
148 | * its entries. |
149 | */ |
150 | uint64_t entries_lba = GPT_PMBR_SECTORS1 + GPT_HEADER_SECTORS1; |
151 | if (gptdata->primary_header) { |
152 | GptHeader *h = (GptHeader *)(gptdata->primary_header); |
153 | entries_lba = h->entries_lba; |
154 | |
155 | if (gptdata->ignored & MASK_PRIMARY) { |
156 | VB2_DEBUG("Not updating primary GPT: "vb2ex_printf(__func__, "Not updating primary GPT: " "marked to be ignored.\n" ) |
157 | "marked to be ignored.\n")vb2ex_printf(__func__, "Not updating primary GPT: " "marked to be ignored.\n" ); |
158 | skip_primary = 1; |
159 | } else if (gptdata->modified & GPT_MODIFIED_HEADER10x01) { |
160 | if (!memcmp(h->signature, GPT_HEADER_SIGNATURE2"CHROMEOS", |
161 | GPT_HEADER_SIGNATURE_SIZE8)) { |
162 | VB2_DEBUG("Not updating primary GPT: "vb2ex_printf(__func__, "Not updating primary GPT: " "legacy mode is enabled.\n" ) |
163 | "legacy mode is enabled.\n")vb2ex_printf(__func__, "Not updating primary GPT: " "legacy mode is enabled.\n" ); |
164 | skip_primary = 1; |
165 | } else { |
166 | VB2_DEBUG("Updating GPT header 1\n")vb2ex_printf(__func__, "Updating GPT header 1\n"); |
167 | if (0 != VbExDiskWrite(disk_handle, 1, 1, |
168 | gptdata->primary_header)) |
169 | goto fail; |
170 | } |
171 | } |
172 | } |
173 | |
174 | if (gptdata->primary_entries && !skip_primary) { |
175 | if (gptdata->modified & GPT_MODIFIED_ENTRIES10x04) { |
176 | VB2_DEBUG("Updating GPT entries 1\n")vb2ex_printf(__func__, "Updating GPT entries 1\n"); |
177 | if (0 != VbExDiskWrite(disk_handle, entries_lba, |
178 | entries_sectors, |
179 | gptdata->primary_entries)) |
180 | goto fail; |
181 | } |
182 | } |
183 | |
184 | entries_lba = (gptdata->gpt_drive_sectors - entries_sectors - |
185 | GPT_HEADER_SECTORS1); |
186 | if (gptdata->secondary_header && !(gptdata->ignored & MASK_SECONDARY)) { |
187 | GptHeader *h = (GptHeader *)(gptdata->secondary_header); |
188 | entries_lba = h->entries_lba; |
189 | if (gptdata->modified & GPT_MODIFIED_HEADER20x02) { |
190 | VB2_DEBUG("Updating GPT header 2\n")vb2ex_printf(__func__, "Updating GPT header 2\n"); |
191 | if (0 != VbExDiskWrite(disk_handle, |
192 | gptdata->gpt_drive_sectors - 1, 1, |
193 | gptdata->secondary_header)) |
194 | goto fail; |
195 | } |
196 | } |
197 | |
198 | if (gptdata->secondary_entries && !(gptdata->ignored & MASK_SECONDARY)){ |
199 | if (gptdata->modified & GPT_MODIFIED_ENTRIES20x08) { |
200 | VB2_DEBUG("Updating GPT entries 2\n")vb2ex_printf(__func__, "Updating GPT entries 2\n"); |
201 | if (0 != VbExDiskWrite(disk_handle, |
202 | entries_lba, entries_sectors, |
203 | gptdata->secondary_entries)) |
204 | goto fail; |
205 | } |
206 | } |
207 | |
208 | ret = 0; |
209 | |
210 | fail: |
211 | /* Avoid leaking memory on disk write failure */ |
212 | if (gptdata->primary_header) |
213 | free(gptdata->primary_header); |
214 | if (gptdata->primary_entries) |
215 | free(gptdata->primary_entries); |
216 | if (gptdata->secondary_entries) |
217 | free(gptdata->secondary_entries); |
218 | if (gptdata->secondary_header) |
219 | free(gptdata->secondary_header); |
220 | |
221 | /* Success */ |
222 | return ret; |
223 | } |
224 | |
225 | int IsUnusedEntry(const GptEntry *e) |
226 | { |
227 | static Guid zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}}; |
228 | return !memcmp(&zero, (const uint8_t*)(&e->type), sizeof(zero)); |
229 | } |
230 | |
231 | /* |
232 | * Func: GptGetEntrySize |
233 | * Desc: This function returns size(in lba) of a partition represented by |
234 | * given GPT entry. |
235 | */ |
236 | size_t GptGetEntrySizeLba(const GptEntry *e) |
237 | { |
238 | return (e->ending_lba - e->starting_lba + 1); |
239 | } |
240 | |
241 | /* |
242 | * Func: GptGetEntrySize |
243 | * Desc: This function returns size(in bytes) of a partition represented by |
244 | * given GPT entry. |
245 | */ |
246 | size_t GptGetEntrySizeBytes(const GptData *gpt, const GptEntry *e) |
247 | { |
248 | return GptGetEntrySizeLba(e) * gpt->sector_bytes; |
249 | } |