mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-21 22:23:05 +00:00
chainload: Add new m1n1-side chainloader (raw images only)
This basically duplicates the chainload.py logic, minus the mach-o handling. Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
parent
0a8a593cdc
commit
e386e17550
4 changed files with 151 additions and 0 deletions
2
Makefile
2
Makefile
|
@ -61,6 +61,8 @@ OBJECTS := \
|
||||||
aic.o \
|
aic.o \
|
||||||
asc.o \
|
asc.o \
|
||||||
bootlogo_128.o bootlogo_256.o \
|
bootlogo_128.o bootlogo_256.o \
|
||||||
|
chainload.o \
|
||||||
|
chainload_asm.o \
|
||||||
chickens.o \
|
chickens.o \
|
||||||
clk.o \
|
clk.o \
|
||||||
cpufreq.o \
|
cpufreq.o \
|
||||||
|
|
118
src/chainload.c
Normal file
118
src/chainload.c
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
#include "chainload.h"
|
||||||
|
#include "adt.h"
|
||||||
|
#include "malloc.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "nvme.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "xnuboot.h"
|
||||||
|
|
||||||
|
extern u8 _chainload_stub_start[];
|
||||||
|
extern u8 _chainload_stub_end[];
|
||||||
|
|
||||||
|
int chainload_image(void *image, size_t size, char **vars, size_t var_cnt)
|
||||||
|
{
|
||||||
|
u64 new_base = (u64)_base;
|
||||||
|
size_t image_size = size;
|
||||||
|
|
||||||
|
printf("chainload: Preparing image...\n");
|
||||||
|
|
||||||
|
// m1n1 variables
|
||||||
|
for (size_t i = 0; i < var_cnt; i++)
|
||||||
|
image_size += strlen(vars[i]) + 1;
|
||||||
|
|
||||||
|
// pad to end payload
|
||||||
|
image_size += 4;
|
||||||
|
image_size = ALIGN_UP(image_size, SZ_16K);
|
||||||
|
size_t kernel_size = image_size;
|
||||||
|
|
||||||
|
// SEPFW
|
||||||
|
size_t sepfw_off = image_size;
|
||||||
|
|
||||||
|
int anode = adt_path_offset(adt, "/chosen/memory-map");
|
||||||
|
if (anode < 0) {
|
||||||
|
printf("chainload: /chosen/memory-map not found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
u64 sepfw[2];
|
||||||
|
if (ADT_GETPROP_ARRAY(adt, anode, "SEPFW", sepfw) < 0) {
|
||||||
|
printf("chainload: Failed to find SEPFW\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
image_size += sepfw[1];
|
||||||
|
image_size = ALIGN_UP(image_size, SZ_16K);
|
||||||
|
|
||||||
|
// Bootargs
|
||||||
|
size_t bootargs_off = image_size;
|
||||||
|
const size_t bootargs_size = SZ_16K;
|
||||||
|
image_size += bootargs_size;
|
||||||
|
|
||||||
|
printf("chainload: Total image size: 0x%lx\n", image_size);
|
||||||
|
|
||||||
|
size_t stub_size = _chainload_stub_end - _chainload_stub_start;
|
||||||
|
|
||||||
|
void *new_image = malloc(image_size + stub_size);
|
||||||
|
|
||||||
|
// Copy m1n1
|
||||||
|
memcpy(new_image, image, size);
|
||||||
|
|
||||||
|
// Add vars
|
||||||
|
u8 *p = new_image + size;
|
||||||
|
for (size_t i = 0; i < var_cnt; i++) {
|
||||||
|
size_t len = strlen(vars[i]);
|
||||||
|
|
||||||
|
memcpy(p, vars[i], len);
|
||||||
|
p[len] = '\n';
|
||||||
|
p += len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add end padding
|
||||||
|
memset(p, 0, 4);
|
||||||
|
|
||||||
|
// Copy SEPFW
|
||||||
|
memcpy(new_image + sepfw_off, (void *)sepfw[0], sepfw[1]);
|
||||||
|
|
||||||
|
// Adjust ADT SEPFW address
|
||||||
|
sepfw[0] = new_base + sepfw_off;
|
||||||
|
if (adt_setprop(adt, anode, "SEPFW", &sepfw, sizeof(sepfw)) < 0) {
|
||||||
|
printf("chainload: Failed to set SEPFW prop\n");
|
||||||
|
free(new_image);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy bootargs
|
||||||
|
struct boot_args *new_boot_args = new_image + bootargs_off;
|
||||||
|
*new_boot_args = cur_boot_args;
|
||||||
|
new_boot_args->top_of_kernel_data = new_base + kernel_size;
|
||||||
|
|
||||||
|
// Copy chainload stub
|
||||||
|
void *stub = new_image + image_size;
|
||||||
|
memcpy(stub, _chainload_stub_start, stub_size);
|
||||||
|
dc_cvau_range(stub, stub_size);
|
||||||
|
ic_ivau_range(stub, stub_size);
|
||||||
|
|
||||||
|
// Set up next stage
|
||||||
|
next_stage.entry = stub;
|
||||||
|
next_stage.args[0] = new_base + bootargs_off;
|
||||||
|
next_stage.args[1] = (u64)new_image;
|
||||||
|
next_stage.args[2] = new_base;
|
||||||
|
next_stage.args[3] = image_size;
|
||||||
|
next_stage.args[4] = new_base + 0x800; // m1n1 entrypoint
|
||||||
|
next_stage.restore_logo = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int chainload_load(const char *spec, char **vars, size_t var_cnt)
|
||||||
|
{
|
||||||
|
UNUSED(spec);
|
||||||
|
UNUSED(vars);
|
||||||
|
UNUSED(var_cnt);
|
||||||
|
|
||||||
|
printf("Chainloading files not supported in this build!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
11
src/chainload.h
Normal file
11
src/chainload.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
#ifndef __CHAINLOAD_H__
|
||||||
|
#define __CHAINLOAD_H__
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
int chainload_image(void *base, size_t size, char **vars, size_t var_cnt);
|
||||||
|
int chainload_load(const char *spec, char **vars, size_t var_cnt);
|
||||||
|
|
||||||
|
#endif
|
20
src/chainload_asm.S
Normal file
20
src/chainload_asm.S
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
.globl _chainload_stub_start
|
||||||
|
.globl _chainload_stub_end
|
||||||
|
.type _chainload_stub_start, @function
|
||||||
|
|
||||||
|
_chainload_stub_start:
|
||||||
|
1:
|
||||||
|
ldp x5, x6, [x1], #16
|
||||||
|
stp x5, x6, [x2]
|
||||||
|
dc cvau, x2
|
||||||
|
ic ivau, x2
|
||||||
|
add x2, x2, #16
|
||||||
|
sub x3, x3, #16
|
||||||
|
cbnz x3, 1b
|
||||||
|
|
||||||
|
br x4
|
||||||
|
_chainload_stub_end:
|
Loading…
Reference in a new issue