Skip to content

Commit

Permalink
kboot: Expose m1n1 console log in phram MTD reserved memory node
Browse files Browse the repository at this point in the history
This registers a log buffer IODEV similar to the frame buffer IODEV. It
is using a console IODEV to allow writing to the buffer until m1n1 jumps
to the next stage. This allows also to increase the buffer size without
increasing m1n1's size. The current CONSOLE_BUFFER_SIZE of 8k is not
large enough to hold the entire log of executing m1n1 under the
hypervisor on the M1 Ultra Mac Studio.

Signed-off-by: Janne Grunau <[email protected]>
  • Loading branch information
jannau authored and marcan committed Sep 24, 2024
1 parent 1d5556c commit 48837f4
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 5 deletions.
12 changes: 7 additions & 5 deletions src/iodev.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@

extern struct iodev iodev_uart;
extern struct iodev iodev_fb;
extern struct iodev iodev_log;
extern struct iodev iodev_usb_vuart;

struct iodev *iodevs[IODEV_MAX] = {
struct iodev *iodevs[IODEV_NUM] = {
[IODEV_UART] = &iodev_uart,
[IODEV_FB] = &iodev_fb,
[IODEV_USB_VUART] = &iodev_usb_vuart,
[IODEV_LOG] = &iodev_log,
};

char con_buf[CONSOLE_BUFFER_SIZE];
size_t con_wp;
size_t con_rp[IODEV_MAX];
size_t con_rp[IODEV_NUM];

void iodev_register_device(iodev_id_t id, struct iodev *dev)
{
Expand Down Expand Up @@ -173,7 +175,7 @@ void iodev_console_write(const void *buf, size_t length)
in_iodev++;

dprintf(" iodev_console_write() wp=%d\n", con_wp);
for (iodev_id_t id = 0; id < IODEV_MAX; id++) {
for (iodev_id_t id = 0; id < IODEV_NUM; id++) {
if (!iodevs[id])
continue;

Expand Down Expand Up @@ -275,7 +277,7 @@ void iodev_console_kick(void)
{
iodev_console_write(NULL, 0);

for (iodev_id_t id = 0; id < IODEV_MAX; id++) {
for (iodev_id_t id = 0; id < IODEV_NUM; id++) {
if (!iodevs[id])
continue;
if (!(iodevs[id]->usage & USAGE_CONSOLE))
Expand All @@ -287,7 +289,7 @@ void iodev_console_kick(void)

void iodev_console_flush(void)
{
for (iodev_id_t id = 0; id < IODEV_MAX; id++) {
for (iodev_id_t id = 0; id < IODEV_NUM; id++) {
if (!iodevs[id])
continue;
if (!(iodevs[id]->usage & USAGE_CONSOLE))
Expand Down
2 changes: 2 additions & 0 deletions src/iodev.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ typedef enum _iodev_id_t {
IODEV_USB_VUART,
IODEV_USB0,
IODEV_MAX = IODEV_USB0 + USB_IODEV_COUNT,
IODEV_LOG = IODEV_MAX, // hidden log buffer iodev
IODEV_NUM,
} iodev_id_t;

typedef enum _iodev_usage_t {
Expand Down
64 changes: 64 additions & 0 deletions src/kboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "display.h"
#include "exception.h"
#include "firmware.h"
#include "iodev.h"
#include "isp.h"
#include "malloc.h"
#include "mcc.h"
Expand Down Expand Up @@ -2265,6 +2266,54 @@ int kboot_set_chosen(const char *name, const char *value)
return i;
}

#define LOGBUF_SIZE SZ_16K

struct {
void *buffer;
size_t wp;
} logbuf;

static bool log_console_iodev_can_write(void *opaque)
{
UNUSED(opaque);
return !!logbuf.buffer;
}

static ssize_t log_console_iodev_write(void *opaque, const void *buf, size_t len)
{
UNUSED(opaque);

if (!logbuf.buffer)
return 0;

ssize_t wrote = 0;
size_t remain = LOGBUF_SIZE - logbuf.wp;
while (remain < len) {
memcpy(logbuf.buffer + logbuf.wp, buf, remain);
logbuf.wp = 0;
wrote += remain;
buf += remain;
len -= remain;
remain = LOGBUF_SIZE;
}
memcpy(logbuf.buffer + logbuf.wp, buf, len);
wrote += len;
logbuf.wp = (logbuf.wp + len) % LOGBUF_SIZE;

return wrote;
}

const struct iodev_ops iodev_log_ops = {
.can_write = log_console_iodev_can_write,
.write = log_console_iodev_write,
};

struct iodev iodev_log = {
.ops = &iodev_log_ops,
.usage = USAGE_CONSOLE,
.lock = SPINLOCK_INIT,
};

static int dt_setup_mtd_phram(void)
{
char node_name[64];
Expand All @@ -2279,6 +2328,20 @@ static int dt_setup_mtd_phram(void)
bail("FDT: failed to setup ADT MTD phram label\n");
}

// init memory backed iodev for console log
logbuf.buffer = (void *)top_of_memory_alloc(LOGBUF_SIZE);
if (!logbuf.buffer)
bail("FDT: failed to allocate m1n1 log buffer\n");

snprintf(node_name, sizeof(node_name), "flash@%lx", (u64)logbuf.buffer);
node = dt_get_or_add_reserved_mem(node_name, "phram", false, (u64)logbuf.buffer, SZ_16K);

if (node > 0) {
int ret = fdt_setprop_string(dt, node, "label", "m1n1_stage2.log");
if (ret)
bail("FDT: failed to setup m1n1 log MTD phram label\n");
}

return 0;
}

Expand Down Expand Up @@ -2307,6 +2370,7 @@ int kboot_prepare_dt(void *fdt)
if (fdt_add_mem_rsv(dt, (u64)_base, ((u64)_end) - ((u64)_base)))
bail("FDT: couldn't add reservation for m1n1\n");

/* setup console log buffer early to cpature as much log as possible */
dt_setup_mtd_phram();

if (dt_set_chosen())
Expand Down

0 comments on commit 48837f4

Please sign in to comment.