Loading fastboot/bootimg_utils.cpp +17 −22 Original line number Diff line number Diff line Loading @@ -34,16 +34,15 @@ #include <stdlib.h> #include <string.h> void bootimg_set_cmdline(boot_img_hdr_v1* h, const char* cmdline) { if (strlen(cmdline) >= sizeof(h->cmdline)) die("command line too large: %zu", strlen(cmdline)); strcpy(reinterpret_cast<char*>(h->cmdline), cmdline); void bootimg_set_cmdline(boot_img_hdr_v1* h, const std::string& cmdline) { if (cmdline.size() >= sizeof(h->cmdline)) die("command line too large: %zu", cmdline.size()); strcpy(reinterpret_cast<char*>(h->cmdline), cmdline.c_str()); } boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offset, void* ramdisk, int64_t ramdisk_size, off_t ramdisk_offset, void* second, int64_t second_size, off_t second_offset, size_t page_size, size_t base, off_t tags_offset, uint32_t header_version, int64_t* bootimg_size) { size_t page_mask = page_size - 1; boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, void* ramdisk, int64_t ramdisk_size, void* second, int64_t second_size, size_t base, const boot_img_hdr_v1& src, int64_t* bootimg_size) { const size_t page_mask = src.page_size - 1; int64_t header_actual = sizeof(boot_img_hdr_v1) & (~page_mask); int64_t kernel_actual = (kernel_size + page_mask) & (~page_mask); Loading @@ -53,30 +52,26 @@ boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offse *bootimg_size = header_actual + kernel_actual + ramdisk_actual + second_actual; boot_img_hdr_v1* hdr = reinterpret_cast<boot_img_hdr_v1*>(calloc(*bootimg_size, 1)); if (hdr == nullptr) { return hdr; } if (hdr == nullptr) die("couldn't allocate boot image: %" PRId64 " bytes", *bootimg_size); *hdr = src; memcpy(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE); hdr->kernel_size = kernel_size; hdr->ramdisk_size = ramdisk_size; hdr->second_size = second_size; hdr->kernel_addr = base + kernel_offset; hdr->ramdisk_addr = base + ramdisk_offset; hdr->second_addr = base + second_offset; hdr->tags_addr = base + tags_offset; hdr->page_size = page_size; hdr->kernel_addr += base; hdr->ramdisk_addr += base; hdr->second_addr += base; hdr->tags_addr += base; if (header_version) { hdr->header_version = header_version; if (hdr->header_version != 0) { hdr->header_size = sizeof(boot_img_hdr_v1); } memcpy(hdr->magic + page_size, kernel, kernel_size); memcpy(hdr->magic + page_size + kernel_actual, ramdisk, ramdisk_size); memcpy(hdr->magic + page_size + kernel_actual + ramdisk_actual, second, second_size); memcpy(hdr->magic + hdr->page_size, kernel, kernel_size); memcpy(hdr->magic + hdr->page_size + kernel_actual, ramdisk, ramdisk_size); memcpy(hdr->magic + hdr->page_size + kernel_actual + ramdisk_actual, second, second_size); return hdr; } fastboot/bootimg_utils.h +6 −8 Original line number Diff line number Diff line Loading @@ -26,17 +26,15 @@ * SUCH DAMAGE. */ #ifndef _FASTBOOT_BOOTIMG_UTILS_H_ #define _FASTBOOT_BOOTIMG_UTILS_H_ #pragma once #include <bootimg.h> #include <inttypes.h> #include <sys/types.h> void bootimg_set_cmdline(boot_img_hdr_v1* h, const char* cmdline); boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offset, void* ramdisk, int64_t ramdisk_size, off_t ramdisk_offset, void* second, int64_t second_size, off_t second_offset, size_t page_size, size_t base, off_t tags_offset, uint32_t header_version, int64_t* bootimg_size); #include <string> #endif boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, void* ramdisk, int64_t ramdisk_size, void* second, int64_t second_size, size_t base, const boot_img_hdr_v1& src, int64_t* bootimg_size); void bootimg_set_cmdline(boot_img_hdr_v1* h, const std::string& cmdline); fastboot/fastboot.cpp +134 −123 Original line number Diff line number Diff line Loading @@ -76,9 +76,9 @@ using android::base::unique_fd; char cur_product[FB_RESPONSE_SZ + 1]; static const char* serial = nullptr; static const char* cmdline = nullptr; static unsigned short vendor_id = 0; static int long_listing = 0; static bool g_long_listing = false; // Don't resparse files in too-big chunks. // libsparse will support INT_MAX, but this results in large allocations, so // let's keep it at 1GB to avoid memory pressure on the host. Loading @@ -86,12 +86,9 @@ static constexpr int64_t RESPARSE_LIMIT = 1 * 1024 * 1024 * 1024; static int64_t sparse_limit = -1; static int64_t target_sparse_limit = -1; static unsigned page_size = 2048; static unsigned base_addr = 0x10000000; static unsigned kernel_offset = 0x00008000; static unsigned ramdisk_offset = 0x01000000; static unsigned second_offset = 0x00f00000; static unsigned tags_offset = 0x00000100; static unsigned g_base_addr = 0x10000000; static boot_img_hdr_v1 g_boot_img_hdr = {}; static std::string g_cmdline; static bool g_disable_verity = false; static bool g_disable_verification = false; Loading Loading @@ -223,7 +220,7 @@ static int list_devices_callback(usb_ifc_info* info) { serial = "????????????"; } // output compatible with "adb devices" if (!long_listing) { if (!g_long_listing) { printf("%s\tfastboot", serial.c_str()); } else { printf("%-22s fastboot", serial.c_str()); Loading Loading @@ -360,14 +357,18 @@ static int show_help() { " Download and boot kernel from RAM.\n" " flash:raw PARTITION KERNEL [RAMDISK [SECOND]]\n" " Create boot image and flash it.\n" // TODO: give -c a long option, and remove the short options for this group? " -c CMDLINE Override kernel command line.\n" " --cmdline CMDLINE Override kernel command line.\n" " --base ADDRESS Set kernel base address (default: 0x10000000).\n" " --kernel-offset Set kernel offset (default: 0x00008000).\n" " --ramdisk-offset Set ramdisk offset (default: 0x01000000).\n" " --tags-offset Set tags offset (default: 0x00000100).\n" " --page-size BYTES Set flash page size (default: 2048).\n" " --header-version VERSION Set boot image header version.\n" " --os-version MAJOR[.MINOR[.PATCH]]\n" " Set boot image OS version (default: 0.0.0).\n" " --os-patch-level YYYY-MM-DD\n" " Set boot image OS security patch level.\n" // TODO: still missing: `second_addr`, `name`, `id`, `recovery_dtbo_*`. "\n" // TODO: what device(s) used this? is there any documentation? //" continue Continue with autoboot.\n" Loading Loading @@ -404,8 +405,7 @@ static int show_help() { } static void* load_bootable_image(const std::string& kernel, const std::string& ramdisk, const std::string& second_stage, int64_t* sz, const char* cmdline, uint32_t header_version) { const std::string& second_stage, int64_t* sz) { int64_t ksize; void* kdata = load_file(kernel.c_str(), &ksize); if (kdata == nullptr) die("cannot load '%s': %s", kernel.c_str(), strerror(errno)); Loading @@ -415,12 +415,14 @@ static void* load_bootable_image(const std::string& kernel, const std::string& r die("cannot load '%s': too short", kernel.c_str()); } if (!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { if (cmdline) bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v1*>(kdata), cmdline); if (!g_cmdline.empty()) { bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v1*>(kdata), g_cmdline); } uint32_t header_version_existing = reinterpret_cast<boot_img_hdr_v1*>(kdata)->header_version; if (header_version != header_version_existing) { if (g_boot_img_hdr.header_version != header_version_existing) { die("header version mismatch, expected: %" PRIu32 " found %" PRIu32 "", header_version, header_version_existing); g_boot_img_hdr.header_version, header_version_existing); } if (!ramdisk.empty()) die("cannot boot a boot.img *and* ramdisk"); Loading @@ -444,16 +446,12 @@ static void* load_bootable_image(const std::string& kernel, const std::string& r } fprintf(stderr,"creating boot image...\n"); int64_t bsize = 0; boot_img_hdr_v1* bdata = mkbootimg(kdata, ksize, kernel_offset, rdata, rsize, ramdisk_offset, sdata, ssize, second_offset, page_size, base_addr, tags_offset, header_version, &bsize); boot_img_hdr_v1* bdata = mkbootimg(kdata, ksize, rdata, rsize, sdata, ssize, g_base_addr, g_boot_img_hdr, sz); if (bdata == nullptr) die("failed to create boot.img"); if (cmdline) bootimg_set_cmdline(bdata, cmdline); fprintf(stderr, "creating boot image - %" PRId64 " bytes\n", bsize); *sz = bsize; if (!g_cmdline.empty()) bootimg_set_cmdline(bdata, g_cmdline); fprintf(stderr, "creating boot image - %" PRId64 " bytes\n", *sz); return bdata; } Loading Loading @@ -1422,34 +1420,37 @@ int main(int argc, char **argv) bool skip_secondary = false; bool set_fbe_marker = false; void *data; uint32_t header_version = 0; int64_t sz; int longindex; std::string slot_override; std::string next_active; g_boot_img_hdr.kernel_addr = 0x00008000; g_boot_img_hdr.ramdisk_addr = 0x01000000; g_boot_img_hdr.second_addr = 0x00f00000; g_boot_img_hdr.tags_addr = 0x00000100; g_boot_img_hdr.page_size = 2048; const struct option longopts[] = { {"base", required_argument, 0, 'b'}, {"kernel_offset", required_argument, 0, 'k'}, {"kernel-offset", required_argument, 0, 'k'}, {"page_size", required_argument, 0, 'n'}, {"page-size", required_argument, 0, 'n'}, {"ramdisk_offset", required_argument, 0, 'r'}, {"ramdisk-offset", required_argument, 0, 'r'}, {"tags_offset", required_argument, 0, 't'}, {"tags-offset", required_argument, 0, 't'}, {"base", required_argument, 0, 0}, {"cmdline", required_argument, 0, 0}, {"disable-verification", no_argument, 0, 0}, {"disable-verity", no_argument, 0, 0}, {"header-version", required_argument, 0, 0}, {"help", no_argument, 0, 'h'}, {"unbuffered", no_argument, 0, 0}, {"slot", required_argument, 0, 0}, {"set_active", optional_argument, 0, 'a'}, {"kernel-offset", required_argument, 0, 0}, {"os-patch-level", required_argument, 0, 0}, {"os-version", required_argument, 0, 0}, {"page-size", required_argument, 0, 0}, {"ramdisk-offset", required_argument, 0, 0}, {"set-active", optional_argument, 0, 'a'}, {"skip-secondary", no_argument, 0, 0}, {"skip-reboot", no_argument, 0, 0}, {"skip-secondary", no_argument, 0, 0}, {"slot", required_argument, 0, 0}, {"tags-offset", required_argument, 0, 0}, {"unbuffered", no_argument, 0, 0}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 0}, {"disable-verity", no_argument, 0, 0}, {"disable-verification", no_argument, 0, 0}, {"header-version", required_argument, 0, 0}, #if !defined(_WIN32) {"wipe-and-use-fbe", no_argument, 0, 0}, #endif Loading @@ -1458,51 +1459,89 @@ int main(int argc, char **argv) serial = getenv("ANDROID_SERIAL"); while (1) { int c = getopt_long(argc, argv, "vwb:k:n:r:t:s:S:lc:i:m:ha::", longopts, &longindex); if (c < 0) { break; int c; while ((c = getopt_long(argc, argv, "a::hi:ls:S:vw", longopts, &longindex)) != -1) { if (c == 0) { std::string name{longopts[longindex].name}; if (name == "base") { g_base_addr = strtoul(optarg, 0, 16); } else if (name == "cmdline") { g_cmdline = optarg; } else if (name == "disable-verification") { g_disable_verification = true; } else if (name == "disable-verity") { g_disable_verity = true; } else if (name == "header-version") { g_boot_img_hdr.header_version = strtoul(optarg, nullptr, 0); } else if (name == "kernel-offset") { g_boot_img_hdr.kernel_addr = strtoul(optarg, 0, 16); } else if (name == "os-patch-level") { unsigned year, month, day; if (sscanf(optarg, "%u-%u-%u", &year, &month, &day) != 3) { syntax_error("OS patch level should be YYYY-MM-DD: %s", optarg); } if (year < 2000 || year >= 2128) syntax_error("year out of range: %d", year); if (month < 1 || month > 12) syntax_error("month out of range: %d", month); g_boot_img_hdr.SetOsPatchLevel(year, month); } else if (name == "os-version") { unsigned major = 0, minor = 0, patch = 0; std::vector<std::string> versions = android::base::Split(optarg, "."); if (versions.size() < 1 || versions.size() > 3 || (versions.size() >= 1 && !android::base::ParseUint(versions[0], &major)) || (versions.size() >= 2 && !android::base::ParseUint(versions[1], &minor)) || (versions.size() == 3 && !android::base::ParseUint(versions[2], &patch)) || (major > 0x7f || minor > 0x7f || patch > 0x7f)) { syntax_error("bad OS version: %s", optarg); } g_boot_img_hdr.SetOsVersion(major, minor, patch); } else if (name == "page-size") { g_boot_img_hdr.page_size = strtoul(optarg, nullptr, 0); if (g_boot_img_hdr.page_size == 0) die("invalid page size"); } else if (name == "ramdisk-offset") { g_boot_img_hdr.ramdisk_addr = strtoul(optarg, 0, 16); } else if (name == "skip-reboot") { skip_reboot = true; } else if (name == "skip-secondary") { skip_secondary = true; } else if (name == "slot") { slot_override = optarg; } else if (name == "tags-offset") { g_boot_img_hdr.tags_addr = strtoul(optarg, 0, 16); } else if (name == "unbuffered") { setvbuf(stdout, nullptr, _IONBF, 0); setvbuf(stderr, nullptr, _IONBF, 0); } else if (name == "version") { fprintf(stdout, "fastboot version %s\n", FASTBOOT_VERSION); fprintf(stdout, "Installed as %s\n", android::base::GetExecutablePath().c_str()); return 0; #if !defined(_WIN32) } else if (name == "wipe-and-use-fbe") { wants_wipe = true; set_fbe_marker = true; #endif } else { die("unknown option %s", longopts[longindex].name); } /* Alphabetical cases */ } else { switch (c) { case 'a': wants_set_active = true; if (optarg) next_active = optarg; break; case 'b': base_addr = strtoul(optarg, 0, 16); break; case 'c': cmdline = optarg; if (optarg) next_active = optarg; break; case 'h': return show_help(); case 'i': { case 'i': { char *endptr = nullptr; unsigned long val; val = strtoul(optarg, &endptr, 0); if (!endptr || *endptr != '\0' || (val & ~0xffff)) unsigned long val = strtoul(optarg, &endptr, 0); if (!endptr || *endptr != '\0' || (val & ~0xffff)) { die("invalid vendor id '%s'", optarg); } vendor_id = (unsigned short)val; break; } case 'k': kernel_offset = strtoul(optarg, 0, 16); break; case 'l': long_listing = 1; break; case 'n': page_size = (unsigned)strtoul(optarg, nullptr, 0); if (!page_size) die("invalid page size"); break; case 'r': ramdisk_offset = strtoul(optarg, 0, 16); break; case 't': tags_offset = strtoul(optarg, 0, 16); g_long_listing = true; break; case 's': serial = optarg; Loading @@ -1519,39 +1558,11 @@ int main(int argc, char **argv) break; case '?': return 1; case 0: if (strcmp("unbuffered", longopts[longindex].name) == 0) { setvbuf(stdout, nullptr, _IONBF, 0); setvbuf(stderr, nullptr, _IONBF, 0); } else if (strcmp("version", longopts[longindex].name) == 0) { fprintf(stdout, "fastboot version %s\n", FASTBOOT_VERSION); fprintf(stdout, "Installed as %s\n", android::base::GetExecutablePath().c_str()); return 0; } else if (strcmp("slot", longopts[longindex].name) == 0) { slot_override = std::string(optarg); } else if (strcmp("skip-secondary", longopts[longindex].name) == 0 ) { skip_secondary = true; } else if (strcmp("skip-reboot", longopts[longindex].name) == 0 ) { skip_reboot = true; } else if (strcmp("disable-verity", longopts[longindex].name) == 0 ) { g_disable_verity = true; } else if (strcmp("disable-verification", longopts[longindex].name) == 0 ) { g_disable_verification = true; #if !defined(_WIN32) } else if (strcmp("wipe-and-use-fbe", longopts[longindex].name) == 0) { wants_wipe = true; set_fbe_marker = true; #endif } else if (strcmp("header-version", longopts[longindex].name) == 0) { header_version = strtoul(optarg, nullptr, 0); } else { die("unknown option %s", longopts[longindex].name); } break; default: abort(); } } } argc -= optind; argv += optind; Loading Loading @@ -1668,7 +1679,7 @@ int main(int argc, char **argv) std::string second_stage; if (!args.empty()) second_stage = next_arg(&args); data = load_bootable_image(kernel, ramdisk, second_stage, &sz, cmdline, header_version); data = load_bootable_image(kernel, ramdisk, second_stage, &sz); fb_queue_download("boot.img", data, sz); fb_queue_command("boot", "booting"); } else if (command == "flash") { Loading @@ -1694,7 +1705,7 @@ int main(int argc, char **argv) std::string second_stage; if (!args.empty()) second_stage = next_arg(&args); data = load_bootable_image(kernel, ramdisk, second_stage, &sz, cmdline, header_version); data = load_bootable_image(kernel, ramdisk, second_stage, &sz); auto flashraw = [&](const std::string& partition) { fb_queue_flash(partition, data, sz); }; Loading mkbootimg/include/bootimg/bootimg.h +42 −58 Original line number Diff line number Diff line /* tools/mkbootimg/bootimg.h ** ** Copyright 2007, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. /* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdint.h> #pragma once #ifndef _BOOT_IMAGE_H_ #define _BOOT_IMAGE_H_ #include <stdint.h> #define BOOT_MAGIC "ANDROID!" #define BOOT_MAGIC_SIZE 8 Loading @@ -26,12 +24,10 @@ #define BOOT_ARGS_SIZE 512 #define BOOT_EXTRA_ARGS_SIZE 1024 #define BOOT_HEADER_VERSION_ZERO 0 /* * Bootloader expects the structure of boot_img_hdr with header version * BOOT_HEADER_VERSION_ZERO to be as follows: */ // The bootloader expects the structure of boot_img_hdr with header // version 0 to be as follows: struct boot_img_hdr_v0 { // Must be BOOT_MAGIC. uint8_t magic[BOOT_MAGIC_SIZE]; uint32_t kernel_size; /* size in bytes */ Loading @@ -45,26 +41,36 @@ struct boot_img_hdr_v0 { uint32_t tags_addr; /* physical addr for kernel tags */ uint32_t page_size; /* flash page size we assume */ /* * version for the boot image header. */ // Version of the boot image header. uint32_t header_version; /* operating system version and security patch level; for * version "A.B.C" and patch level "Y-M-D": * ver = A << 14 | B << 7 | C (7 bits for each of A, B, C) * lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M) * os_version = ver << 11 | lvl */ // Operating system version and security patch level. // For version "A.B.C" and patch level "Y-M-D": // (7 bits for each of A, B, C; 7 bits for (Y-2000), 4 bits for M) // os_version = A[31:25] B[24:18] C[17:11] (Y-2000)[10:4] M[3:0] uint32_t os_version; #if __cplusplus void SetOsVersion(unsigned major, unsigned minor, unsigned patch) { os_version &= ((1 << 11) - 1); os_version |= (((major & 0x7f) << 25) | ((minor & 0x7f) << 18) | ((patch & 0x7f) << 11)); } void SetOsPatchLevel(unsigned year, unsigned month) { os_version &= ~((1 << 11) - 1); os_version |= (((year - 2000) & 0x7f) << 4) | ((month & 0xf) << 0); } #endif uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */ uint8_t cmdline[BOOT_ARGS_SIZE]; uint32_t id[8]; /* timestamp / checksum / sha1 / etc */ /* Supplemental command line data; kept here to maintain * binary compatibility with older versions of mkbootimg */ // Supplemental command line data; kept here to maintain // binary compatibility with older versions of mkbootimg. uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE]; } __attribute__((packed)); Loading @@ -74,7 +80,7 @@ struct boot_img_hdr_v0 { */ typedef struct boot_img_hdr_v0 boot_img_hdr; /* When a boot header is of version BOOT_HEADER_VERSION_ZERO, the structure of boot image is as /* When a boot header is of version 0, the structure of boot image is as * follows: * * +-----------------+ Loading Loading @@ -103,15 +109,13 @@ typedef struct boot_img_hdr_v0 boot_img_hdr; * else: jump to kernel_addr */ #define BOOT_HEADER_VERSION_ONE 1 struct boot_img_hdr_v1 : public boot_img_hdr_v0 { uint32_t recovery_dtbo_size; /* size in bytes for recovery DTBO image */ uint64_t recovery_dtbo_offset; /* physical load addr */ uint32_t header_size; } __attribute__((packed)); /* When the boot image header has a version of BOOT_HEADER_VERSION_ONE, the structure of the boot /* When the boot image header has a version of 1, the structure of the boot * image is as follows: * * +-----------------+ Loading Loading @@ -142,23 +146,3 @@ struct boot_img_hdr_v1 : public boot_img_hdr_v0 { * 7. if second_size != 0: jump to second_addr * else: jump to kernel_addr */ #if 0 typedef struct ptentry ptentry; struct ptentry { char name[16]; /* asciiz partition name */ unsigned start; /* starting block number */ unsigned length; /* length in blocks */ unsigned flags; /* set to zero */ }; /* MSM Partition Table ATAG ** ** length: 2 + 7 * n ** atag: 0x4d534d70 ** <ptentry> x n */ #endif #endif Loading
fastboot/bootimg_utils.cpp +17 −22 Original line number Diff line number Diff line Loading @@ -34,16 +34,15 @@ #include <stdlib.h> #include <string.h> void bootimg_set_cmdline(boot_img_hdr_v1* h, const char* cmdline) { if (strlen(cmdline) >= sizeof(h->cmdline)) die("command line too large: %zu", strlen(cmdline)); strcpy(reinterpret_cast<char*>(h->cmdline), cmdline); void bootimg_set_cmdline(boot_img_hdr_v1* h, const std::string& cmdline) { if (cmdline.size() >= sizeof(h->cmdline)) die("command line too large: %zu", cmdline.size()); strcpy(reinterpret_cast<char*>(h->cmdline), cmdline.c_str()); } boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offset, void* ramdisk, int64_t ramdisk_size, off_t ramdisk_offset, void* second, int64_t second_size, off_t second_offset, size_t page_size, size_t base, off_t tags_offset, uint32_t header_version, int64_t* bootimg_size) { size_t page_mask = page_size - 1; boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, void* ramdisk, int64_t ramdisk_size, void* second, int64_t second_size, size_t base, const boot_img_hdr_v1& src, int64_t* bootimg_size) { const size_t page_mask = src.page_size - 1; int64_t header_actual = sizeof(boot_img_hdr_v1) & (~page_mask); int64_t kernel_actual = (kernel_size + page_mask) & (~page_mask); Loading @@ -53,30 +52,26 @@ boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offse *bootimg_size = header_actual + kernel_actual + ramdisk_actual + second_actual; boot_img_hdr_v1* hdr = reinterpret_cast<boot_img_hdr_v1*>(calloc(*bootimg_size, 1)); if (hdr == nullptr) { return hdr; } if (hdr == nullptr) die("couldn't allocate boot image: %" PRId64 " bytes", *bootimg_size); *hdr = src; memcpy(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE); hdr->kernel_size = kernel_size; hdr->ramdisk_size = ramdisk_size; hdr->second_size = second_size; hdr->kernel_addr = base + kernel_offset; hdr->ramdisk_addr = base + ramdisk_offset; hdr->second_addr = base + second_offset; hdr->tags_addr = base + tags_offset; hdr->page_size = page_size; hdr->kernel_addr += base; hdr->ramdisk_addr += base; hdr->second_addr += base; hdr->tags_addr += base; if (header_version) { hdr->header_version = header_version; if (hdr->header_version != 0) { hdr->header_size = sizeof(boot_img_hdr_v1); } memcpy(hdr->magic + page_size, kernel, kernel_size); memcpy(hdr->magic + page_size + kernel_actual, ramdisk, ramdisk_size); memcpy(hdr->magic + page_size + kernel_actual + ramdisk_actual, second, second_size); memcpy(hdr->magic + hdr->page_size, kernel, kernel_size); memcpy(hdr->magic + hdr->page_size + kernel_actual, ramdisk, ramdisk_size); memcpy(hdr->magic + hdr->page_size + kernel_actual + ramdisk_actual, second, second_size); return hdr; }
fastboot/bootimg_utils.h +6 −8 Original line number Diff line number Diff line Loading @@ -26,17 +26,15 @@ * SUCH DAMAGE. */ #ifndef _FASTBOOT_BOOTIMG_UTILS_H_ #define _FASTBOOT_BOOTIMG_UTILS_H_ #pragma once #include <bootimg.h> #include <inttypes.h> #include <sys/types.h> void bootimg_set_cmdline(boot_img_hdr_v1* h, const char* cmdline); boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offset, void* ramdisk, int64_t ramdisk_size, off_t ramdisk_offset, void* second, int64_t second_size, off_t second_offset, size_t page_size, size_t base, off_t tags_offset, uint32_t header_version, int64_t* bootimg_size); #include <string> #endif boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, void* ramdisk, int64_t ramdisk_size, void* second, int64_t second_size, size_t base, const boot_img_hdr_v1& src, int64_t* bootimg_size); void bootimg_set_cmdline(boot_img_hdr_v1* h, const std::string& cmdline);
fastboot/fastboot.cpp +134 −123 Original line number Diff line number Diff line Loading @@ -76,9 +76,9 @@ using android::base::unique_fd; char cur_product[FB_RESPONSE_SZ + 1]; static const char* serial = nullptr; static const char* cmdline = nullptr; static unsigned short vendor_id = 0; static int long_listing = 0; static bool g_long_listing = false; // Don't resparse files in too-big chunks. // libsparse will support INT_MAX, but this results in large allocations, so // let's keep it at 1GB to avoid memory pressure on the host. Loading @@ -86,12 +86,9 @@ static constexpr int64_t RESPARSE_LIMIT = 1 * 1024 * 1024 * 1024; static int64_t sparse_limit = -1; static int64_t target_sparse_limit = -1; static unsigned page_size = 2048; static unsigned base_addr = 0x10000000; static unsigned kernel_offset = 0x00008000; static unsigned ramdisk_offset = 0x01000000; static unsigned second_offset = 0x00f00000; static unsigned tags_offset = 0x00000100; static unsigned g_base_addr = 0x10000000; static boot_img_hdr_v1 g_boot_img_hdr = {}; static std::string g_cmdline; static bool g_disable_verity = false; static bool g_disable_verification = false; Loading Loading @@ -223,7 +220,7 @@ static int list_devices_callback(usb_ifc_info* info) { serial = "????????????"; } // output compatible with "adb devices" if (!long_listing) { if (!g_long_listing) { printf("%s\tfastboot", serial.c_str()); } else { printf("%-22s fastboot", serial.c_str()); Loading Loading @@ -360,14 +357,18 @@ static int show_help() { " Download and boot kernel from RAM.\n" " flash:raw PARTITION KERNEL [RAMDISK [SECOND]]\n" " Create boot image and flash it.\n" // TODO: give -c a long option, and remove the short options for this group? " -c CMDLINE Override kernel command line.\n" " --cmdline CMDLINE Override kernel command line.\n" " --base ADDRESS Set kernel base address (default: 0x10000000).\n" " --kernel-offset Set kernel offset (default: 0x00008000).\n" " --ramdisk-offset Set ramdisk offset (default: 0x01000000).\n" " --tags-offset Set tags offset (default: 0x00000100).\n" " --page-size BYTES Set flash page size (default: 2048).\n" " --header-version VERSION Set boot image header version.\n" " --os-version MAJOR[.MINOR[.PATCH]]\n" " Set boot image OS version (default: 0.0.0).\n" " --os-patch-level YYYY-MM-DD\n" " Set boot image OS security patch level.\n" // TODO: still missing: `second_addr`, `name`, `id`, `recovery_dtbo_*`. "\n" // TODO: what device(s) used this? is there any documentation? //" continue Continue with autoboot.\n" Loading Loading @@ -404,8 +405,7 @@ static int show_help() { } static void* load_bootable_image(const std::string& kernel, const std::string& ramdisk, const std::string& second_stage, int64_t* sz, const char* cmdline, uint32_t header_version) { const std::string& second_stage, int64_t* sz) { int64_t ksize; void* kdata = load_file(kernel.c_str(), &ksize); if (kdata == nullptr) die("cannot load '%s': %s", kernel.c_str(), strerror(errno)); Loading @@ -415,12 +415,14 @@ static void* load_bootable_image(const std::string& kernel, const std::string& r die("cannot load '%s': too short", kernel.c_str()); } if (!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { if (cmdline) bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v1*>(kdata), cmdline); if (!g_cmdline.empty()) { bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v1*>(kdata), g_cmdline); } uint32_t header_version_existing = reinterpret_cast<boot_img_hdr_v1*>(kdata)->header_version; if (header_version != header_version_existing) { if (g_boot_img_hdr.header_version != header_version_existing) { die("header version mismatch, expected: %" PRIu32 " found %" PRIu32 "", header_version, header_version_existing); g_boot_img_hdr.header_version, header_version_existing); } if (!ramdisk.empty()) die("cannot boot a boot.img *and* ramdisk"); Loading @@ -444,16 +446,12 @@ static void* load_bootable_image(const std::string& kernel, const std::string& r } fprintf(stderr,"creating boot image...\n"); int64_t bsize = 0; boot_img_hdr_v1* bdata = mkbootimg(kdata, ksize, kernel_offset, rdata, rsize, ramdisk_offset, sdata, ssize, second_offset, page_size, base_addr, tags_offset, header_version, &bsize); boot_img_hdr_v1* bdata = mkbootimg(kdata, ksize, rdata, rsize, sdata, ssize, g_base_addr, g_boot_img_hdr, sz); if (bdata == nullptr) die("failed to create boot.img"); if (cmdline) bootimg_set_cmdline(bdata, cmdline); fprintf(stderr, "creating boot image - %" PRId64 " bytes\n", bsize); *sz = bsize; if (!g_cmdline.empty()) bootimg_set_cmdline(bdata, g_cmdline); fprintf(stderr, "creating boot image - %" PRId64 " bytes\n", *sz); return bdata; } Loading Loading @@ -1422,34 +1420,37 @@ int main(int argc, char **argv) bool skip_secondary = false; bool set_fbe_marker = false; void *data; uint32_t header_version = 0; int64_t sz; int longindex; std::string slot_override; std::string next_active; g_boot_img_hdr.kernel_addr = 0x00008000; g_boot_img_hdr.ramdisk_addr = 0x01000000; g_boot_img_hdr.second_addr = 0x00f00000; g_boot_img_hdr.tags_addr = 0x00000100; g_boot_img_hdr.page_size = 2048; const struct option longopts[] = { {"base", required_argument, 0, 'b'}, {"kernel_offset", required_argument, 0, 'k'}, {"kernel-offset", required_argument, 0, 'k'}, {"page_size", required_argument, 0, 'n'}, {"page-size", required_argument, 0, 'n'}, {"ramdisk_offset", required_argument, 0, 'r'}, {"ramdisk-offset", required_argument, 0, 'r'}, {"tags_offset", required_argument, 0, 't'}, {"tags-offset", required_argument, 0, 't'}, {"base", required_argument, 0, 0}, {"cmdline", required_argument, 0, 0}, {"disable-verification", no_argument, 0, 0}, {"disable-verity", no_argument, 0, 0}, {"header-version", required_argument, 0, 0}, {"help", no_argument, 0, 'h'}, {"unbuffered", no_argument, 0, 0}, {"slot", required_argument, 0, 0}, {"set_active", optional_argument, 0, 'a'}, {"kernel-offset", required_argument, 0, 0}, {"os-patch-level", required_argument, 0, 0}, {"os-version", required_argument, 0, 0}, {"page-size", required_argument, 0, 0}, {"ramdisk-offset", required_argument, 0, 0}, {"set-active", optional_argument, 0, 'a'}, {"skip-secondary", no_argument, 0, 0}, {"skip-reboot", no_argument, 0, 0}, {"skip-secondary", no_argument, 0, 0}, {"slot", required_argument, 0, 0}, {"tags-offset", required_argument, 0, 0}, {"unbuffered", no_argument, 0, 0}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 0}, {"disable-verity", no_argument, 0, 0}, {"disable-verification", no_argument, 0, 0}, {"header-version", required_argument, 0, 0}, #if !defined(_WIN32) {"wipe-and-use-fbe", no_argument, 0, 0}, #endif Loading @@ -1458,51 +1459,89 @@ int main(int argc, char **argv) serial = getenv("ANDROID_SERIAL"); while (1) { int c = getopt_long(argc, argv, "vwb:k:n:r:t:s:S:lc:i:m:ha::", longopts, &longindex); if (c < 0) { break; int c; while ((c = getopt_long(argc, argv, "a::hi:ls:S:vw", longopts, &longindex)) != -1) { if (c == 0) { std::string name{longopts[longindex].name}; if (name == "base") { g_base_addr = strtoul(optarg, 0, 16); } else if (name == "cmdline") { g_cmdline = optarg; } else if (name == "disable-verification") { g_disable_verification = true; } else if (name == "disable-verity") { g_disable_verity = true; } else if (name == "header-version") { g_boot_img_hdr.header_version = strtoul(optarg, nullptr, 0); } else if (name == "kernel-offset") { g_boot_img_hdr.kernel_addr = strtoul(optarg, 0, 16); } else if (name == "os-patch-level") { unsigned year, month, day; if (sscanf(optarg, "%u-%u-%u", &year, &month, &day) != 3) { syntax_error("OS patch level should be YYYY-MM-DD: %s", optarg); } if (year < 2000 || year >= 2128) syntax_error("year out of range: %d", year); if (month < 1 || month > 12) syntax_error("month out of range: %d", month); g_boot_img_hdr.SetOsPatchLevel(year, month); } else if (name == "os-version") { unsigned major = 0, minor = 0, patch = 0; std::vector<std::string> versions = android::base::Split(optarg, "."); if (versions.size() < 1 || versions.size() > 3 || (versions.size() >= 1 && !android::base::ParseUint(versions[0], &major)) || (versions.size() >= 2 && !android::base::ParseUint(versions[1], &minor)) || (versions.size() == 3 && !android::base::ParseUint(versions[2], &patch)) || (major > 0x7f || minor > 0x7f || patch > 0x7f)) { syntax_error("bad OS version: %s", optarg); } g_boot_img_hdr.SetOsVersion(major, minor, patch); } else if (name == "page-size") { g_boot_img_hdr.page_size = strtoul(optarg, nullptr, 0); if (g_boot_img_hdr.page_size == 0) die("invalid page size"); } else if (name == "ramdisk-offset") { g_boot_img_hdr.ramdisk_addr = strtoul(optarg, 0, 16); } else if (name == "skip-reboot") { skip_reboot = true; } else if (name == "skip-secondary") { skip_secondary = true; } else if (name == "slot") { slot_override = optarg; } else if (name == "tags-offset") { g_boot_img_hdr.tags_addr = strtoul(optarg, 0, 16); } else if (name == "unbuffered") { setvbuf(stdout, nullptr, _IONBF, 0); setvbuf(stderr, nullptr, _IONBF, 0); } else if (name == "version") { fprintf(stdout, "fastboot version %s\n", FASTBOOT_VERSION); fprintf(stdout, "Installed as %s\n", android::base::GetExecutablePath().c_str()); return 0; #if !defined(_WIN32) } else if (name == "wipe-and-use-fbe") { wants_wipe = true; set_fbe_marker = true; #endif } else { die("unknown option %s", longopts[longindex].name); } /* Alphabetical cases */ } else { switch (c) { case 'a': wants_set_active = true; if (optarg) next_active = optarg; break; case 'b': base_addr = strtoul(optarg, 0, 16); break; case 'c': cmdline = optarg; if (optarg) next_active = optarg; break; case 'h': return show_help(); case 'i': { case 'i': { char *endptr = nullptr; unsigned long val; val = strtoul(optarg, &endptr, 0); if (!endptr || *endptr != '\0' || (val & ~0xffff)) unsigned long val = strtoul(optarg, &endptr, 0); if (!endptr || *endptr != '\0' || (val & ~0xffff)) { die("invalid vendor id '%s'", optarg); } vendor_id = (unsigned short)val; break; } case 'k': kernel_offset = strtoul(optarg, 0, 16); break; case 'l': long_listing = 1; break; case 'n': page_size = (unsigned)strtoul(optarg, nullptr, 0); if (!page_size) die("invalid page size"); break; case 'r': ramdisk_offset = strtoul(optarg, 0, 16); break; case 't': tags_offset = strtoul(optarg, 0, 16); g_long_listing = true; break; case 's': serial = optarg; Loading @@ -1519,39 +1558,11 @@ int main(int argc, char **argv) break; case '?': return 1; case 0: if (strcmp("unbuffered", longopts[longindex].name) == 0) { setvbuf(stdout, nullptr, _IONBF, 0); setvbuf(stderr, nullptr, _IONBF, 0); } else if (strcmp("version", longopts[longindex].name) == 0) { fprintf(stdout, "fastboot version %s\n", FASTBOOT_VERSION); fprintf(stdout, "Installed as %s\n", android::base::GetExecutablePath().c_str()); return 0; } else if (strcmp("slot", longopts[longindex].name) == 0) { slot_override = std::string(optarg); } else if (strcmp("skip-secondary", longopts[longindex].name) == 0 ) { skip_secondary = true; } else if (strcmp("skip-reboot", longopts[longindex].name) == 0 ) { skip_reboot = true; } else if (strcmp("disable-verity", longopts[longindex].name) == 0 ) { g_disable_verity = true; } else if (strcmp("disable-verification", longopts[longindex].name) == 0 ) { g_disable_verification = true; #if !defined(_WIN32) } else if (strcmp("wipe-and-use-fbe", longopts[longindex].name) == 0) { wants_wipe = true; set_fbe_marker = true; #endif } else if (strcmp("header-version", longopts[longindex].name) == 0) { header_version = strtoul(optarg, nullptr, 0); } else { die("unknown option %s", longopts[longindex].name); } break; default: abort(); } } } argc -= optind; argv += optind; Loading Loading @@ -1668,7 +1679,7 @@ int main(int argc, char **argv) std::string second_stage; if (!args.empty()) second_stage = next_arg(&args); data = load_bootable_image(kernel, ramdisk, second_stage, &sz, cmdline, header_version); data = load_bootable_image(kernel, ramdisk, second_stage, &sz); fb_queue_download("boot.img", data, sz); fb_queue_command("boot", "booting"); } else if (command == "flash") { Loading @@ -1694,7 +1705,7 @@ int main(int argc, char **argv) std::string second_stage; if (!args.empty()) second_stage = next_arg(&args); data = load_bootable_image(kernel, ramdisk, second_stage, &sz, cmdline, header_version); data = load_bootable_image(kernel, ramdisk, second_stage, &sz); auto flashraw = [&](const std::string& partition) { fb_queue_flash(partition, data, sz); }; Loading
mkbootimg/include/bootimg/bootimg.h +42 −58 Original line number Diff line number Diff line /* tools/mkbootimg/bootimg.h ** ** Copyright 2007, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. /* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdint.h> #pragma once #ifndef _BOOT_IMAGE_H_ #define _BOOT_IMAGE_H_ #include <stdint.h> #define BOOT_MAGIC "ANDROID!" #define BOOT_MAGIC_SIZE 8 Loading @@ -26,12 +24,10 @@ #define BOOT_ARGS_SIZE 512 #define BOOT_EXTRA_ARGS_SIZE 1024 #define BOOT_HEADER_VERSION_ZERO 0 /* * Bootloader expects the structure of boot_img_hdr with header version * BOOT_HEADER_VERSION_ZERO to be as follows: */ // The bootloader expects the structure of boot_img_hdr with header // version 0 to be as follows: struct boot_img_hdr_v0 { // Must be BOOT_MAGIC. uint8_t magic[BOOT_MAGIC_SIZE]; uint32_t kernel_size; /* size in bytes */ Loading @@ -45,26 +41,36 @@ struct boot_img_hdr_v0 { uint32_t tags_addr; /* physical addr for kernel tags */ uint32_t page_size; /* flash page size we assume */ /* * version for the boot image header. */ // Version of the boot image header. uint32_t header_version; /* operating system version and security patch level; for * version "A.B.C" and patch level "Y-M-D": * ver = A << 14 | B << 7 | C (7 bits for each of A, B, C) * lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M) * os_version = ver << 11 | lvl */ // Operating system version and security patch level. // For version "A.B.C" and patch level "Y-M-D": // (7 bits for each of A, B, C; 7 bits for (Y-2000), 4 bits for M) // os_version = A[31:25] B[24:18] C[17:11] (Y-2000)[10:4] M[3:0] uint32_t os_version; #if __cplusplus void SetOsVersion(unsigned major, unsigned minor, unsigned patch) { os_version &= ((1 << 11) - 1); os_version |= (((major & 0x7f) << 25) | ((minor & 0x7f) << 18) | ((patch & 0x7f) << 11)); } void SetOsPatchLevel(unsigned year, unsigned month) { os_version &= ~((1 << 11) - 1); os_version |= (((year - 2000) & 0x7f) << 4) | ((month & 0xf) << 0); } #endif uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */ uint8_t cmdline[BOOT_ARGS_SIZE]; uint32_t id[8]; /* timestamp / checksum / sha1 / etc */ /* Supplemental command line data; kept here to maintain * binary compatibility with older versions of mkbootimg */ // Supplemental command line data; kept here to maintain // binary compatibility with older versions of mkbootimg. uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE]; } __attribute__((packed)); Loading @@ -74,7 +80,7 @@ struct boot_img_hdr_v0 { */ typedef struct boot_img_hdr_v0 boot_img_hdr; /* When a boot header is of version BOOT_HEADER_VERSION_ZERO, the structure of boot image is as /* When a boot header is of version 0, the structure of boot image is as * follows: * * +-----------------+ Loading Loading @@ -103,15 +109,13 @@ typedef struct boot_img_hdr_v0 boot_img_hdr; * else: jump to kernel_addr */ #define BOOT_HEADER_VERSION_ONE 1 struct boot_img_hdr_v1 : public boot_img_hdr_v0 { uint32_t recovery_dtbo_size; /* size in bytes for recovery DTBO image */ uint64_t recovery_dtbo_offset; /* physical load addr */ uint32_t header_size; } __attribute__((packed)); /* When the boot image header has a version of BOOT_HEADER_VERSION_ONE, the structure of the boot /* When the boot image header has a version of 1, the structure of the boot * image is as follows: * * +-----------------+ Loading Loading @@ -142,23 +146,3 @@ struct boot_img_hdr_v1 : public boot_img_hdr_v0 { * 7. if second_size != 0: jump to second_addr * else: jump to kernel_addr */ #if 0 typedef struct ptentry ptentry; struct ptentry { char name[16]; /* asciiz partition name */ unsigned start; /* starting block number */ unsigned length; /* length in blocks */ unsigned flags; /* set to zero */ }; /* MSM Partition Table ATAG ** ** length: 2 + 7 * n ** atag: 0x4d534d70 ** <ptentry> x n */ #endif #endif