/* SPDX-License-Identifier: MIT */ #include "../build/build_cfg.h" #include "../build/build_tag.h" #include "../config.h" #include "adt.h" #include "aic.h" #include "clk.h" #include "cpufreq.h" #include "display.h" #include "exception.h" #include "fb.h" #include "firmware.h" #include "gxf.h" #include "heapblock.h" #include "mcc.h" #include "memory.h" #include "nvme.h" #include "payload.h" #include "pcie.h" #include "pmgr.h" #include "sep.h" #include "smp.h" #include "string.h" #include "tunables.h" #include "uart.h" #include "uartproxy.h" #include "usb.h" #include "utils.h" #include "wdt.h" #include "xnuboot.h" struct vector_args next_stage; const char version_tag[] = "##m1n1_ver##" BUILD_TAG; const char *const m1n1_version = version_tag + 12; u32 board_id = ~0, chip_id = ~0; void get_device_info(void) { printf("Device info:\n"); printf(" Model: %s\n", (const char *)adt_getprop(adt, 0, "model", NULL)); printf(" Target: %s\n", (const char *)adt_getprop(adt, 0, "target-type", NULL)); int chosen = adt_path_offset(adt, "/chosen"); if (chosen > 0) { if (ADT_GETPROP(adt, chosen, "board-id", &board_id) < 0) printf("Failed to find board-id\n"); if (ADT_GETPROP(adt, chosen, "chip-id", &chip_id) < 0) printf("Failed to find chip-id\n"); printf(" Board-ID: 0x%x\n", board_id); printf(" Chip-ID: 0x%x\n", chip_id); } else { printf("No chosen node!\n"); } printf("\n"); } void run_actions(void) { bool usb_up = false; #ifndef BRINGUP #ifdef EARLY_PROXY_TIMEOUT int node = adt_path_offset(adt, "/chosen/asmb"); u64 lp_sip0 = 0; if (node >= 0) { ADT_GETPROP(adt, node, "lp-sip0", &lp_sip0); printf("Boot policy: sip0 = %ld\n", lp_sip0); } if (!cur_boot_args.video.display && lp_sip0 == 127) { printf("Bringing up USB for early debug...\n"); usb_init(); usb_iodev_init(); usb_up = true; printf("Waiting for proxy connection... "); for (int i = 0; i < EARLY_PROXY_TIMEOUT * 100; i++) { for (int j = 0; j < USB_IODEV_COUNT; j++) { iodev_id_t iodev = IODEV_USB0 + j; if (!(iodev_get_usage(iodev) & USAGE_UARTPROXY)) continue; usb_iodev_vuart_setup(iodev); iodev_handle_events(iodev); if (iodev_can_write(iodev) || iodev_can_write(IODEV_USB_VUART)) { printf(" Connected!\n"); uartproxy_run(NULL); return; } } mdelay(10); if (i % 100 == 99) printf("."); } printf(" Timed out\n"); } #endif #endif printf("Checking for payloads...\n"); if (payload_run() == 0) { printf("Valid payload found\n"); return; } fb_set_active(true); printf("No valid payload found\n"); #ifndef BRINGUP if (!usb_up) { usb_init(); usb_iodev_init(); } #endif printf("Running proxy...\n"); uartproxy_run(NULL); } void m1n1_main(void) { printf("\n\nm1n1 %s\n", m1n1_version); printf("Copyright The Asahi Linux Contributors\n"); printf("Licensed under the MIT license\n\n"); printf("Running in EL%lu\n\n", mrs(CurrentEL) >> 2); get_device_info(); firmware_init(); heapblock_init(); #ifndef BRINGUP gxf_init(); mcc_init(); mmu_init(); aic_init(); #endif wdt_disable(); #ifndef BRINGUP pmgr_init(); tunables_apply_static(); #ifdef USE_FB display_init(); // Kick DCP to sleep, so dodgy monitors which cause reconnect cycles don't cause us to lose the // framebuffer. display_shutdown(DCP_SLEEP_IF_EXTERNAL); fb_init(false); fb_display_logo(); #ifdef FB_SILENT_MODE fb_set_active(!cur_boot_args.video.display); #else fb_set_active(true); #endif #endif clk_init(); cpufreq_init(); sep_init(); #endif printf("Initialization complete.\n"); run_actions(); if (!next_stage.entry) { panic("Nothing to do!\n"); } printf("Preparing to run next stage at %p...\n", next_stage.entry); nvme_shutdown(); exception_shutdown(); #ifndef BRINGUP usb_iodev_shutdown(); display_shutdown(DCP_SLEEP_IF_EXTERNAL); #ifdef USE_FB fb_shutdown(next_stage.restore_logo); #endif mmu_shutdown(); #endif printf("Vectoring to next stage...\n"); next_stage.entry(next_stage.args[0], next_stage.args[1], next_stage.args[2], next_stage.args[3], next_stage.args[4]); panic("Next stage returned!\n"); }