[bootdata] further movement toward new bootdata headers
- bootloader, kernel, userboot, and devmgr now support FLAG_EXTRA for container headers as well as item headers - bootloader generates new style headers for prepended bootdata items when it detects a new style container header - mkbootfs generates large container headers when generating bootdata images with crc32 enabled - bootloader version bumped to 0.6.0 to mark the point of compatibility needed for kernels once we throw the switch to use new headers exclusively Change-Id: Ifcb78d62f882ddd869da8d73ffe774a0f7937bc0
Esse commit está contido em:
commit de
CQ bot account: commit-bot@chromium.org
pai
ad86b5ee58
commit
71b934bd5b
@@ -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 \
|
||||
|
||||
@@ -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 <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xefi.h>
|
||||
|
||||
#include "osboot.h"
|
||||
|
||||
#include <magenta/boot/bootdata.h>
|
||||
|
||||
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;
|
||||
}
|
||||
+120
-49
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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<const uintptr_t>(root);
|
||||
bootdata_t* section = reinterpret_cast<bootdata_t*>(ptr + offset);
|
||||
|
||||
@@ -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<bootdata_t*>(reinterpret_cast<char*>(hdr) + hsz);
|
||||
|
||||
size_t remain = hdr->length;
|
||||
while (remain > sizeof(bootdata_t)) {
|
||||
remain -= sizeof(bootdata_t);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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--;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário