Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(188)

Side by Side Diff: src/platform/vboot_reference/vkernel/kernel_image.c

Issue 2283005: Modifying the kernel_utility tool to create our magic blob. (Closed) Base URL: ssh://git@chromiumos-git/chromeos
Patch Set: respond to feedback Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/platform/vboot_reference/vkernel/include/kernel_image.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be 2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file. 3 * found in the LICENSE file.
4 * 4 *
5 * Functions for generating and manipulating a verified boot kernel image. 5 * Functions for generating and manipulating a verified boot kernel image.
6 * (Userland portion) 6 * (Userland portion)
7 */ 7 */
8 8
9 #include "kernel_image.h"
10
11 #include <fcntl.h> 9 #include <fcntl.h>
10 #include <stddef.h>
12 #include <stdio.h> 11 #include <stdio.h>
13 #include <sys/types.h> 12 #include <sys/types.h>
14 #include <sys/stat.h> 13 #include <sys/stat.h>
15 #include <unistd.h> 14 #include <unistd.h>
16 15
17 #include "cryptolib.h" 16 #include "cryptolib.h"
18 #include "file_keys.h" 17 #include "file_keys.h"
18 #include "kernel_image.h"
gauravsh 2010/05/27 18:06:04 oops, I meant only #include kernel_blob.h should g
19 #include "kernel_blob.h"
19 #include "rollback_index.h" 20 #include "rollback_index.h"
20 #include "signature_digest.h" 21 #include "signature_digest.h"
21 #include "utility.h" 22 #include "utility.h"
22 23
23 /* Macro to determine the size of a field structure in the KernelImage 24 /* Macro to determine the size of a field structure in the KernelImage
24 * structure. */ 25 * structure. */
25 #define FIELD_LEN(field) (sizeof(((KernelImage*)0)->field)) 26 #define FIELD_LEN(field) (sizeof(((KernelImage*)0)->field))
26 27
27 KernelImage* KernelImageNew(void) { 28 KernelImage* KernelImageNew(void) {
28 KernelImage* image = (KernelImage*) Malloc(sizeof(KernelImage)); 29 KernelImage* image = (KernelImage*) Malloc(sizeof(KernelImage));
29 if (image) { 30 if (image) {
30 image->kernel_sign_key = NULL; 31 image->kernel_sign_key = NULL;
31 image->kernel_key_signature = NULL; 32 image->kernel_key_signature = NULL;
32 image->preamble_signature = NULL; 33 image->preamble_signature = NULL;
33 image->kernel_signature = NULL; 34 image->kernel_signature = NULL;
34 image->kernel_data = NULL; 35 image->kernel_data = NULL;
36 image->padded_header_size = 0x4000;
35 } 37 }
36 return image; 38 return image;
37 } 39 }
38 40
39 void KernelImageFree(KernelImage* image) { 41 void KernelImageFree(KernelImage* image) {
40 if (image) { 42 if (image) {
41 Free(image->kernel_sign_key); 43 Free(image->kernel_sign_key);
42 Free(image->kernel_key_signature); 44 Free(image->kernel_key_signature);
43 Free(image->preamble_signature); 45 Free(image->preamble_signature);
44 Free(image->kernel_signature); 46 Free(image->kernel_signature);
45 Free(image->kernel_data); 47 Free(image->kernel_data);
46 Free(image); 48 Free(image);
47 } 49 }
48 } 50 }
49 51
52 uint64_t GetHeaderSizeOnDisk(const KernelImage* image) {
53 uint64_t kernel_signature_len = siglen_map[image->kernel_sign_algorithm];
54 uint64_t kernel_key_signature_len =
55 siglen_map[image->firmware_sign_algorithm];
56
57 return FIELD_LEN(magic) +
58 GetKernelHeaderLen(image) +
59 kernel_key_signature_len +
60 GetKernelPreambleLen(image->kernel_sign_algorithm) +
61 kernel_signature_len;
62 }
63
64
50 KernelImage* ReadKernelImage(const char* input_file) { 65 KernelImage* ReadKernelImage(const char* input_file) {
51 uint64_t file_size; 66 uint64_t file_size;
52 int image_len = 0; /* Total size of the kernel image. */ 67 uint64_t on_disk_header_size;
68 uint64_t on_disk_padding;
53 int header_len = 0; 69 int header_len = 0;
54 int firmware_sign_key_len; 70 int firmware_sign_key_len;
55 int kernel_key_signature_len; 71 int kernel_key_signature_len;
56 int kernel_sign_key_len; 72 int kernel_sign_key_len;
57 int kernel_signature_len; 73 int kernel_signature_len;
58 uint8_t* kernel_buf; 74 uint8_t* kernel_buf;
59 uint8_t header_checksum[FIELD_LEN(header_checksum)]; 75 uint8_t header_checksum[FIELD_LEN(header_checksum)];
60 MemcpyState st; 76 MemcpyState st;
61 KernelImage* image = KernelImageNew(); 77 KernelImage* image = KernelImageNew();
62 78
63 if (!image) 79 if (!image)
64 return NULL; 80 return NULL;
65 81
66 kernel_buf = BufferFromFile(input_file, &file_size); 82 kernel_buf = BufferFromFile(input_file, &file_size);
67 image_len = file_size;
68 83
69 st.remaining_len = image_len; 84 st.remaining_len = file_size;
70 st.remaining_buf = kernel_buf; 85 st.remaining_buf = kernel_buf;
71 st.overrun = 0; 86 st.overrun = 0;
72 87
73 /* Read and compare magic bytes. */ 88 /* Read and compare magic bytes. */
74 StatefulMemcpy(&st, &image->magic, KERNEL_MAGIC_SIZE); 89 StatefulMemcpy(&st, &image->magic, KERNEL_MAGIC_SIZE);
75 90
76 if (SafeMemcmp(image->magic, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) { 91 if (SafeMemcmp(image->magic, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) {
77 debug("Wrong Kernel Magic.\n"); 92 debug("Wrong Kernel Magic.\n");
78 Free(kernel_buf); 93 Free(kernel_buf);
79 return NULL; 94 return NULL;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 kernel_key_signature_len); 149 kernel_key_signature_len);
135 150
136 /* Read the kernel preamble. */ 151 /* Read the kernel preamble. */
137 StatefulMemcpy(&st, &image->kernel_version, FIELD_LEN(kernel_version)); 152 StatefulMemcpy(&st, &image->kernel_version, FIELD_LEN(kernel_version));
138 StatefulMemcpy(&st, &image->kernel_len, FIELD_LEN(kernel_len)); 153 StatefulMemcpy(&st, &image->kernel_len, FIELD_LEN(kernel_len));
139 StatefulMemcpy(&st, &image->bootloader_offset, FIELD_LEN(bootloader_offset)); 154 StatefulMemcpy(&st, &image->bootloader_offset, FIELD_LEN(bootloader_offset));
140 StatefulMemcpy(&st, &image->bootloader_size, FIELD_LEN(bootloader_size)); 155 StatefulMemcpy(&st, &image->bootloader_size, FIELD_LEN(bootloader_size));
141 StatefulMemcpy(&st, &image->padded_header_size, 156 StatefulMemcpy(&st, &image->padded_header_size,
142 FIELD_LEN(padded_header_size)); 157 FIELD_LEN(padded_header_size));
143 158
144 /* Read config and kernel signatures. */ 159 /* Read preamble and kernel signatures. */
160 image->kernel_signature = (uint8_t*) Malloc(kernel_signature_len);
161 StatefulMemcpy(&st, image->kernel_signature, kernel_signature_len);
145 image->preamble_signature = (uint8_t*) Malloc(kernel_signature_len); 162 image->preamble_signature = (uint8_t*) Malloc(kernel_signature_len);
146 StatefulMemcpy(&st, image->preamble_signature, kernel_signature_len); 163 StatefulMemcpy(&st, image->preamble_signature, kernel_signature_len);
147 image->kernel_signature = (uint8_t*) Malloc(kernel_signature_len); 164
148 StatefulMemcpy(&st, image->kernel_signature, kernel_signature_len); 165 /* Skip over the rest of the padded header, unless we're already past it. */
166 on_disk_header_size = file_size - st.remaining_len;
167 if (image->padded_header_size > on_disk_header_size) {
168 on_disk_padding = image->padded_header_size - on_disk_header_size;
169 if (st.remaining_len < on_disk_padding)
170 st.overrun = -1;
171 st.remaining_buf += on_disk_padding;
172 st.remaining_len -= on_disk_padding;
173 }
149 174
150 /* Read kernel image data. */ 175 /* Read kernel image data. */
151 image->kernel_data = (uint8_t*) Malloc(image->kernel_len); 176 image->kernel_data = (uint8_t*) Malloc(image->kernel_len);
152 StatefulMemcpy(&st, image->kernel_data, image->kernel_len); 177 StatefulMemcpy(&st, image->kernel_data, image->kernel_len);
153 178
154 if(st.overrun || st.remaining_len != 0) { /* Overrun or underrun. */ 179 if(st.overrun || st.remaining_len != 0) { /* Overrun or underrun. */
155 Free(kernel_buf); 180 Free(kernel_buf);
156 return NULL; 181 return NULL;
157 } 182 }
158 Free(kernel_buf); 183 Free(kernel_buf);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 } 268 }
244 return preamble_blob; 269 return preamble_blob;
245 } 270 }
246 271
247 uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_len) { 272 uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_len) {
248 int kernel_key_signature_len; 273 int kernel_key_signature_len;
249 int kernel_signature_len; 274 int kernel_signature_len;
250 uint8_t* kernel_blob = NULL; 275 uint8_t* kernel_blob = NULL;
251 uint8_t* header_blob = NULL; 276 uint8_t* header_blob = NULL;
252 MemcpyState st; 277 MemcpyState st;
278 uint64_t on_disk_header_size;
279 uint64_t on_disk_padding = 0;
253 280
254 if (!image) 281 if (!image)
255 return NULL; 282 return NULL;
256 kernel_key_signature_len = siglen_map[image->firmware_sign_algorithm]; 283 kernel_key_signature_len = siglen_map[image->firmware_sign_algorithm];
257 kernel_signature_len = siglen_map[image->kernel_sign_algorithm]; 284 kernel_signature_len = siglen_map[image->kernel_sign_algorithm];
258 *blob_len = (FIELD_LEN(magic) + 285 on_disk_header_size = GetHeaderSizeOnDisk(image);
259 GetKernelHeaderLen(image) + 286 if (image->padded_header_size > on_disk_header_size)
260 kernel_key_signature_len + 287 on_disk_padding = image->padded_header_size - on_disk_header_size;
261 GetKernelPreambleLen(image->kernel_sign_algorithm) + 288 *blob_len = on_disk_header_size + on_disk_padding + image->kernel_len;
262 kernel_signature_len +
263 image->kernel_len);
264 kernel_blob = (uint8_t*) Malloc(*blob_len); 289 kernel_blob = (uint8_t*) Malloc(*blob_len);
265 st.remaining_len = *blob_len; 290 st.remaining_len = *blob_len;
266 st.remaining_buf = kernel_blob; 291 st.remaining_buf = kernel_blob;
267 st.overrun = 0; 292 st.overrun = 0;
268
269 header_blob = GetKernelHeaderBlob(image); 293 header_blob = GetKernelHeaderBlob(image);
270 294
271 StatefulMemcpy_r(&st, image->magic, FIELD_LEN(magic)); 295 StatefulMemcpy_r(&st, image->magic, FIELD_LEN(magic));
272 StatefulMemcpy_r(&st, header_blob, GetKernelHeaderLen(image)); 296 StatefulMemcpy_r(&st, header_blob, GetKernelHeaderLen(image));
273 StatefulMemcpy_r(&st, image->kernel_key_signature, kernel_key_signature_len); 297 StatefulMemcpy_r(&st, image->kernel_key_signature, kernel_key_signature_len);
274 /* Copy over kernel preamble blob (including signatures.) */ 298 /* Copy over kernel preamble blob (including signatures.) */
275 StatefulMemcpy_r(&st, &image->kernel_version, FIELD_LEN(kernel_version)); 299 StatefulMemcpy_r(&st, &image->kernel_version, FIELD_LEN(kernel_version));
276 StatefulMemcpy_r(&st, &image->kernel_len, FIELD_LEN(kernel_len)); 300 StatefulMemcpy_r(&st, &image->kernel_len, FIELD_LEN(kernel_len));
277 StatefulMemcpy_r(&st, &image->bootloader_offset, 301 StatefulMemcpy_r(&st, &image->bootloader_offset,
278 FIELD_LEN(bootloader_offset)); 302 FIELD_LEN(bootloader_offset));
279 StatefulMemcpy_r(&st, &image->bootloader_size, FIELD_LEN(bootloader_size)); 303 StatefulMemcpy_r(&st, &image->bootloader_size, FIELD_LEN(bootloader_size));
280 StatefulMemcpy_r(&st, &image->padded_header_size, 304 StatefulMemcpy_r(&st, &image->padded_header_size,
281 FIELD_LEN(padded_header_size)); 305 FIELD_LEN(padded_header_size));
282 StatefulMemcpy_r(&st, image->kernel_signature, kernel_signature_len); 306 StatefulMemcpy_r(&st, image->kernel_signature, kernel_signature_len);
283 StatefulMemcpy_r(&st, image->preamble_signature, kernel_signature_len); 307 StatefulMemcpy_r(&st, image->preamble_signature, kernel_signature_len);
308 /* Copy a bunch of zeros to pad out the header */
309 if (on_disk_padding)
310 StatefulMemset_r(&st, 0, on_disk_padding);
284 StatefulMemcpy_r(&st, image->kernel_data, image->kernel_len); 311 StatefulMemcpy_r(&st, image->kernel_data, image->kernel_len);
285 312
286 Free(header_blob); 313 Free(header_blob);
287 314
288 if (st.overrun || st.remaining_len != 0) { /* Underrun or Overrun. */ 315 if (st.overrun || st.remaining_len != 0) { /* Underrun or Overrun. */
289 debug("GetKernelBlob() failed.\n"); 316 debug("GetKernelBlob() failed.\n");
290 Free(kernel_blob); 317 Free(kernel_blob);
291 return NULL; 318 return NULL;
292 } 319 }
293 return kernel_blob; 320 return kernel_blob;
294 } 321 }
295 322
296 int WriteKernelImage(const char* input_file, 323 int WriteKernelImage(const char* output_file,
297 const KernelImage* image, 324 const KernelImage* image,
298 int is_only_vblock) { 325 int is_only_vblock) {
299 int fd; 326 int fd;
300 int success = 1; 327 int success = 1;
301 uint8_t* kernel_blob; 328 uint8_t* kernel_blob;
302 uint64_t blob_len; 329 uint64_t blob_len;
303 330
304 if (!image) 331 if (!image)
305 return 0; 332 return 0;
306 if (-1 == (fd = creat(input_file, S_IRWXU))) { 333 if (-1 == (fd = creat(output_file, S_IRWXU))) {
307 debug("Couldn't open file for writing kernel image: %s\n", 334 debug("Couldn't open file for writing kernel image: %s\n",
308 input_file); 335 output_file);
309 return 0; 336 return 0;
310 } 337 }
311 kernel_blob = GetKernelBlob(image, &blob_len); 338 kernel_blob = GetKernelBlob(image, &blob_len);
312 if (!kernel_blob) { 339 if (!kernel_blob) {
313 debug("Couldn't create kernel blob from KernelImage.\n"); 340 debug("Couldn't create kernel blob from KernelImage.\n");
314 return 0; 341 return 0;
315 } 342 }
316 if (!is_only_vblock) { 343 if (!is_only_vblock) {
317 if (blob_len != write(fd, kernel_blob, blob_len)) { 344 if (blob_len != write(fd, kernel_blob, blob_len)) {
318 debug("Couldn't write Kernel Image to file: %s\n", 345 debug("Couldn't write Kernel Image to file: %s\n",
319 input_file); 346 output_file);
320 success = 0; 347 success = 0;
321 } 348 }
322 } else { 349 } else {
323 /* Exclude kernel_data. */ 350 /* Exclude kernel_data. */
324 int vblock_len = blob_len - (image->kernel_len); 351 int vblock_len = blob_len - (image->kernel_len);
325 if (vblock_len != write(fd, kernel_blob, vblock_len)) { 352 if (vblock_len != write(fd, kernel_blob, vblock_len)) {
326 debug("Couldn't write Kernel Image Verification block to file: %s\n", 353 debug("Couldn't write Kernel Image Verification block to file: %s\n",
327 input_file); 354 output_file);
328 success = 0; 355 success = 0;
329 } 356 }
330 } 357 }
331 Free(kernel_blob); 358 Free(kernel_blob);
332 close(fd); 359 close(fd);
333 return success; 360 return success;
334 } 361 }
335 362
336 void PrintKernelImage(const KernelImage* image) { 363 void PrintKernelImage(const KernelImage* image) {
364 uint64_t header_size;
365
337 if (!image) 366 if (!image)
338 return; 367 return;
339 368
369 header_size = GetHeaderSizeOnDisk(image);
370 if (image->padded_header_size > header_size)
371 header_size = image->padded_header_size;
372
373
340 /* Print header. */ 374 /* Print header. */
341 printf("Header Version = %d\n" 375 printf("Header Version = %d\n"
342 "Header Length = %d\n" 376 "Header Length = %d\n"
343 "Kernel Key Signature Algorithm = %s\n" 377 "Kernel Key Signature Algorithm = %s\n"
344 "Kernel Signature Algorithm = %s\n" 378 "Kernel Signature Algorithm = %s\n"
345 "Kernel Key Version = %d\n\n", 379 "Kernel Key Version = %d\n\n",
346 image->header_version, 380 image->header_version,
347 image->header_len, 381 image->header_len,
348 algo_strings[image->firmware_sign_algorithm], 382 algo_strings[image->firmware_sign_algorithm],
349 algo_strings[image->kernel_sign_algorithm], 383 algo_strings[image->kernel_sign_algorithm],
350 image->kernel_key_version); 384 image->kernel_key_version);
351 /* TODO(gauravsh): Output hash and key signature here? */ 385 /* TODO(gauravsh): Output hash and key signature here? */
352 /* Print preamble. */ 386 /* Print preamble. */
353 printf("Kernel Version = %d\n" 387 printf("Kernel Version = %d\n"
354 "kernel Length = %" PRId64 "\n" 388 "kernel Length = %" PRId64 " (0x%" PRIx64 ")\n"
355 "Bootloader Offset = %" PRId64 "\n" 389 "Bootloader Offset = %" PRId64 " (0x%" PRIx64 ")\n"
356 "Bootloader Size = %" PRId64 "\n" 390 "Bootloader Size = %" PRId64 " (0x%" PRIx64 ")\n"
357 "Padded Header Size = %" PRId64 "\n", 391 "Padded Header Size = %" PRId64 " (0x%" PRIx64 ")\n\n"
392 "Actual Header Size on disk = %" PRIu64 " (0x%" PRIx64 ")\n",
358 image->kernel_version, 393 image->kernel_version,
359 image->kernel_len, 394 image->kernel_len, image->kernel_len,
360 image->bootloader_offset, 395 image->bootloader_offset, image->bootloader_offset,
361 image->bootloader_size, 396 image->bootloader_size, image->bootloader_size,
362 image->padded_header_size); 397 image->padded_header_size, image->padded_header_size,
398 header_size, header_size);
363 /* TODO(gauravsh): Output kernel signature here? */ 399 /* TODO(gauravsh): Output kernel signature here? */
364 } 400 }
365 401
366 402
367 int VerifyKernelImage(const RSAPublicKey* firmware_key, 403 int VerifyKernelImage(const RSAPublicKey* firmware_key,
368 const KernelImage* image, 404 const KernelImage* image,
369 const int dev_mode) { 405 const int dev_mode) {
370 RSAPublicKey* kernel_sign_key = NULL; 406 RSAPublicKey* kernel_sign_key = NULL;
371 uint8_t* header_digest = NULL; 407 uint8_t* header_digest = NULL;
372 uint8_t* preamble_digest = NULL; 408 uint8_t* preamble_digest = NULL;
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 Free(kernel_signature); 576 Free(kernel_signature);
541 Free(kernel_buf); 577 Free(kernel_buf);
542 return 1; 578 return 1;
543 } 579 }
544 580
545 void PrintKernelEntry(kernel_entry* entry) { 581 void PrintKernelEntry(kernel_entry* entry) {
546 debug("Boot Priority = %d\n", entry->boot_priority); 582 debug("Boot Priority = %d\n", entry->boot_priority);
547 debug("Boot Tries Remaining = %d\n", entry->boot_tries_remaining); 583 debug("Boot Tries Remaining = %d\n", entry->boot_tries_remaining);
548 debug("Boot Success Flag = %d\n", entry->boot_success_flag); 584 debug("Boot Success Flag = %d\n", entry->boot_success_flag);
549 } 585 }
586
587 // Return the smallest integral multiple of [alignment] that is equal to or
588 // greater than [val]. Used to determine the number of
589 // pages/sectors/blocks/whatever needed to contain [val] items/bytes/etc.
590 static uint64_t roundup(uint64_t val, uint64_t alignment) {
591 uint64_t rem = val % alignment;
592 if ( rem )
593 return val + (alignment - rem);
594 return val;
595 }
596
597 // Match regexp /\b--\b/ to delimit the start of the kernel commandline. If we
598 // don't find one, we'll use the whole thing.
599 static unsigned int find_cmdline_start(char *input, unsigned int max_len) {
600 int start = 0;
601 int i;
602 for(i = 0; i < max_len-1 && input[i]; i++) {
603 if (input[i] == '-' && input[i+1] == '-') { // found a "--"
604 if ((i == 0 || input[i-1] == ' ') && // nothing before it
605 (i+2 >= max_len || input[i+2] == ' ')) { // nothing after it
606 start = i+2; // note: hope there's a trailing '\0'
607 break;
608 }
609 }
610 }
611 while(input[start] == ' ') // skip leading spaces
612 start++;
613
614 return start;
615 }
616
617 uint8_t* GenerateKernelBlob(const char* kernel_file,
618 const char* config_file,
619 const char* bootloader_file,
620 uint64_t* ret_blob_len,
621 uint64_t* ret_bootloader_offset,
622 uint64_t* ret_bootloader_size) {
623 uint8_t* kernel_buf;
624 uint8_t* config_buf;
625 uint8_t* bootloader_buf;
626 uint8_t* blob = 0;
627 uint64_t kernel_size;
628 uint64_t config_size;
629 uint64_t bootloader_size;
630 uint64_t blob_size;
631 uint64_t kernel32_start = 0;
632 uint64_t kernel32_size = 0;
633 uint64_t bootloader_mem_start;
634 uint64_t bootloader_mem_size;
635 uint64_t now;
636 struct linux_kernel_header *lh = 0;
637 struct linux_kernel_params *params = 0;
638 uint32_t cmdline_addr;
639 uint64_t i;
640
641 // Read the input files.
642 kernel_buf = BufferFromFile(kernel_file, &kernel_size);
643 if (!kernel_buf)
644 goto done0;
645
646 config_buf = BufferFromFile(config_file, &config_size);
647 if (!config_buf)
648 goto done1;
649 if (config_size < CROS_CONFIG_SIZE) // need room for trailing '\0'
650 goto done1;
651
652 // Replace any newlines with spaces in the config file.
653 for (i=0; i < config_size; i++)
654 if (config_buf[i] == '\n')
655 config_buf[i] = ' ';
656
657 bootloader_buf = BufferFromFile(bootloader_file, &bootloader_size);
658 if (!bootloader_buf)
659 goto done2;
660
661 // The first part of vmlinuz is a header, followed by a real-mode boot stub.
662 // We only want the 32-bit part.
663 if (kernel_size) {
664 lh = (struct linux_kernel_header *)kernel_buf;
665 kernel32_start = (lh->setup_sects+1) << 9;
666 kernel32_size = kernel_size - kernel32_start;
667 }
668
669 // Allocate and zero the blob we need.
670 blob_size = roundup(kernel32_size, CROS_ALIGN) +
671 CROS_CONFIG_SIZE +
672 CROS_PARAMS_SIZE +
673 roundup(bootloader_size, CROS_ALIGN);
674 blob = (uint8_t *)Malloc(blob_size);
675 if (!blob)
676 goto done3;
677 Memset(blob, 0, blob_size);
678 now = 0;
679
680 // Copy the 32-bit kernel.
681 if (kernel32_size)
682 Memcpy(blob + now, kernel_buf + kernel32_start, kernel32_size);
683 now += roundup(now + kernel32_size, CROS_ALIGN);
684
685 // Find the load address of the commandline. We'll need it later.
686 cmdline_addr = CROS_32BIT_ENTRY_ADDR + now
687 + find_cmdline_start((char *)config_buf, config_size);
688
689 // Copy the config.
690 if (config_size)
691 Memcpy(blob + now, config_buf, config_size);
692 now += CROS_CONFIG_SIZE;
693
694 // The zeropage data is next. Overlay the linux_kernel_header onto it, and
695 // tweak a few fields.
696 params = (struct linux_kernel_params *)(blob + now);
697
698 if (kernel_size)
699 Memcpy(&(params->setup_sects), &(lh->setup_sects),
700 sizeof(*lh) - offsetof(struct linux_kernel_header, setup_sects));
701 params->boot_flag = 0;
702 params->ramdisk_image = 0; // we don't support initrd
703 params->ramdisk_size = 0;
704 params->type_of_loader = 0xff;
705 params->cmd_line_ptr = cmdline_addr;
706 now += CROS_PARAMS_SIZE;
707
708 // Finally, append the bootloader. Remember where it will load in memory, too.
709 bootloader_mem_start = CROS_32BIT_ENTRY_ADDR + now;
710 bootloader_mem_size = roundup(bootloader_size, CROS_ALIGN);
711 if (bootloader_size)
712 Memcpy(blob + now, bootloader_buf, bootloader_size);
713 now += bootloader_mem_size;
714
715 // Pass back some info.
716 if (ret_blob_len)
717 *ret_blob_len = blob_size;
718 if (ret_bootloader_offset)
719 *ret_bootloader_offset = bootloader_mem_start;
720 if (ret_bootloader_size)
721 *ret_bootloader_size = bootloader_mem_size;
722
723 // Clean up and return the blob.
724 done3:
725 Free(bootloader_buf);
726 done2:
727 Free(config_buf);
728 done1:
729 Free(kernel_buf);
730 done0:
731 return blob;
732 }
OLDNEW
« no previous file with comments | « src/platform/vboot_reference/vkernel/include/kernel_image.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698