Skip to content

Commit

Permalink
Build relocation stub from source
Browse files Browse the repository at this point in the history
  • Loading branch information
9ary committed Dec 5, 2023
1 parent 3ec63cd commit 2d51e62
Show file tree
Hide file tree
Showing 9 changed files with 194 additions and 65 deletions.
8 changes: 6 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,22 @@ dols = {}
# executable to `dols`.
compressed_exes = {}

subdir('stub')

linker_script = meson.current_source_dir() / 'ogc.ld'

iplboot = executable(
'iplboot',
'source/main.c',
'source/stub.c',
'source/utils.c',
'source/fatfs/ff.c',
'source/fatfs/ffsystem.c',
'source/fatfs/ffunicode.c',
'source/ffshim.c',
dependencies: libogc_deps['ogc'],
dependencies: [
libogc_deps['ogc'],
stub_dep,
],
link_args: ['-T' + linker_script],
link_depends: [linker_script],
name_suffix: 'elf',
Expand Down
11 changes: 10 additions & 1 deletion ogc.ld
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,13 @@ SECTIONS
PROVIDE (_etext = .);
PROVIDE (etext = .);

.rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) } :data
.rodata : {
*(.rodata) *(.rodata.*)
*(.gnu.linkonce.r.*)
stub = .;
KEEP(*(reloc_stub.data))
__stub_end = .;
} :data
.rodata1 : { *(.rodata1) }
.sdata2 : {
PROVIDE(_SDA2_BASE_ = . );
Expand Down Expand Up @@ -261,6 +267,9 @@ SECTIONS
/* These must appear regardless of . */
}

stub_size = __stub_end - stub;
ASSERT(stub_size > 0, "Relocation stub missing!")

__isIPL = 0;
__stack_addr = (__bss_start + SIZEOF(.bss) + 0x20000 + 7) & (-8);
__stack_end = (__bss_start + SIZEOF(.bss));
Expand Down
6 changes: 2 additions & 4 deletions source/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
#include "utils.h"

#include "stub.h"
#define STUB_ADDR 0x80001000
#define STUB_STACK 0x80003000

#define VERBOSE_LOGGING 0

Expand Down Expand Up @@ -450,8 +448,8 @@ int main()
}
}

memcpy((void *) STUB_ADDR, stub, stub_size);
DCStoreRange((void *) STUB_ADDR, stub_size);
memcpy((void *) STUB_ADDR, stub, (size_t) stub_size);
DCStoreRange((void *) STUB_ADDR, (u32) stub_size);

delay_exit();

Expand Down
44 changes: 0 additions & 44 deletions source/stub.c

This file was deleted.

14 changes: 0 additions & 14 deletions source/stub.h

This file was deleted.

21 changes: 21 additions & 0 deletions stub/link.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
OUTPUT_FORMAT("elf32-powerpc")
OUTPUT_ARCH(powerpc:common)
ENTRY(not_main)

PHDRS
{
stub PT_LOAD FLAGS(5);
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
bss PT_LOAD FLAGS(6);
}

SECTIONS
{
. = ALIGN(32);
.text :
{
*(.text.not_main)
*(.text .text.*)
} : text
}
49 changes: 49 additions & 0 deletions stub/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
stub_linker_script = meson.current_source_dir() / 'link.ld'

stub_exe = executable(
'stub',
'stub.c',
c_args: [
'-fPIC',
'-ffreestanding',
'-mno-eabi',
],
link_args: [
'-nostdlib',
'-T' + stub_linker_script,
],
link_depends: stub_linker_script,
dependencies: [
# For the headers
libogc_deps['ogc'].partial_dependency(
compile_args: true,
sources: true,
),
],
)

stub_bin = custom_target(
'stub_bin',
input: stub_exe,
output: 'stub.bin',
command: [objcopy, '-O', 'binary', '@INPUT@', '@OUTPUT@'],
)

stub_o = custom_target(
'stub_o',
input: stub_bin,
output: 'stub.o',
command: [
objcopy,
'-I', 'binary',
'-O', 'default',
'@INPUT@',
'@OUTPUT@',
'--prefix-sections=reloc_stub',
],
)

stub_dep = declare_dependency(
sources: stub_o,
include_directories: '.',
)
97 changes: 97 additions & 0 deletions stub/stub.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright (c) 2014-2023, Extrems' Corner.org
* All rights reserved.
*/

#include <ogc/system.h>
#include <ogc/machine/processor.h>

typedef struct {
ptrdiff_t section_offset[18];

void *section[18];
size_t section_size[18];

void *bss;
size_t bss_size;

void (*entrypoint)(void);
} dol_header_t;

static void memsync(void *buf, size_t size)
{
uint8_t *b = buf;
size_t i;

for (i = 0; i < size; i += PPC_CACHE_ALIGNMENT)
asm("dcbst %y0" :: "Z" (b[i]));
}

static void memzero(void *buf, size_t size)
{
uint8_t *b = buf;
uint8_t *e = b + size;

while (b != e)
*b++ = '\0';
}

static void *memmove(void *dest, const void *src, size_t size)
{
uint8_t *d = dest;
const uint8_t *s = src;
size_t i;

if (d < s) {
for (i = 0; i < size; ++i)
d[i] = s[i];
} else if (d > s) {
i = size;
while (i-- > 0)
d[i] = s[i];
}

return dest;
}

// Workaround for GCC bug 5372 – [powerpc-*-eabi] -mno-eabi not working
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=5372
// Entry point can't be called main or GCC will insert a call to __eabi
__attribute__((noreturn)) void not_main(const void *buf, size_t buflen, const void *arg, size_t arglen)
{
dol_header_t header;
uint32_t *entrypoint;
uint8_t args[arglen];

memmove(&header, buf, sizeof(dol_header_t));
memmove(args, arg, arglen);

if (header.section[0] < buf + header.section_offset[0]) {
for (int i = 0; i < 18; i++) {
memmove(header.section[i], buf + header.section_offset[i], header.section_size[i]);
memsync(header.section[i], header.section_size[i]);
}
} else {
for (int i = 18; i > 0; i--) {
memmove(header.section[i - 1], buf + header.section_offset[i - 1], header.section_size[i - 1]);
memsync(header.section[i - 1], header.section_size[i - 1]);
}
}

memzero(header.bss, header.bss_size);
memsync(header.bss, header.bss_size);

entrypoint = MEM_K0_TO_K1(header.entrypoint);

if (entrypoint[1] == ARGV_MAGIC && arglen) {
entrypoint[2] = ARGV_MAGIC;
entrypoint[3] = (intptr_t)args;
entrypoint[4] = arglen;
}

_sync();
mthid0(mfhid0() | 0xC00);
header.entrypoint();

__builtin_unreachable();
}
9 changes: 9 additions & 0 deletions stub/stub.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <stdint.h>

#define STUB_ADDR 0x80001000
#define STUB_STACK 0x80003000

extern const uint8_t stub[];
extern const uint8_t stub_size[];

0 comments on commit 2d51e62

Please sign in to comment.