mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-12-18 17:53:10 +00:00
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:
parent
63e8d0d48e
commit
7e5b734ae7
9 changed files with 53 additions and 31 deletions
|
@ -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)
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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
|
||||||
|
|
37
src/kboot.c
37
src/kboot.c
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue