kboot: Rework how kboot_prepare_fw() works

Now it just builds and returns the firmware portion of the initramfs. It
is up to the caller to prepend it to the user-supplied initramfs, unless
no initramfs was set, in which case kboot_prepare_dt will implicitly
call kboot_prepare_fw.

Then make the payload code and linux.py handle this properly.

Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
Hector Martin 2021-07-23 02:43:46 +09:00
parent 63e8d0d48e
commit 7e5b734ae7
9 changed files with 53 additions and 31 deletions

View file

@ -514,6 +514,7 @@ class M1N1Proxy(Reloadable):
P_KBOOT_SET_BOOTARGS = 0x701 P_KBOOT_SET_BOOTARGS = 0x701
P_KBOOT_SET_INITRD = 0x702 P_KBOOT_SET_INITRD = 0x702
P_KBOOT_PREPARE_DT = 0x703 P_KBOOT_PREPARE_DT = 0x703
P_KBOOT_PREPARE_FW = 0x704
P_PMGR_CLOCK_ENABLE = 0x800 P_PMGR_CLOCK_ENABLE = 0x800
P_PMGR_CLOCK_DISABLE = 0x801 P_PMGR_CLOCK_DISABLE = 0x801
@ -852,6 +853,8 @@ class M1N1Proxy(Reloadable):
self.request(self.P_KBOOT_SET_INITRD, base, size) self.request(self.P_KBOOT_SET_INITRD, base, size)
def kboot_prepare_dt(self, dt_addr): def kboot_prepare_dt(self, dt_addr):
return self.request(self.P_KBOOT_PREPARE_DT, dt_addr) return self.request(self.P_KBOOT_PREPARE_DT, dt_addr)
def kboot_prepare_fw(self, p_size):
return self.request(self.P_KBOOT_PREPARE_FW, p_size)
def pmgr_clock_enable(self, clkid): def pmgr_clock_enable(self, clkid):
return self.request(self.P_PMGR_CLOCK_ENABLE, clkid) return self.request(self.P_PMGR_CLOCK_ENABLE, clkid)

View file

@ -68,11 +68,24 @@ print("Kernel_base: 0x%x" % kernel_base)
assert not (kernel_base & 0xffff) assert not (kernel_base & 0xffff)
if initramfs is not None: if initramfs is not None:
initramfs_base = u.memalign(65536, initramfs_size) psize = u.malloc(8)
print("Loading %d initramfs bytes to 0x%x..." % (initramfs_size, initramfs_base)) fw = proxy.kboot_prepare_fw(psize)
iface.writemem(initramfs_base, initramfs, True) if fw:
p.kboot_set_initrd(initramfs_base, initramfs_size) fw_size = p.read64(psize)
else:
fw_size = 0
initramfs_base = initramfs_load = u.memalign(65536, initramfs_size + fw_size)
if fw_size:
print("Copying %d firmware bytes to 0x%x..." % (fw_size, initramfs_base + fw_size))
p.memcpy(initramfs_base, fw, fw_size)
print("Loading %d initramfs bytes to 0x%x..." % (initramfs_size, initramfs_base + fw_size))
iface.writemem(initramfs_base + fw_size, initramfs, True)
p.kboot_set_initrd(initramfs_base, initramfs_size + fw_size)
if fw:
p.free(fw)
if args.u_boot: if args.u_boot:
uboot = bytearray(args.u_boot.read_bytes()) uboot = bytearray(args.u_boot.read_bytes())

View file

@ -118,12 +118,12 @@ size_t cpio_get_size(struct cpio *c)
return sz; return sz;
} }
size_t cpio_finalize(struct cpio *c, u8 *bfr, size_t bfr_size) int cpio_finalize(struct cpio *c, u8 *bfr, size_t bfr_size)
{ {
size_t off = 0; size_t off = 0;
if (cpio_get_size(c) > bfr_size) if (cpio_get_size(c) > bfr_size)
return 0; return -1;
for (u32 i = 0; i < c->n_files; ++i) { for (u32 i = 0; i < c->n_files; ++i) {
memcpy(bfr + off, &c->files[i].hdr, sizeof(struct cpio_header)); memcpy(bfr + off, &c->files[i].hdr, sizeof(struct cpio_header));

View file

@ -12,7 +12,7 @@ struct cpio *cpio_init(void);
int cpio_add_file(struct cpio *c, const char *name, const u8 *bfr, size_t sz); int cpio_add_file(struct cpio *c, const char *name, const u8 *bfr, size_t sz);
int cpio_add_dir(struct cpio *c, const char *name); int cpio_add_dir(struct cpio *c, const char *name);
size_t cpio_get_size(struct cpio *c); size_t cpio_get_size(struct cpio *c);
size_t cpio_finalize(struct cpio *c, u8 *bfr, size_t bfr_size); int cpio_finalize(struct cpio *c, u8 *bfr, size_t bfr_size);
void cpio_free(struct cpio *c); void cpio_free(struct cpio *c);
#endif #endif

View file

@ -308,8 +308,8 @@ int kboot_prepare_dt(void *fdt)
dt = NULL; dt = NULL;
} }
if (kboot_prepare_fw() < 0) if (!initrd_start)
bail("FDT: couldn't prepare firmware."); initrd_start = kboot_prepare_fw(&initrd_size);
dt_bufsize = fdt_totalsize(fdt); dt_bufsize = fdt_totalsize(fdt);
assert(dt_bufsize); assert(dt_bufsize);
@ -368,13 +368,11 @@ static int kboot_prepare_sepfw(struct cpio *c)
return 0; return 0;
} }
int kboot_prepare_fw(void) void *kboot_prepare_fw(size_t *size)
{ {
struct cpio *c = cpio_init(); struct cpio *c = cpio_init();
u8 *cpio_start = NULL; u8 *cpio_start = NULL;
u8 *new_initrd_start = NULL;
size_t cpio_size = 0; size_t cpio_size = 0;
u32 new_initrd_size = 0;
if (cpio_add_dir(c, "lib") < 0) if (cpio_add_dir(c, "lib") < 0)
goto err; goto err;
@ -386,33 +384,26 @@ int kboot_prepare_fw(void)
if (kboot_prepare_sepfw(c) < 0) if (kboot_prepare_sepfw(c) < 0)
printf("kboot: no SEPFW found.\n"); printf("kboot: no SEPFW found.\n");
if (cpio_add_file(c, "TRAILER!!!", NULL, 0) < 0)
goto err;
cpio_size = cpio_get_size(c); cpio_size = cpio_get_size(c);
new_initrd_size = cpio_size + ALIGN_UP(initrd_size, 4); cpio_start = memalign(INITRD_ALIGN, cpio_size);
new_initrd_start = memalign(INITRD_ALIGN, new_initrd_size); int res = cpio_finalize(c, cpio_start, cpio_size);
if (!new_initrd_start) { if (res != (int)cpio_size) {
printf("kboot: couldn't allocate initrd buffer\n"); printf("kboot: unexpected cpio_finalize size: %d should be %lu\n", res, cpio_size);
goto err; goto err;
} }
memcpy(new_initrd_start, initrd_start, initrd_size); if (size)
*size = cpio_size;
cpio_start = new_initrd_start + ALIGN_UP(initrd_size, 4);
size_t res = cpio_finalize(c, cpio_start, cpio_size);
if (res != cpio_size) {
printf("kboot: unexpected cpio_finalize size: %lu should be %lu\n", res, cpio_size);
goto err;
}
initrd_start = new_initrd_start;
initrd_size = new_initrd_size;
cpio_free(c); cpio_free(c);
return cpio_start;
return 0;
err: err:
free(new_initrd_start);
cpio_free(c); cpio_free(c);
return -1; return NULL;
} }
int kboot_boot(void *kernel) int kboot_boot(void *kernel)

View file

@ -19,7 +19,7 @@ struct kernel_header {
void kboot_set_initrd(void *start, size_t size); void kboot_set_initrd(void *start, size_t size);
void kboot_set_bootargs(const char *ba); void kboot_set_bootargs(const char *ba);
int kboot_prepare_fw(void); void *kboot_prepare_fw(size_t *size);
int kboot_prepare_dt(void *fdt); int kboot_prepare_dt(void *fdt);
int kboot_boot(void *kernel); int kboot_boot(void *kernel);

View file

@ -4,6 +4,7 @@
#include "assert.h" #include "assert.h"
#include "heapblock.h" #include "heapblock.h"
#include "kboot.h" #include "kboot.h"
#include "malloc.h"
#include "smp.h" #include "smp.h"
#include "utils.h" #include "utils.h"
@ -104,6 +105,16 @@ static void *load_cpio(void *p, size_t size)
return NULL; return NULL;
} }
size_t fw_size;
void *fw = kboot_prepare_fw(&fw_size);
if (fw) {
memmove((void *)(fw_size + (u64)p), p, size);
memcpy(p, fw, fw_size);
free(fw);
size += fw_size;
}
kboot_set_initrd(p, size); kboot_set_initrd(p, size);
return ((u8 *)p) + size; return ((u8 *)p) + size;
} }

View file

@ -351,6 +351,9 @@ int proxy_process(ProxyRequest *request, ProxyReply *reply)
case P_KBOOT_PREPARE_DT: case P_KBOOT_PREPARE_DT:
reply->retval = kboot_prepare_dt((void *)request->args[0]); reply->retval = kboot_prepare_dt((void *)request->args[0]);
break; break;
case P_KBOOT_PREPARE_FW:
reply->retval = (u64)kboot_prepare_fw((size_t *)request->args[0]);
break;
case P_PMGR_CLOCK_ENABLE: case P_PMGR_CLOCK_ENABLE:
reply->retval = pmgr_clock_enable(request->args[0]); reply->retval = pmgr_clock_enable(request->args[0]);

View file

@ -90,6 +90,7 @@ typedef enum {
P_KBOOT_SET_BOOTARGS, P_KBOOT_SET_BOOTARGS,
P_KBOOT_SET_INITRD, P_KBOOT_SET_INITRD,
P_KBOOT_PREPARE_DT, P_KBOOT_PREPARE_DT,
P_KBOOT_PREPARE_FW,
P_PMGR_CLOCK_ENABLE = 0x800, // power/clock management ops P_PMGR_CLOCK_ENABLE = 0x800, // power/clock management ops
P_PMGR_CLOCK_DISABLE, P_PMGR_CLOCK_DISABLE,