Skip to content

Commit 48837f4

Browse files
jannaumarcan
authored andcommitted
kboot: Expose m1n1 console log in phram MTD reserved memory node
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]>
1 parent 1d5556c commit 48837f4

3 files changed

Lines changed: 73 additions & 5 deletions

File tree

src/iodev.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,19 @@
1818

1919
extern struct iodev iodev_uart;
2020
extern struct iodev iodev_fb;
21+
extern struct iodev iodev_log;
2122
extern struct iodev iodev_usb_vuart;
2223

23-
struct iodev *iodevs[IODEV_MAX] = {
24+
struct iodev *iodevs[IODEV_NUM] = {
2425
[IODEV_UART] = &iodev_uart,
2526
[IODEV_FB] = &iodev_fb,
2627
[IODEV_USB_VUART] = &iodev_usb_vuart,
28+
[IODEV_LOG] = &iodev_log,
2729
};
2830

2931
char con_buf[CONSOLE_BUFFER_SIZE];
3032
size_t con_wp;
31-
size_t con_rp[IODEV_MAX];
33+
size_t con_rp[IODEV_NUM];
3234

3335
void iodev_register_device(iodev_id_t id, struct iodev *dev)
3436
{
@@ -173,7 +175,7 @@ void iodev_console_write(const void *buf, size_t length)
173175
in_iodev++;
174176

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

@@ -275,7 +277,7 @@ void iodev_console_kick(void)
275277
{
276278
iodev_console_write(NULL, 0);
277279

278-
for (iodev_id_t id = 0; id < IODEV_MAX; id++) {
280+
for (iodev_id_t id = 0; id < IODEV_NUM; id++) {
279281
if (!iodevs[id])
280282
continue;
281283
if (!(iodevs[id]->usage & USAGE_CONSOLE))
@@ -287,7 +289,7 @@ void iodev_console_kick(void)
287289

288290
void iodev_console_flush(void)
289291
{
290-
for (iodev_id_t id = 0; id < IODEV_MAX; id++) {
292+
for (iodev_id_t id = 0; id < IODEV_NUM; id++) {
291293
if (!iodevs[id])
292294
continue;
293295
if (!(iodevs[id]->usage & USAGE_CONSOLE))

src/iodev.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ typedef enum _iodev_id_t {
1414
IODEV_USB_VUART,
1515
IODEV_USB0,
1616
IODEV_MAX = IODEV_USB0 + USB_IODEV_COUNT,
17+
IODEV_LOG = IODEV_MAX, // hidden log buffer iodev
18+
IODEV_NUM,
1719
} iodev_id_t;
1820

1921
typedef enum _iodev_usage_t {

src/kboot.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "display.h"
1212
#include "exception.h"
1313
#include "firmware.h"
14+
#include "iodev.h"
1415
#include "isp.h"
1516
#include "malloc.h"
1617
#include "mcc.h"
@@ -2265,6 +2266,54 @@ int kboot_set_chosen(const char *name, const char *value)
22652266
return i;
22662267
}
22672268

2269+
#define LOGBUF_SIZE SZ_16K
2270+
2271+
struct {
2272+
void *buffer;
2273+
size_t wp;
2274+
} logbuf;
2275+
2276+
static bool log_console_iodev_can_write(void *opaque)
2277+
{
2278+
UNUSED(opaque);
2279+
return !!logbuf.buffer;
2280+
}
2281+
2282+
static ssize_t log_console_iodev_write(void *opaque, const void *buf, size_t len)
2283+
{
2284+
UNUSED(opaque);
2285+
2286+
if (!logbuf.buffer)
2287+
return 0;
2288+
2289+
ssize_t wrote = 0;
2290+
size_t remain = LOGBUF_SIZE - logbuf.wp;
2291+
while (remain < len) {
2292+
memcpy(logbuf.buffer + logbuf.wp, buf, remain);
2293+
logbuf.wp = 0;
2294+
wrote += remain;
2295+
buf += remain;
2296+
len -= remain;
2297+
remain = LOGBUF_SIZE;
2298+
}
2299+
memcpy(logbuf.buffer + logbuf.wp, buf, len);
2300+
wrote += len;
2301+
logbuf.wp = (logbuf.wp + len) % LOGBUF_SIZE;
2302+
2303+
return wrote;
2304+
}
2305+
2306+
const struct iodev_ops iodev_log_ops = {
2307+
.can_write = log_console_iodev_can_write,
2308+
.write = log_console_iodev_write,
2309+
};
2310+
2311+
struct iodev iodev_log = {
2312+
.ops = &iodev_log_ops,
2313+
.usage = USAGE_CONSOLE,
2314+
.lock = SPINLOCK_INIT,
2315+
};
2316+
22682317
static int dt_setup_mtd_phram(void)
22692318
{
22702319
char node_name[64];
@@ -2279,6 +2328,20 @@ static int dt_setup_mtd_phram(void)
22792328
bail("FDT: failed to setup ADT MTD phram label\n");
22802329
}
22812330

2331+
// init memory backed iodev for console log
2332+
logbuf.buffer = (void *)top_of_memory_alloc(LOGBUF_SIZE);
2333+
if (!logbuf.buffer)
2334+
bail("FDT: failed to allocate m1n1 log buffer\n");
2335+
2336+
snprintf(node_name, sizeof(node_name), "flash@%lx", (u64)logbuf.buffer);
2337+
node = dt_get_or_add_reserved_mem(node_name, "phram", false, (u64)logbuf.buffer, SZ_16K);
2338+
2339+
if (node > 0) {
2340+
int ret = fdt_setprop_string(dt, node, "label", "m1n1_stage2.log");
2341+
if (ret)
2342+
bail("FDT: failed to setup m1n1 log MTD phram label\n");
2343+
}
2344+
22822345
return 0;
22832346
}
22842347

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

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

23122376
if (dt_set_chosen())

0 commit comments

Comments
 (0)