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 \
|
||||
asc.o \
|
||||
bootlogo_128.o bootlogo_256.o \
|
||||
chainload.o \
|
||||
chainload_asm.o \
|
||||
chickens.o \
|
||||
clk.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