mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-22 06:33:03 +00:00
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 <j@jannau.net>
This commit is contained in:
parent
1d5556ccf3
commit
48837f4d47
3 changed files with 73 additions and 5 deletions
12
src/iodev.c
12
src/iodev.c
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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))
|
||||
|
|
|
@ -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 {
|
||||
|
|
64
src/kboot.c
64
src/kboot.c
|
@ -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"
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
|
|
Loading…
Reference in a new issue