| OLD | NEW |
| 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 * Verified boot kernel utility | 5 * Verified boot kernel utility |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <getopt.h> | 9 #include <getopt.h> |
| 10 #include <inttypes.h> /* For PRIu64 */ | 10 #include <inttypes.h> /* For PRIu64 */ |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 /* Global opt */ | 26 /* Global opt */ |
| 27 static int opt_debug = 0; | 27 static int opt_debug = 0; |
| 28 | 28 |
| 29 static const int DEFAULT_PADDING = 65536; | 29 static const int DEFAULT_PADDING = 65536; |
| 30 | 30 |
| 31 /* Command line options */ | 31 /* Command line options */ |
| 32 enum { | 32 enum { |
| 33 OPT_MODE_PACK = 1000, | 33 OPT_MODE_PACK = 1000, |
| 34 OPT_MODE_REPACK, | 34 OPT_MODE_REPACK, |
| 35 OPT_MODE_VERIFY, | 35 OPT_MODE_VERIFY, |
| 36 OPT_ARCH, |
| 36 OPT_OLDBLOB, | 37 OPT_OLDBLOB, |
| 37 OPT_KEYBLOCK, | 38 OPT_KEYBLOCK, |
| 38 OPT_SIGNPUBKEY, | 39 OPT_SIGNPUBKEY, |
| 39 OPT_SIGNPRIVATE, | 40 OPT_SIGNPRIVATE, |
| 40 OPT_VERSION, | 41 OPT_VERSION, |
| 41 OPT_VMLINUZ, | 42 OPT_VMLINUZ, |
| 42 OPT_BOOTLOADER, | 43 OPT_BOOTLOADER, |
| 43 OPT_CONFIG, | 44 OPT_CONFIG, |
| 44 OPT_VBLOCKONLY, | 45 OPT_VBLOCKONLY, |
| 45 OPT_PAD, | 46 OPT_PAD, |
| 46 OPT_VERBOSE, | 47 OPT_VERBOSE, |
| 47 }; | 48 }; |
| 48 | 49 |
| 50 enum { |
| 51 ARCH_NO_SUCH_ARCHITECTURE = -1, |
| 52 ARCH_ARM, |
| 53 ARCH_X86 |
| 54 }; |
| 55 |
| 49 static struct option long_opts[] = { | 56 static struct option long_opts[] = { |
| 50 {"pack", 1, 0, OPT_MODE_PACK }, | 57 {"pack", 1, 0, OPT_MODE_PACK }, |
| 51 {"repack", 1, 0, OPT_MODE_REPACK }, | 58 {"repack", 1, 0, OPT_MODE_REPACK }, |
| 52 {"verify", 1, 0, OPT_MODE_VERIFY }, | 59 {"verify", 1, 0, OPT_MODE_VERIFY }, |
| 60 {"arch", 1, 0, OPT_ARCH }, |
| 53 {"oldblob", 1, 0, OPT_OLDBLOB }, | 61 {"oldblob", 1, 0, OPT_OLDBLOB }, |
| 54 {"keyblock", 1, 0, OPT_KEYBLOCK }, | 62 {"keyblock", 1, 0, OPT_KEYBLOCK }, |
| 55 {"signpubkey", 1, 0, OPT_SIGNPUBKEY }, | 63 {"signpubkey", 1, 0, OPT_SIGNPUBKEY }, |
| 56 {"signprivate", 1, 0, OPT_SIGNPRIVATE }, | 64 {"signprivate", 1, 0, OPT_SIGNPRIVATE }, |
| 57 {"version", 1, 0, OPT_VERSION }, | 65 {"version", 1, 0, OPT_VERSION }, |
| 58 {"vmlinuz", 1, 0, OPT_VMLINUZ }, | 66 {"vmlinuz", 1, 0, OPT_VMLINUZ }, |
| 59 {"bootloader", 1, 0, OPT_BOOTLOADER }, | 67 {"bootloader", 1, 0, OPT_BOOTLOADER }, |
| 60 {"config", 1, 0, OPT_CONFIG }, | 68 {"config", 1, 0, OPT_CONFIG }, |
| 61 {"vblockonly", 0, 0, OPT_VBLOCKONLY }, | 69 {"vblockonly", 0, 0, OPT_VBLOCKONLY }, |
| 62 {"pad", 1, 0, OPT_PAD }, | 70 {"pad", 1, 0, OPT_PAD }, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 75 "Usage: %s --pack <file> [PARAMETERS]\n" | 83 "Usage: %s --pack <file> [PARAMETERS]\n" |
| 76 "\n" | 84 "\n" |
| 77 " Required parameters:\n" | 85 " Required parameters:\n" |
| 78 " --keyblock <file> Key block in .keyblock format\n" | 86 " --keyblock <file> Key block in .keyblock format\n" |
| 79 " --signprivate <file>" | 87 " --signprivate <file>" |
| 80 " Private key to sign kernel data, in .vbprivk format\n" | 88 " Private key to sign kernel data, in .vbprivk format\n" |
| 81 " --version <number> Kernel version\n" | 89 " --version <number> Kernel version\n" |
| 82 " --vmlinuz <file> Linux kernel bzImage file\n" | 90 " --vmlinuz <file> Linux kernel bzImage file\n" |
| 83 " --bootloader <file> Bootloader stub\n" | 91 " --bootloader <file> Bootloader stub\n" |
| 84 " --config <file> Command line file\n" | 92 " --config <file> Command line file\n" |
| 93 " --arch <arch> Cpu architecture\n" |
| 85 "\n" | 94 "\n" |
| 86 " Optional:\n" | 95 " Optional:\n" |
| 87 " --pad <number> Verification padding size in bytes\n" | 96 " --pad <number> Verification padding size in bytes\n" |
| 88 " --vblockonly Emit just the verification blob\n", | 97 " --vblockonly Emit just the verification blob\n", |
| 89 progname); | 98 progname); |
| 90 fprintf(stderr, | 99 fprintf(stderr, |
| 91 "\nOR\n\n" | 100 "\nOR\n\n" |
| 92 "Usage: %s --repack <file> [PARAMETERS]\n" | 101 "Usage: %s --repack <file> [PARAMETERS]\n" |
| 93 "\n" | 102 "\n" |
| 94 " Required parameters (of --keyblock, --config, and --version \n" | 103 " Required parameters (of --keyblock, --config, and --version \n" |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 config_buf[ii] = ' '; | 242 config_buf[ii] = ' '; |
| 234 } | 243 } |
| 235 } | 244 } |
| 236 return config_buf; | 245 return config_buf; |
| 237 } | 246 } |
| 238 | 247 |
| 239 /* Create a blob from its components */ | 248 /* Create a blob from its components */ |
| 240 static blob_t *NewBlob(uint64_t version, | 249 static blob_t *NewBlob(uint64_t version, |
| 241 const char* vmlinuz, | 250 const char* vmlinuz, |
| 242 const char* bootloader_file, | 251 const char* bootloader_file, |
| 243 const char* config_file) { | 252 const char* config_file, |
| 244 blob_t *bp; | 253 int arch) { |
| 245 struct linux_kernel_header *lh = 0; | 254 blob_t* bp; |
| 246 struct linux_kernel_params *params = 0; | 255 struct linux_kernel_header* lh = 0; |
| 256 struct linux_kernel_params* params = 0; |
| 247 uint8_t* config_buf; | 257 uint8_t* config_buf; |
| 248 uint64_t config_size; | 258 uint64_t config_size; |
| 249 uint8_t* bootloader_buf; | 259 uint8_t* bootloader_buf; |
| 250 uint64_t bootloader_size; | 260 uint64_t bootloader_size; |
| 251 uint8_t* kernel_buf; | 261 uint8_t* kernel_buf; |
| 252 uint64_t kernel_size; | 262 uint64_t kernel_size; |
| 253 uint64_t kernel32_start = 0; | 263 uint64_t kernel32_start = 0; |
| 254 uint64_t kernel32_size = 0; | 264 uint64_t kernel32_size = 0; |
| 255 uint32_t cmdline_addr; | 265 uint32_t cmdline_addr; |
| 256 uint8_t* blob = NULL; | 266 uint8_t* blob = NULL; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 287 Debug("Reading %s\n", vmlinuz); | 297 Debug("Reading %s\n", vmlinuz); |
| 288 kernel_buf = ReadFile(vmlinuz, &kernel_size); | 298 kernel_buf = ReadFile(vmlinuz, &kernel_size); |
| 289 if (!kernel_buf) | 299 if (!kernel_buf) |
| 290 return 0; | 300 return 0; |
| 291 Debug(" kernel file size=0x%" PRIx64 "\n", kernel_size); | 301 Debug(" kernel file size=0x%" PRIx64 "\n", kernel_size); |
| 292 if (!kernel_size) { | 302 if (!kernel_size) { |
| 293 error("Empty kernel file\n"); | 303 error("Empty kernel file\n"); |
| 294 return 0; | 304 return 0; |
| 295 } | 305 } |
| 296 | 306 |
| 297 /* The first part of vmlinuz is a header, followed by a real-mode | 307 if (arch == ARCH_X86) { |
| 298 * boot stub. We only want the 32-bit part. */ | 308 /* The first part of vmlinuz is a header, followed by a real-mode |
| 299 lh = (struct linux_kernel_header *)kernel_buf; | 309 * boot stub. We only want the 32-bit part. */ |
| 300 kernel32_start = (lh->setup_sects + 1) << 9; | 310 lh = (struct linux_kernel_header *)kernel_buf; |
| 301 if (kernel32_start >= kernel_size) { | 311 kernel32_start = (lh->setup_sects + 1) << 9; |
| 302 error("Malformed kernel\n"); | 312 if (kernel32_start >= kernel_size) { |
| 303 return 0; | 313 error("Malformed kernel\n"); |
| 304 } | 314 return 0; |
| 315 } |
| 316 } else |
| 317 kernel32_start = 0; |
| 305 kernel32_size = kernel_size - kernel32_start; | 318 kernel32_size = kernel_size - kernel32_start; |
| 306 Debug(" kernel32_start=0x%" PRIx64 "\n", kernel32_start); | 319 Debug(" kernel32_start=0x%" PRIx64 "\n", kernel32_start); |
| 307 Debug(" kernel32_size=0x%" PRIx64 "\n", kernel32_size); | 320 Debug(" kernel32_size=0x%" PRIx64 "\n", kernel32_size); |
| 308 | 321 |
| 309 /* Allocate and zero the blob we need. */ | 322 /* Allocate and zero the blob we need. */ |
| 310 bp->blob_size = roundup(kernel32_size, CROS_ALIGN) + | 323 bp->blob_size = roundup(kernel32_size, CROS_ALIGN) + |
| 311 CROS_CONFIG_SIZE + | 324 CROS_CONFIG_SIZE + |
| 312 CROS_PARAMS_SIZE + | 325 CROS_PARAMS_SIZE + |
| 313 roundup(bootloader_size, CROS_ALIGN); | 326 roundup(bootloader_size, CROS_ALIGN); |
| 314 blob = (uint8_t *)Malloc(bp->blob_size); | 327 blob = (uint8_t *)Malloc(bp->blob_size); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 334 | 347 |
| 335 /* Copy the config. */ | 348 /* Copy the config. */ |
| 336 if (config_size) | 349 if (config_size) |
| 337 Memcpy(blob + now, config_buf, config_size); | 350 Memcpy(blob + now, config_buf, config_size); |
| 338 now += CROS_CONFIG_SIZE; | 351 now += CROS_CONFIG_SIZE; |
| 339 | 352 |
| 340 /* The zeropage data is next. Overlay the linux_kernel_header onto it, and | 353 /* The zeropage data is next. Overlay the linux_kernel_header onto it, and |
| 341 * tweak a few fields. */ | 354 * tweak a few fields. */ |
| 342 Debug("params goes at blob+=0x%" PRIx64 "\n", now); | 355 Debug("params goes at blob+=0x%" PRIx64 "\n", now); |
| 343 params = (struct linux_kernel_params *)(blob + now); | 356 params = (struct linux_kernel_params *)(blob + now); |
| 344 Memcpy(&(params->setup_sects), &(lh->setup_sects), | 357 if (arch == ARCH_X86) |
| 345 sizeof(*lh) - offsetof(struct linux_kernel_header, setup_sects)); | 358 Memcpy(&(params->setup_sects), &(lh->setup_sects), |
| 359 sizeof(*lh) - offsetof(struct linux_kernel_header, setup_sects)); |
| 360 else |
| 361 Memset(&(params->setup_sects), 0, |
| 362 sizeof(*lh) - offsetof(struct linux_kernel_header, setup_sects)); |
| 346 params->boot_flag = 0; | 363 params->boot_flag = 0; |
| 347 params->ramdisk_image = 0; /* we don't support initrd */ | 364 params->ramdisk_image = 0; /* we don't support initrd */ |
| 348 params->ramdisk_size = 0; | 365 params->ramdisk_size = 0; |
| 349 params->type_of_loader = 0xff; | 366 params->type_of_loader = 0xff; |
| 350 params->cmd_line_ptr = cmdline_addr; | 367 params->cmd_line_ptr = cmdline_addr; |
| 351 /* A fake e820 memory map with 2 entries */ | 368 /* A fake e820 memory map with 2 entries */ |
| 352 params->n_e820_entry = 2; | 369 params->n_e820_entry = 2; |
| 353 params->e820_entries[0].start_addr = 0x00000000; | 370 params->e820_entries[0].start_addr = 0x00000000; |
| 354 params->e820_entries[0].segment_size = 0x00001000; | 371 params->e820_entries[0].segment_size = 0x00001000; |
| 355 params->e820_entries[0].segment_type = E820_TYPE_RAM; | 372 params->e820_entries[0].segment_type = E820_TYPE_RAM; |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 int main(int argc, char* argv[]) { | 781 int main(int argc, char* argv[]) { |
| 765 char* filename = NULL; | 782 char* filename = NULL; |
| 766 char* oldfile = NULL; | 783 char* oldfile = NULL; |
| 767 char* key_block_file = NULL; | 784 char* key_block_file = NULL; |
| 768 char* signpubkey = NULL; | 785 char* signpubkey = NULL; |
| 769 char* signprivate = NULL; | 786 char* signprivate = NULL; |
| 770 int version = -1; | 787 int version = -1; |
| 771 char* vmlinuz = NULL; | 788 char* vmlinuz = NULL; |
| 772 char* bootloader = NULL; | 789 char* bootloader = NULL; |
| 773 char* config_file = NULL; | 790 char* config_file = NULL; |
| 791 int arch = ARCH_NO_SUCH_ARCHITECTURE; |
| 774 int vblockonly = 0; | 792 int vblockonly = 0; |
| 775 int verbose = 0; | 793 int verbose = 0; |
| 776 uint64_t pad = DEFAULT_PADDING; | 794 uint64_t pad = DEFAULT_PADDING; |
| 777 int mode = 0; | 795 int mode = 0; |
| 778 int parse_error = 0; | 796 int parse_error = 0; |
| 779 char* e; | 797 char* e; |
| 780 int i,r; | 798 int i,r; |
| 781 blob_t *bp; | 799 blob_t *bp; |
| 782 | 800 |
| 783 | 801 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 805 case OPT_MODE_VERIFY: | 823 case OPT_MODE_VERIFY: |
| 806 if (mode && (mode != i)) { | 824 if (mode && (mode != i)) { |
| 807 fprintf(stderr, "Only single mode can be specified\n"); | 825 fprintf(stderr, "Only single mode can be specified\n"); |
| 808 parse_error = 1; | 826 parse_error = 1; |
| 809 break; | 827 break; |
| 810 } | 828 } |
| 811 mode = i; | 829 mode = i; |
| 812 filename = optarg; | 830 filename = optarg; |
| 813 break; | 831 break; |
| 814 | 832 |
| 833 case OPT_ARCH: |
| 834 if (!strcasecmp(optarg, "x86")) |
| 835 arch = ARCH_X86; |
| 836 else if (!strcasecmp(optarg, "arm")) |
| 837 arch = ARCH_ARM; |
| 838 else { |
| 839 fprintf(stderr, "Unknown architecture string: %s\n", optarg); |
| 840 parse_error = 1; |
| 841 } |
| 842 break; |
| 843 |
| 815 case OPT_OLDBLOB: | 844 case OPT_OLDBLOB: |
| 816 oldfile = optarg; | 845 oldfile = optarg; |
| 817 break; | 846 break; |
| 818 | 847 |
| 819 case OPT_KEYBLOCK: | 848 case OPT_KEYBLOCK: |
| 820 key_block_file = optarg; | 849 key_block_file = optarg; |
| 821 break; | 850 break; |
| 822 | 851 |
| 823 case OPT_SIGNPUBKEY: | 852 case OPT_SIGNPUBKEY: |
| 824 signpubkey = optarg; | 853 signpubkey = optarg; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 864 verbose = 1; | 893 verbose = 1; |
| 865 break; | 894 break; |
| 866 } | 895 } |
| 867 } | 896 } |
| 868 | 897 |
| 869 if (parse_error) | 898 if (parse_error) |
| 870 return PrintHelp(progname); | 899 return PrintHelp(progname); |
| 871 | 900 |
| 872 switch(mode) { | 901 switch(mode) { |
| 873 case OPT_MODE_PACK: | 902 case OPT_MODE_PACK: |
| 874 bp = NewBlob(version, vmlinuz, bootloader, config_file); | 903 if (arch == ARCH_NO_SUCH_ARCHITECTURE) { |
| 904 fprintf(stderr, "You must specify --arch\n"); |
| 905 return 1; |
| 906 } |
| 907 bp = NewBlob(version, vmlinuz, bootloader, config_file, arch); |
| 875 if (!bp) | 908 if (!bp) |
| 876 return 1; | 909 return 1; |
| 877 r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly); | 910 r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly); |
| 878 FreeBlob(bp); | 911 FreeBlob(bp); |
| 879 return r; | 912 return r; |
| 880 | 913 |
| 881 case OPT_MODE_REPACK: | 914 case OPT_MODE_REPACK: |
| 882 if (!config_file && !key_block_file && (version<0)) { | 915 if (!config_file && !key_block_file && (version<0)) { |
| 883 fprintf(stderr, | 916 fprintf(stderr, |
| 884 "You must supply at least one of " | 917 "You must supply at least one of " |
| 885 "--config, --keyblock or --version\n"); | 918 "--config, --keyblock or --version\n"); |
| 886 return 1; | 919 return 1; |
| 887 } | 920 } |
| 888 | 921 |
| 889 bp = OldBlob(oldfile); | 922 bp = OldBlob(oldfile); |
| 890 if (!bp) | 923 if (!bp) |
| 891 return 1; | 924 return 1; |
| 892 r = ReplaceConfig(bp, config_file); | 925 r = ReplaceConfig(bp, config_file); |
| 893 if (!r) { | 926 if (!r) { |
| 894 if (version >= 0) { | 927 if (version >= 0) { |
| 895 » » bp->kernel_version = (uint64_t) version; | 928 bp->kernel_version = (uint64_t) version; |
| 896 } | 929 } |
| 897 r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly); | 930 r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly); |
| 898 } | 931 } |
| 899 FreeBlob(bp); | 932 FreeBlob(bp); |
| 900 return r; | 933 return r; |
| 901 | 934 |
| 902 case OPT_MODE_VERIFY: | 935 case OPT_MODE_VERIFY: |
| 903 return Verify(filename, signpubkey, verbose, key_block_file); | 936 return Verify(filename, signpubkey, verbose, key_block_file); |
| 904 | 937 |
| 905 default: | 938 default: |
| 906 fprintf(stderr, | 939 fprintf(stderr, |
| 907 "You must specify a mode: --pack, --repack or --verify\n"); | 940 "You must specify a mode: --pack, --repack or --verify\n"); |
| 908 return PrintHelp(progname); | 941 return PrintHelp(progname); |
| 909 } | 942 } |
| 910 } | 943 } |
| OLD | NEW |