extract_vmlinuz.c 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /* Copyright 2015 The Chromium OS Authors. All rights reserved.
  2. * Use of this source code is governed by a BSD-style license that can be
  3. * found in the LICENSE file.
  4. *
  5. * Exports a vmlinuz from a kernel partition in memory.
  6. */
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include "vb2_struct.h"
  10. #include "vboot_struct.h"
  11. int ExtractVmlinuz(void *kpart_data, size_t kpart_size,
  12. void **vmlinuz_out, size_t *vmlinuz_size) {
  13. size_t now = 0;
  14. struct vb2_kernel_preamble *preamble = NULL;
  15. uint8_t *kblob_data = NULL;
  16. uint32_t kblob_size = 0;
  17. uint32_t vmlinuz_header_size = 0;
  18. uint64_t vmlinuz_header_address = 0;
  19. uint64_t vmlinuz_header_offset = 0;
  20. void *vmlinuz = NULL;
  21. struct vb2_keyblock *keyblock = (struct vb2_keyblock *)kpart_data;
  22. now += keyblock->keyblock_size;
  23. if (now > kpart_size)
  24. return 1;
  25. preamble = (struct vb2_kernel_preamble *)(kpart_data + now);
  26. now += preamble->preamble_size;
  27. if (now > kpart_size)
  28. return 1;
  29. kblob_data = kpart_data + now;
  30. kblob_size = preamble->body_signature.data_size;
  31. if (!kblob_data || (now + kblob_size) > kpart_size)
  32. return 1;
  33. if (preamble->header_version_minor > 0) {
  34. vmlinuz_header_address = preamble->vmlinuz_header_address;
  35. vmlinuz_header_size = preamble->vmlinuz_header_size;
  36. }
  37. if (!vmlinuz_header_size ||
  38. kpart_data + vmlinuz_header_offset + vmlinuz_header_size >
  39. kpart_data) {
  40. return 1;
  41. }
  42. // calculate the vmlinuz_header offset from
  43. // the beginning of the kpart_data. The kblob doesn't
  44. // include the body_load_offset, but does include
  45. // the keyblock and preamble sections.
  46. vmlinuz_header_offset = vmlinuz_header_address -
  47. preamble->body_load_address +
  48. keyblock->keyblock_size +
  49. preamble->preamble_size;
  50. vmlinuz = malloc(vmlinuz_header_size + kblob_size);
  51. if (vmlinuz == NULL)
  52. return 1;
  53. memcpy(vmlinuz, kpart_data + vmlinuz_header_offset,
  54. vmlinuz_header_size);
  55. memcpy(vmlinuz + vmlinuz_header_size, kblob_data, kblob_size);
  56. *vmlinuz_out = vmlinuz;
  57. *vmlinuz_size = vmlinuz_header_size + kblob_size;
  58. return 0;
  59. }