diff --git a/bootloader/build.mk b/bootloader/build.mk index a9e63ebc1..5c464eeb2 100644 --- a/bootloader/build.mk +++ b/bootloader/build.mk @@ -46,7 +46,6 @@ EFI_SOURCES := \ $(LOCAL_DIR)/src/osboot.c \ $(LOCAL_DIR)/src/cmdline.c \ $(LOCAL_DIR)/src/magenta.c \ - $(LOCAL_DIR)/src/legacy.c \ $(LOCAL_DIR)/src/misc.c \ $(LOCAL_DIR)/src/netboot.c \ $(LOCAL_DIR)/src/netifc.c \ diff --git a/bootloader/src/legacy.c b/bootloader/src/legacy.c deleted file mode 100644 index 4b07b4cae..000000000 --- a/bootloader/src/legacy.c +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright 2017 The Fuchsia Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include -#include -#include - -#include "osboot.h" - -#include - -typedef struct { - uint8_t* zeropage; - uint8_t* cmdline; - void* image; - uint32_t pages; -} kernel_t; - -#define E820_IGNORE 0 -#define E820_RAM 1 -#define E820_RESERVED 2 -#define E820_ACPI 3 -#define E820_NVS 4 -#define E820_UNUSABLE 5 - -static inline const char* e820name(int e820) { - switch (e820) { - case E820_IGNORE: return "IGNORE"; - case E820_RAM: return "RAM"; - case E820_RESERVED: return "RESERVED"; - case E820_ACPI: return "ACPI"; - case E820_NVS: return "NVS"; - case E820_UNUSABLE: return "UNUSABLE"; - } - return ""; -} - -struct e820entry { - uint64_t addr; - uint64_t size; - uint32_t type; -} __attribute__((packed)); - -static unsigned e820type(unsigned uefi_mem_type) { - switch (uefi_mem_type) { - case EfiReservedMemoryType: - case EfiPalCode: - return E820_RESERVED; - case EfiRuntimeServicesCode: - case EfiRuntimeServicesData: -#if WITH_RUNTIME_SERVICES - return E820_RESERVED; -#else - return E820_RAM; -#endif - case EfiACPIReclaimMemory: - return E820_ACPI; - case EfiACPIMemoryNVS: - return E820_NVS; - case EfiLoaderCode: - case EfiLoaderData: - case EfiBootServicesCode: - case EfiBootServicesData: - case EfiConventionalMemory: - return E820_RAM; - case EfiMemoryMappedIO: - case EfiMemoryMappedIOPortSpace: - return E820_IGNORE; - default: - if (uefi_mem_type >= 0x80000000) { - return E820_RAM; - } - return E820_UNUSABLE; - } -} - -static unsigned char scratch[32768]; -static struct e820entry e820table[128]; - -static int process_memory_map(efi_system_table* sys, size_t* _key, int silent) { - efi_memory_descriptor* mmap; - struct e820entry* entry = e820table; - size_t msize, off; - size_t mkey, dsize; - uint32_t dversion; - unsigned n, type; - efi_status r; - - msize = sizeof(scratch); - mmap = (efi_memory_descriptor*)scratch; - mkey = dsize = dversion = 0; - r = sys->BootServices->GetMemoryMap(&msize, mmap, &mkey, &dsize, &dversion); - if (!silent) - printf("r=%zx msz=%zx key=%zx dsz=%zx dvn=%x\n", r, msize, mkey, dsize, dversion); - if (r != EFI_SUCCESS) { - return -1; - } - if (msize > sizeof(scratch)) { - if (!silent) - printf("Memory Table Too Large (%zu entries)\n", (msize / dsize)); - return -1; - } - for (off = 0, n = 0; off < msize; off += dsize) { - mmap = (efi_memory_descriptor*)(scratch + off); - type = e820type(mmap->Type); - if (type == E820_IGNORE) { - continue; - } - if ((n > 0) && (entry[n - 1].type == type)) { - if ((entry[n - 1].addr + entry[n - 1].size) == mmap->PhysicalStart) { - entry[n - 1].size += mmap->NumberOfPages * PAGE_SIZE; - continue; - } - } - entry[n].addr = mmap->PhysicalStart; - entry[n].size = mmap->NumberOfPages * PAGE_SIZE; - entry[n].type = type; - n++; - if (n == 128) { - if (!silent) - printf("E820 Table Too Large (%zu raw entries)\n", (msize / dsize)); - return -1; - } - } - *_key = mkey; - return n; -} - -#define ZP_E820_COUNT 0x1E8 // byte -#define ZP_SETUP 0x1F1 // start of setup structure -#define ZP_SETUP_SECTS 0x1F1 // byte (setup_size/512-1) -#define ZP_JUMP 0x200 // jump instruction -#define ZP_HEADER 0x202 // word "HdrS" -#define ZP_VERSION 0x206 // half 0xHHLL -#define ZP_LOADER_TYPE 0x210 // byte -#define ZP_RAMDISK_BASE 0x218 // word (ptr or 0) -#define ZP_RAMDISK_SIZE 0x21C // word (bytes) -#define ZP_EXTRA_MAGIC 0x220 // word -#define ZP_CMDLINE 0x228 // word (ptr) -#define ZP_SYSSIZE 0x1F4 // word (size/16) -#define ZP_XLOADFLAGS 0x236 // half -#define ZP_E820_TABLE 0x2D0 // 128 entries - -#define ZP_ACPI_RSD 0x080 // word phys ptr -#define ZP_FB_BASE 0x090 -#define ZP_FB_WIDTH 0x094 -#define ZP_FB_HEIGHT 0x098 -#define ZP_FB_STRIDE 0x09C -#define ZP_FB_FORMAT 0x0A0 -#define ZP_FB_REGBASE 0x0A4 -#define ZP_FB_SIZE 0x0A8 - -#define ZP_MAGIC_VALUE 0xDBC64323 - -#define ZP8(p, off) (*((uint8_t*)((p) + (off)))) -#define ZP16(p, off) (*((uint16_t*)((p) + (off)))) -#define ZP32(p, off) (*((uint32_t*)((p) + (off)))) - -static void install_memmap(kernel_t* k, struct e820entry* memmap, unsigned count) { - memcpy(k->zeropage + ZP_E820_TABLE, memmap, sizeof(*memmap) * count); - ZP8(k->zeropage, ZP_E820_COUNT) = count; -} - -static void start_deprecated(kernel_t* k) { - // 64bit entry is at offset 0x200 - uint64_t entry = (uint64_t)(k->image + 0x200); - - // ebx = 0, ebp = 0, edi = 0, esi = zeropage - __asm__ __volatile__( - "movl $0, %%ebp \n" - "cli \n" - "jmp *%[entry] \n" ::[entry] "a"(entry), - [zeropage] "S"(k->zeropage), - "b"(0), "D"(0)); - for (;;) - ; -} - -static int load_deprecated(efi_boot_services* bs, uint8_t* image, size_t sz, kernel_t* k) { - uint32_t setup_sz; - uint32_t image_sz; - uint32_t setup_end; - efi_physical_addr mem; - - k->zeropage = NULL; - k->cmdline = NULL; - k->image = NULL; - k->pages = 0; - - if (sz < 1024) { - // way too small to be a kernel - goto fail; - } - - if (ZP32(image, ZP_HEADER) != 0x53726448) { - printf("kernel: invalid setup magic %08x\n", ZP32(image, ZP_HEADER)); - goto fail; - } - if (ZP16(image, ZP_VERSION) < 0x020B) { - printf("kernel: unsupported setup version %04x\n", ZP16(image, ZP_VERSION)); - goto fail; - } - setup_sz = (ZP8(image, ZP_SETUP_SECTS) + 1) * 512; - image_sz = (ZP32(image, ZP_SYSSIZE) * 16); - setup_end = ZP_JUMP + ZP8(image, ZP_JUMP + 1); - - printf("setup %d image %d hdr %04x-%04x\n", setup_sz, image_sz, ZP_SETUP, setup_end); - // image size may be rounded up, thus +15 - if ((setup_sz < 1024) || ((setup_sz + image_sz) > (sz + 15))) { - printf("kernel: invalid image size\n"); - goto fail; - } - - mem = 0xFF000; - if (bs->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1, &mem)) { - printf("kernel: cannot allocate 'zero page'\n"); - goto fail; - } - k->zeropage = (void*)mem; - - mem = 0xFF000; - if (bs->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1, &mem)) { - printf("kernel: cannot allocate commandline\n"); - goto fail; - } - k->cmdline = (void*)mem; - - mem = 0x100000; - k->pages = BYTES_TO_PAGES(image_sz); - if (bs->AllocatePages(AllocateAddress, EfiLoaderData, k->pages + 1, &mem)) { - printf("kernel: cannot allocate kernel\n"); - goto fail; - } - k->image = (void*)mem; - - // setup zero page, copy setup header from kernel binary - memset(k->zeropage, 0, PAGE_SIZE); - memcpy(k->zeropage + ZP_SETUP, image + ZP_SETUP, setup_end - ZP_SETUP); - - memcpy(k->image, image + setup_sz, image_sz); - - // empty commandline for now - ZP32(k->zeropage, ZP_CMDLINE) = (uint64_t)k->cmdline; - k->cmdline[0] = 0; - - // default to no ramdisk - ZP32(k->zeropage, ZP_RAMDISK_BASE) = 0; - ZP32(k->zeropage, ZP_RAMDISK_SIZE) = 0; - - // undefined bootloader - ZP8(k->zeropage, ZP_LOADER_TYPE) = 0xFF; - - printf("kernel @%p, zeropage @%p, cmdline @%p\n", - k->image, k->zeropage, k->cmdline); - - return 0; -fail: - if (k->image) { - bs->FreePages((efi_physical_addr)k->image, k->pages); - } - if (k->cmdline) { - bs->FreePages((efi_physical_addr)k->cmdline, 1); - } - if (k->zeropage) { - bs->FreePages((efi_physical_addr)k->zeropage, 1); - } - - return -1; -} - -int boot_deprecated(efi_handle img, efi_system_table* sys, - void* image, size_t sz, - void* ramdisk, size_t rsz, - void* cmdline, size_t csz) { - efi_boot_services* bs = sys->BootServices; - kernel_t kernel; - efi_status r; - size_t key; - int n, i; - - efi_graphics_output_protocol* gop; - bs->LocateProtocol(&GraphicsOutputProtocol, NULL, (void**)&gop); - - printf("boot_kernel() from %p (%zu bytes)\n", image, sz); - if (ramdisk && rsz) { - printf("ramdisk at %p (%zu bytes)\n", ramdisk, rsz); - } - - if (load_deprecated(sys->BootServices, image, sz, &kernel)) { - printf("Failed to load kernel image\n"); - return -1; - } - - ZP32(kernel.zeropage, ZP_EXTRA_MAGIC) = ZP_MAGIC_VALUE; - ZP32(kernel.zeropage, ZP_ACPI_RSD) = find_acpi_root(img, sys); - - ZP32(kernel.zeropage, ZP_FB_BASE) = (uint32_t)gop->Mode->FrameBufferBase; - ZP32(kernel.zeropage, ZP_FB_WIDTH) = (uint32_t)gop->Mode->Info->HorizontalResolution; - ZP32(kernel.zeropage, ZP_FB_HEIGHT) = (uint32_t)gop->Mode->Info->VerticalResolution; - ZP32(kernel.zeropage, ZP_FB_STRIDE) = (uint32_t)gop->Mode->Info->PixelsPerScanLine; - ZP32(kernel.zeropage, ZP_FB_FORMAT) = get_mx_pixel_format(gop); - ZP32(kernel.zeropage, ZP_FB_REGBASE) = 0; - ZP32(kernel.zeropage, ZP_FB_SIZE) = 256 * 1024 * 1024; - - if (cmdline) { - memcpy(kernel.cmdline, cmdline, csz); - } - - if (ramdisk && rsz) { - ZP32(kernel.zeropage, ZP_RAMDISK_BASE) = (uint32_t) (uintptr_t) ramdisk; - ZP32(kernel.zeropage, ZP_RAMDISK_SIZE) = rsz; - } - n = process_memory_map(sys, &key, 0); - - for (i = 0; i < n; i++) { - struct e820entry* e = e820table + i; - printf("%016" PRIx64 " %016" PRIx64 " %s\n", - e->addr, e->size, e820name(e->type)); - } - - r = sys->BootServices->ExitBootServices(img, key); - if (r == EFI_INVALID_PARAMETER) { - n = process_memory_map(sys, &key, 1); - r = sys->BootServices->ExitBootServices(img, key); - if (r) { - printf("Cannot ExitBootServices! (2) %s\n", xefi_strerror(r)); - return -1; - } - } else if (r) { - printf("Cannot ExitBootServices! (1) %s\n", xefi_strerror(r)); - return -1; - } - - install_memmap(&kernel, e820table, n); - start_deprecated(&kernel); - - return 0; -} diff --git a/bootloader/src/magenta.c b/bootloader/src/magenta.c index b6a1dcd27..b45b4f85c 100644 --- a/bootloader/src/magenta.c +++ b/bootloader/src/magenta.c @@ -49,41 +49,94 @@ static void start_magenta(uint64_t entry, void* bootdata) { ; } +static bool with_extra = false; +static bootextra_t default_extra = { + .reserved0 = 0, + .reserved1 = 0, + .magic = BOOTITEM_MAGIC, + .crc32 = BOOTITEM_NO_CRC32, +}; + static int add_bootdata(void** ptr, size_t* avail, bootdata_t* bd, void* data) { - size_t len = BOOTDATA_ALIGN(bd->length); - if ((sizeof(bootdata_t) + len) > *avail) { - printf("boot: no room for bootdata type=%08x size=%08x\n", - bd->type, bd->length); - return -1; + if (with_extra) { + size_t len = BOOTDATA_ALIGN(bd->length); + if ((sizeof(bootdata_t) + sizeof(bootextra_t) + len) > *avail) { + printf("boot: no room for bootdata type=%08x size=%08x\n", + bd->type, bd->length); + return -1; + } + bd->flags |= BOOTDATA_FLAG_EXTRA; + memcpy(*ptr, bd, sizeof(bootdata_t)); + memcpy((*ptr) + sizeof(bootdata_t), &default_extra, sizeof(bootextra_t)); + memcpy((*ptr) + sizeof(bootdata_t) + sizeof(bootextra_t), data, len); + len += sizeof(bootdata_t) + sizeof(bootextra_t); + (*ptr) += len; + (*avail) -= len; + } else { + size_t len = BOOTDATA_ALIGN(bd->length); + if ((sizeof(bootdata_t) + len) > *avail) { + printf("boot: no room for bootdata type=%08x size=%08x\n", + bd->type, bd->length); + return -1; + } + memcpy(*ptr, bd, sizeof(bootdata_t)); + memcpy((*ptr) + sizeof(bootdata_t), data, len); + len += sizeof(bootdata_t); + (*ptr) += len; + (*avail) -= len; } - memcpy(*ptr, bd, sizeof(bootdata_t)); - memcpy((*ptr) + sizeof(bootdata_t), data, len); - len += sizeof(bootdata_t); - (*ptr) += len; - (*avail) -= len; return 0; } -static int header_check(void* image, size_t sz) { - magenta_kernel_t* kernel = image; - if ((sz < sizeof(magenta_kernel_t)) || - (kernel->hdr_kernel.type != BOOTDATA_KERNEL)) { - printf("boot: invalid magenta kernel header\n"); - return -1; +static int header_check(void* image, size_t sz, uint64_t* _entry, + size_t* _hsz, size_t* _flen, size_t* _klen) { + bootdata_t* bd = image; + size_t hsz, flen, klen; + uint64_t entry; + + if (bd->flags & BOOTDATA_FLAG_EXTRA) { + hsz = sizeof(bootdata_t) + sizeof(bootextra_t); + magenta_kernel2_t* kernel2 = image; + if ((sz < sizeof(magenta_kernel2_t)) || + (kernel2->hdr_kernel.type != BOOTDATA_KERNEL) || + ((kernel2->hdr_kernel.flags & BOOTDATA_FLAG_EXTRA) == 0)) { + printf("boot: invalid magenta kernel header\n"); + return -1; + } + flen = BOOTDATA_ALIGN(kernel2->hdr_file.length); + klen = BOOTDATA_ALIGN(kernel2->hdr_kernel.length); + entry = kernel2->data_kernel.entry64; + } else { + hsz = sizeof(bootdata_t); + magenta_kernel_t* kernel = image; + if ((sz < sizeof(magenta_kernel_t)) || + (kernel->hdr_kernel.type != BOOTDATA_KERNEL)) { + printf("boot: invalid magenta kernel header\n"); + return -1; + } + flen = BOOTDATA_ALIGN(kernel->hdr_file.length); + klen = BOOTDATA_ALIGN(kernel->hdr_kernel.length); + entry = kernel->data_kernel.entry64; } - uint32_t flen = BOOTDATA_ALIGN(kernel->hdr_file.length); - if (flen > (sz - sizeof(bootdata_t))) { + if (flen > (sz - hsz)) { printf("boot: invalid magenta kernel header (bad flen)\n"); return -1; } - uint32_t klen = BOOTDATA_ALIGN(kernel->hdr_kernel.length); - if (klen > (sz - (sizeof(bootdata_t) * 2))) { + if (klen > (sz - (hsz * 2))) { printf("boot: invalid magenta kernel header (bad klen)\n"); return -1; } + if (_entry) { + *_entry = entry; + } + if (_hsz) { + *_hsz = hsz; + *_flen = flen; + *_klen = klen; + } return 0; } @@ -93,45 +146,54 @@ int boot_magenta(efi_handle img, efi_system_table* sys, void* cmdline, size_t csz) { efi_boot_services* bs = sys->BootServices; + uint64_t entry; - if (header_check(image, isz)) { + if (header_check(image, isz, &entry, NULL, NULL, NULL)) { return -1; } - if ((ramdisk == NULL) || (rsz < sizeof(bootdata_t))) { + if ((ramdisk == NULL) || (rsz < (sizeof(bootdata_t) + sizeof(bootextra_t)))) { printf("boot: ramdisk missing or too small\n"); return -1; } - magenta_kernel_t* kernel = image; bootdata_t* hdr0 = ramdisk; if ((hdr0->type != BOOTDATA_CONTAINER) || - (hdr0->extra != BOOTDATA_MAGIC) || - (hdr0->flags != 0)) { + (hdr0->extra != BOOTDATA_MAGIC)) { printf("boot: ramdisk has invalid bootdata header\n"); return -1; } - if ((hdr0->length > (rsz - sizeof(bootdata_t)))) { + + // If the ramdisk container header is a new/large header, + // generate all our prepended headers in the same style... + size_t hsz = sizeof(bootdata_t); + if (hdr0->flags & BOOTDATA_FLAG_EXTRA) { + with_extra = true; + hsz += sizeof(bootextra_t); + } + + if ((hdr0->length > (rsz - hsz))) { printf("boot: ramdisk has invalid bootdata length\n"); return -1; } // osboot ensures we have FRONT_BYTES ahead of the // ramdisk to prepend our own bootdata items. - // - // We used sizeof(hdr) up front but will overwrite - // the header at the start of the ramdisk so it works - // out in the end. - bootdata_t hdr; void* bptr = ramdisk - FRONT_BYTES; size_t blen = FRONT_BYTES; + // We create a new container header of the same size + // as the one at the start of the ramdisk hdr.type = BOOTDATA_CONTAINER; hdr.length = hdr0->length + FRONT_BYTES; hdr.extra = BOOTDATA_MAGIC; - hdr.flags = 0; + hdr.flags = with_extra ? BOOTDATA_FLAG_EXTRA : 0; memcpy(bptr, &hdr, sizeof(hdr)); bptr += sizeof(hdr); + if (with_extra) { + memcpy(bptr, &default_extra, sizeof(default_extra)); + bptr += sizeof(default_extra); + } // pass kernel commandline hdr.type = BOOTDATA_CMDLINE; @@ -235,15 +297,18 @@ int boot_magenta(efi_handle img, efi_system_table* sys, } // fill the remaining gap between pre-data and ramdisk image - if ((blen < sizeof(bootdata_t)) || (blen & 7)) { + if ((blen < hsz) || (blen & 7)) { goto fail; } hdr.type = BOOTDATA_IGNORE; - hdr.length = blen - sizeof(bootdata_t); + hdr.length = blen - hsz; memcpy(bptr, &hdr, sizeof(hdr)); + if (with_extra) { + memcpy(bptr + sizeof(hdr), &default_extra, sizeof(default_extra)); + } // jump to the kernel - start_magenta(kernel->data_kernel.entry64, ramdisk - FRONT_BYTES); + start_magenta(entry, ramdisk - FRONT_BYTES); fail: bs->FreePages(mem, pages); @@ -255,17 +320,14 @@ static char cmdline[CMDLINE_MAX]; int mxboot(efi_handle img, efi_system_table* sys, void* image, size_t sz) { - if (header_check(image, sz)) { + size_t hsz, flen, klen; + if (header_check(image, sz, NULL, &hsz, &flen, &klen)) { return -1; } - magenta_kernel_t* kernel = image; - uint32_t flen = BOOTDATA_ALIGN(kernel->hdr_file.length); - uint32_t klen = BOOTDATA_ALIGN(kernel->hdr_kernel.length); - // ramdisk portion is file - headers - kernel len - uint32_t rlen = flen - sizeof(bootdata_t) - klen; - uint32_t roff = (sizeof(bootdata_t) * 2) + klen; + uint32_t rlen = flen - hsz - klen; + uint32_t roff = (hsz * 2) + klen; if (rlen == 0) { printf("mxboot: no ramdisk?!\n"); return -1; @@ -273,7 +335,7 @@ int mxboot(efi_handle img, efi_system_table* sys, // allocate space for the ramdisk efi_boot_services* bs = sys->BootServices; - size_t rsz = rlen + sizeof(bootdata_t) + FRONT_BYTES; + size_t rsz = rlen + hsz + FRONT_BYTES; size_t pages = BYTES_TO_PAGES(rsz); void* ramdisk = NULL; efi_status r = bs->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, @@ -289,15 +351,25 @@ int mxboot(efi_handle img, efi_system_table* sys, hdr->length = rlen; hdr->extra = BOOTDATA_MAGIC; hdr->flags = 0; - memcpy(ramdisk + sizeof(bootdata_t), image + roff, rlen); - rlen += sizeof(bootdata_t); + if (hsz != sizeof(bootdata_t)) { + hdr->flags |= BOOTDATA_FLAG_EXTRA; + memcpy(hdr + 1, &default_extra, sizeof(default_extra)); + } + memcpy(ramdisk + hsz, image + roff, rlen); + rlen += hsz; printf("ramdisk @ %p\n", ramdisk); size_t csz = cmdline_to_string(cmdline, sizeof(cmdline)); // shrink original image header to include only the kernel - kernel->hdr_file.length = sizeof(bootdata_t) + klen; + if (hsz == sizeof(bootdata_t)) { + magenta_kernel_t* kernel = image; + kernel->hdr_file.length = hsz + klen; + } else { + magenta_kernel2_t* kernel2 = image; + kernel2->hdr_file.length = hsz + klen; + } return boot_magenta(img, sys, image, roff, ramdisk, rlen, cmdline, csz); } @@ -310,10 +382,9 @@ int boot_kernel(efi_handle img, efi_system_table* sys, bootdata_t* bd = image; if ((bd->type == BOOTDATA_CONTAINER) && - (bd->extra == BOOTDATA_MAGIC) && - (bd->flags == 0)) { + (bd->extra == BOOTDATA_MAGIC)) { return boot_magenta(img, sys, image, sz, ramdisk, rsz, cmdline, csz); } else { - return boot_deprecated(img, sys, image, sz, ramdisk, rsz, cmdline, csz); + return -1; } } diff --git a/kernel/arch/x86/header.S b/kernel/arch/x86/header.S index 90fbc5541..794114b29 100644 --- a/kernel/arch/x86/header.S +++ b/kernel/arch/x86/header.S @@ -23,6 +23,27 @@ LOCAL_DATA(_setup_start) +#if ENABLE_NEW_BOOTDATA + /* bootdata file header */ + .int BOOTDATA_CONTAINER + .int PHYS(__data_end) - PHYS_LOAD_ADDRESS - 32 + .int BOOTDATA_MAGIC + .int BOOTDATA_FLAG_EXTRA + .int 0 + .int 0 + .int BOOTITEM_MAGIC + .int BOOTITEM_NO_CRC32 + + /* bootdata kernel header */ + .int BOOTDATA_KERNEL + .int PHYS(__data_end) - PHYS_LOAD_ADDRESS - 64 + .int 0 + .int BOOTDATA_FLAG_EXTRA + .int 0 + .int 0 + .int BOOTITEM_MAGIC + .int BOOTITEM_NO_CRC32 +#else /* bootdata file header */ .int BOOTDATA_CONTAINER .int PHYS(__data_end) - PHYS_LOAD_ADDRESS - 16 @@ -34,7 +55,7 @@ LOCAL_DATA(_setup_start) .int PHYS(__data_end) - PHYS_LOAD_ADDRESS - 32 .int 0 .int 0 - +#endif .quad PHYS(_entry64) .quad 0 diff --git a/kernel/platform/generic-arm/platform.cpp b/kernel/platform/generic-arm/platform.cpp index b1724fdcb..c11949955 100644 --- a/kernel/platform/generic-arm/platform.cpp +++ b/kernel/platform/generic-arm/platform.cpp @@ -532,6 +532,10 @@ static void process_bootdata(bootdata_t* root) { size_t offset = sizeof(bootdata_t); const size_t length = (root->length); + if (root->flags & BOOTDATA_FLAG_EXTRA) { + offset += sizeof(bootextra_t); + } + while (offset < length) { uintptr_t ptr = reinterpret_cast(root); bootdata_t* section = reinterpret_cast(ptr + offset); diff --git a/kernel/platform/pc/platform.cpp b/kernel/platform/pc/platform.cpp index 5b9e1e8d8..b0e0b9b2a 100644 --- a/kernel/platform/pc/platform.cpp +++ b/kernel/platform/pc/platform.cpp @@ -137,18 +137,23 @@ extern "C" void boot_alloc_reserve(uintptr_t phys, size_t _len); static void process_bootdata(bootdata_t* hdr, uintptr_t phys, bool verify) { if ((hdr->type != BOOTDATA_CONTAINER) || - (hdr->extra != BOOTDATA_MAGIC) || - (hdr->flags != 0)) { + (hdr->extra != BOOTDATA_MAGIC)) { printf("bootdata: invalid %08x %08x %08x %08x\n", hdr->type, hdr->length, hdr->extra, hdr->flags); return; } - size_t total_len = hdr->length + sizeof(*hdr); + size_t hsz = sizeof(bootdata_t); + if (hdr->flags & BOOTDATA_FLAG_EXTRA) { + hsz += sizeof(bootextra_t); + } + + size_t total_len = hdr->length + hsz; printf("bootdata: @ %p (%zu bytes)\n", hdr, total_len); - bootdata_t* bd = hdr + 1; + bootdata_t* bd = reinterpret_cast(reinterpret_cast(hdr) + hsz); + size_t remain = hdr->length; while (remain > sizeof(bootdata_t)) { remain -= sizeof(bootdata_t); diff --git a/make/engine.mk b/make/engine.mk index 38beabad4..51e668b7e 100644 --- a/make/engine.mk +++ b/make/engine.mk @@ -170,6 +170,10 @@ KERNEL_CPPFLAGS := KERNEL_ASMFLAGS := KERNEL_LDFLAGS := +ifeq ($(call TOBOOL,$(ENABLE_NEW_BOOTDATA)),true) +KERNEL_COMPILEFLAGS += -DENABLE_NEW_BOOTDATA=1 +endif + # Build flags for modules that want frame pointers. # crashlogger, ngunwind, backtrace use this so that the simplisitic unwinder # will work with them. These are recorded here so that modules don't need diff --git a/system/core/devmgr/devmgr-mxio.c b/system/core/devmgr/devmgr-mxio.c index 5ba6648af..6f4419910 100644 --- a/system/core/devmgr/devmgr-mxio.c +++ b/system/core/devmgr/devmgr-mxio.c @@ -257,6 +257,9 @@ static void setup_bootfs(void) { size_t len = bootdata.length; size_t off = sizeof(bootdata); + if (bootdata.flags & BOOTDATA_FLAG_EXTRA) { + off += sizeof(bootextra_t); + } while (len > sizeof(bootdata)) { mx_status_t status = mx_vmo_read(vmo, &bootdata, off, sizeof(bootdata), &actual); diff --git a/system/host/mkbootfs/mkbootfs.c b/system/host/mkbootfs/mkbootfs.c index 5b5e526f9..d81661a82 100644 --- a/system/host/mkbootfs/mkbootfs.c +++ b/system/host/mkbootfs/mkbootfs.c @@ -245,7 +245,7 @@ okay: return 0; } -int import_file_as(const char* fn, uint32_t type, uint32_t hdrlen) { +int import_file_as(const char* fn, uint32_t type, uint32_t hdrlen, bootdata_t* hdr) { // bootdata file struct stat s; if (stat(fn, &s) != 0) { @@ -254,7 +254,11 @@ int import_file_as(const char* fn, uint32_t type, uint32_t hdrlen) { } if (type == ITEM_BOOTDATA) { - if (s.st_size < sizeof(bootdata_t)) { + size_t hsz = sizeof(bootdata_t); + if (hdr->flags & BOOTDATA_FLAG_EXTRA) { + hsz += sizeof(bootextra_t); + } + if (s.st_size < hsz) { fprintf(stderr, "error: bootdata file too small '%s'\n", fn); return -1; } @@ -262,13 +266,10 @@ int import_file_as(const char* fn, uint32_t type, uint32_t hdrlen) { fprintf(stderr, "error: bootdata file misaligned '%s'\n", fn); return -1; } - if (s.st_size != (hdrlen + sizeof(bootdata_t))) { + if (s.st_size != (hdrlen + hsz)) { fprintf(stderr, "error: bootdata header size mismatch '%s'\n", fn); return -1; } - - // The header itself is not copied - s.st_size -= sizeof(bootdata_t); } fsentry_t* e; @@ -289,8 +290,7 @@ int import_file(const char* fn, bool system) { bootdata_t hdr; if ((fread(&hdr, sizeof(hdr), 1, fp) != 1) || (hdr.type != BOOTDATA_CONTAINER) || - (hdr.extra != BOOTDATA_MAGIC) || - (hdr.flags != 0)) { + (hdr.extra != BOOTDATA_MAGIC)) { // not a bootdata file, must be a manifest... rewind(fp); @@ -298,7 +298,7 @@ int import_file(const char* fn, bool system) { return import_manifest(fp, fn, item); } else { fclose(fp); - return import_file_as(fn, ITEM_BOOTDATA, hdr.length); + return import_file_as(fn, ITEM_BOOTDATA, hdr.length, &hdr); } } @@ -583,11 +583,19 @@ ssize_t copybootdatafile(int fd, const char* fn, size_t len) { goto fail; } if ((hdr.type != BOOTDATA_CONTAINER) || - (hdr.extra != BOOTDATA_MAGIC) || - (hdr.flags != 0)) { + (hdr.extra != BOOTDATA_MAGIC)) { fprintf(stderr, "error: '%s' is not a bootdata file\n", fn); goto fail; } + len -= sizeof(hdr); + if (hdr.flags & BOOTDATA_FLAG_EXTRA) { + bootextra_t extra; + if ((r = readx(fdi, &extra, sizeof(extra))) < 0) { + fprintf(stderr, "error: '%s' cannot read extra header\n", fn); + goto fail; + } + len -= sizeof(extra); + } if ((hdr.length != len)) { fprintf(stderr, "error: '%s' header length (%u) != %zd\n", fn, hdr.length, len); goto fail; @@ -836,8 +844,13 @@ int write_bootdata(const char* fn, item_t* item, bool extra) { return -1; } + size_t hdrsize = sizeof(bootdata_t); + if (extra) { + hdrsize += sizeof(bootextra_t); + } + // Leave room for file header - if (lseek(fd, sizeof(bootdata_t), SEEK_SET) != sizeof(bootdata_t)) { + if (lseek(fd, hdrsize, SEEK_SET) != hdrsize) { fprintf(stderr, "error: cannot seek\n"); goto fail; } @@ -879,14 +892,24 @@ int write_bootdata(const char* fn, item_t* item, bool extra) { bootdata_t filehdr = { .type = BOOTDATA_CONTAINER, - .length = file_end - sizeof(bootdata_t), + .length = file_end - hdrsize, .extra = BOOTDATA_MAGIC, - .flags = 0, + .flags = extra ? BOOTDATA_FLAG_EXTRA : 0, }; if (writex(fd, &filehdr, sizeof(filehdr)) < 0) { goto fail; } - + if (extra) { + bootextra_t fileextra = { + .reserved0 = 0, + .reserved1 = 1, + .magic = BOOTITEM_MAGIC, + .crc32 = BOOTITEM_NO_CRC32, + }; + if (writex(fd, &fileextra, sizeof(fileextra)) < 0) { + goto fail; + } + } close(fd); return 0; @@ -911,14 +934,25 @@ int dump_bootdata(const char* fn) { if ((hdr.type != BOOTDATA_CONTAINER) || (hdr.extra != BOOTDATA_MAGIC) || - (hdr.flags != 0) || (hdr.length < sizeof(hdr))) { fprintf(stderr, "error: invalid bootdata header\n"); goto fail; } - size_t off = sizeof(hdr); + if (hdr.flags & BOOTDATA_FLAG_EXTRA) { + bootextra_t extra; + if (readx(fd, &extra, sizeof(extra)) < 0) { + fprintf(stderr, "error: cannot read extra header\n"); + goto fail; + } + if (extra.magic != BOOTITEM_MAGIC) { + fprintf(stderr, "error: invalid extra header\n"); + goto fail; + } + off += sizeof(bootextra_t); + } size_t end = off + hdr.length; + while (off < end) { if (readx(fd, &hdr, sizeof(hdr)) < 0) { fprintf(stderr, "error: cannot read section header\n"); @@ -1077,7 +1111,7 @@ int main(int argc, char **argv) { return -1; } have_kernel = 1; - if (import_file_as(argv[1], ITEM_KERNEL, 0) < 0) { + if (import_file_as(argv[1], ITEM_KERNEL, 0, NULL) < 0) { return -1; } argc--; @@ -1093,7 +1127,7 @@ int main(int argc, char **argv) { } have_cmdline = true; - if (import_file_as(argv[1], ITEM_CMDLINE, 0) < 0) { + if (import_file_as(argv[1], ITEM_CMDLINE, 0, NULL) < 0) { return -1; } argc--; diff --git a/system/public/magenta/boot/bootdata.h b/system/public/magenta/boot/bootdata.h index 1a1cd5acf..57ab5d4d5 100644 --- a/system/public/magenta/boot/bootdata.h +++ b/system/public/magenta/boot/bootdata.h @@ -160,6 +160,14 @@ typedef struct { bootdata_kernel_t data_kernel; } magenta_kernel_t; +typedef struct { + bootdata_t hdr_file; + bootextra_t ext_file; + bootdata_t hdr_kernel; + bootextra_t ext_kernel; + bootdata_kernel_t data_kernel; +} magenta_kernel2_t; + typedef struct { uint64_t base; uint64_t length; diff --git a/system/public/magenta/boot/netboot.h b/system/public/magenta/boot/netboot.h index 6b0f7d67b..7abe3b561 100644 --- a/system/public/magenta/boot/netboot.h +++ b/system/public/magenta/boot/netboot.h @@ -9,7 +9,7 @@ // clang-format off -#define BOOTLOADER_VERSION "0.5.7" +#define BOOTLOADER_VERSION "0.6.0" #define NB_MAGIC 0xAA774217 #define NB_DEBUGLOG_MAGIC 0xAEAE1123