mirror of
https://github.com/xenia-project/libxenon.git
synced 2026-01-31 01:25:22 +01:00
Rewrite the ELF loader / harden it against bad files
This commit is contained in:
@@ -10,6 +10,9 @@ modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY free60.org ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,9 +9,10 @@ char *argv_GetFilename(const char *argv);
|
||||
char *argv_GetFilepath(const char *argv);
|
||||
char *argv_GetDevice(const char *argv);
|
||||
void elf_setArgcArgv(int argc, char *argv[]);
|
||||
void elf_runFromMemory (void *addr, int size);
|
||||
int elf_runFromDisk (char *filename);
|
||||
int elf_runWithDeviceTree (void *elf_addr, int elf_size, void *dt_addr, int dt_size);
|
||||
int elf_runFromMemory(void *addr, int size);
|
||||
int elf_runFromDisk(char *filename);
|
||||
int elf_runWithDeviceTree(void *elf_addr, int elf_size, void *dt_addr,
|
||||
int dt_size);
|
||||
int kernel_prepare_initrd(void *start, size_t size);
|
||||
void kernel_relocate_initrd(void *start, size_t size);
|
||||
void kernel_reset_initrd(void);
|
||||
|
||||
@@ -39,6 +39,7 @@ typedef uint16_t Elf32_Half; /* Unsigned medium integer */
|
||||
#define EI_MAG1 1 /* file ID */
|
||||
#define EI_MAG2 2 /* file ID */
|
||||
#define EI_MAG3 3 /* file ID */
|
||||
#define EI_CLASS 4 /* ELF type */
|
||||
#define EI_NIDENT 16 /* Size of e_ident[] */
|
||||
|
||||
#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */
|
||||
@@ -46,6 +47,10 @@ typedef uint16_t Elf32_Half; /* Unsigned medium integer */
|
||||
#define ELFMAG2 'L' /* e_ident[EI_MAG2] */
|
||||
#define ELFMAG3 'F' /* e_ident[EI_MAG3] */
|
||||
|
||||
#define ELFCLASSNONE 0
|
||||
#define ELFCLASS32 1
|
||||
#define ELFCLASS64 2
|
||||
|
||||
#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
|
||||
(ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
|
||||
(ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
|
||||
@@ -85,8 +90,33 @@ typedef struct {
|
||||
Elf32_Word sh_entsize; /* section entry size */
|
||||
} Elf32_Shdr;
|
||||
|
||||
typedef struct {
|
||||
Elf32_Word p_type;
|
||||
Elf32_Word p_offset;
|
||||
Elf32_Word p_vaddr;
|
||||
Elf32_Word p_paddr;
|
||||
Elf32_Word p_filesz;
|
||||
Elf32_Word p_memsz;
|
||||
Elf32_Word p_flags;
|
||||
Elf32_Word p_align;
|
||||
} Elf32_Phdr;
|
||||
|
||||
#define SHT_NULL 0
|
||||
#define SHT_PROGBITS 1
|
||||
#define SHT_SYMTAB 2
|
||||
#define SHT_STRTAB 3 /* string table section */
|
||||
#define SHT_RELA 4
|
||||
#define SHT_HASH 5
|
||||
#define SHT_DYNAMIC 6
|
||||
#define SHT_NOTE 7
|
||||
#define SHT_NOBITS 8 /* no space section */
|
||||
#define SHT_REL 9
|
||||
#define SHT_SHLIB 10
|
||||
#define SHT_DYNSYM 11
|
||||
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define PT_NOTE 4
|
||||
|
||||
#define SHF_ALLOC 0x2 /* occupies memory */
|
||||
|
||||
|
||||
@@ -1,49 +1,68 @@
|
||||
.section ".elfldr"
|
||||
|
||||
#include <ppc/asm.h>
|
||||
#include <ppc/xenonsprs.h>
|
||||
|
||||
// NOTE: All code in this file is relocated. In order to access any static data,
|
||||
// you must use the offset register r2.
|
||||
|
||||
.globl elf_hold_thread
|
||||
elf_hold_thread:
|
||||
lis %r4,0x87ff
|
||||
lis %r3, elf_secondary_hold_addr@h
|
||||
ori %r3, %r3, elf_secondary_hold_addr@l
|
||||
add %r4,%r4,%r3
|
||||
// r2 = (ELF_CODE_RELOC_START - elfldr_start) (offset to reloc code)
|
||||
lis %r2, 0x87f8 // This must be ELF_CODE_RELOC_START@h
|
||||
lis %r3, elfldr_start@h
|
||||
ori %r3, %r3, elfldr_start@l
|
||||
sub %r4,%r4,%r3
|
||||
sub %r2, %r2, %r3
|
||||
|
||||
1:
|
||||
// or %r1, %r1, %r1 /* low priority */
|
||||
lis %r4, elf_secondary_count@h
|
||||
ori %r4, %r4, elf_secondary_count@l
|
||||
|
||||
/* tell the loader we're here! */
|
||||
1: lwarx %r3, %r2, %r4
|
||||
addi %r3, %r3, 1
|
||||
stwcx. %r3, %r2, %r4
|
||||
bne- 1b
|
||||
|
||||
lis %r3, elf_secondary_hold_addr@h
|
||||
ori %r3, %r3, elf_secondary_hold_addr@l
|
||||
add %r4,%r3,%r2
|
||||
|
||||
2:
|
||||
// or %r1, %r1, %r1 /* low priority */
|
||||
lwz %r3, 0(%r4)
|
||||
cmpwi %r3, 0
|
||||
beq 1b
|
||||
beq 2b
|
||||
|
||||
/* Fall into elf_run. */
|
||||
// or %r2, %r2, %r2
|
||||
li %r4,0
|
||||
|
||||
.globl elf_run
|
||||
elf_run:
|
||||
mr %r31,%r3
|
||||
mr %r30,%r4
|
||||
/* Save arguments for b64 */
|
||||
mr %r31,%r3 // entrypoint
|
||||
mr %r30,%r4 // device tree
|
||||
|
||||
lis %r4,0x07ff
|
||||
lis %r3, b64@h
|
||||
ori %r3, %r3, b64@l
|
||||
add %r4,%r4,%r3
|
||||
lis %r3, elfldr_start@h
|
||||
ori %r3, %r3, elfldr_start@l
|
||||
sub %r4,%r4,%r3
|
||||
mtsrr0 %r4
|
||||
/* Load the relocated b64 routine and set it as the branch target */
|
||||
lis %r4, 0x07F8 // This must be ELF_CODE_RELOC_START@h
|
||||
lis %r3, b64@h
|
||||
ori %r3, %r3, b64@l
|
||||
add %r4,%r4,%r3
|
||||
lis %r3, elfldr_start@h
|
||||
ori %r3, %r3, elfldr_start@l
|
||||
sub %r4,%r4,%r3
|
||||
mtsrr0 %r4
|
||||
|
||||
/* Clear IR/DR and set 64bits mode */
|
||||
/* Clear IR/DR and set 64bits mode */
|
||||
mfmsr %r3
|
||||
li %r4, 0x30
|
||||
li %r4, 0x30
|
||||
andc %r3, %r3, %r4
|
||||
lis %r4, 0x8000
|
||||
lis %r4, 0x8000
|
||||
rldicr %r4, %r4, 32, 31
|
||||
or %r3, %r3, %r4
|
||||
or %r3, %r3, %r4
|
||||
mtsrr1 %r3
|
||||
|
||||
/* Return from interrupt because we're swapping to real mode */
|
||||
rfid
|
||||
|
||||
b64:
|
||||
@@ -76,16 +95,26 @@ b64:
|
||||
mfspr %r3, pir /* linux wants thread # in r3 for secondary threads */
|
||||
cmplwi %r3,0
|
||||
bne 1f
|
||||
|
||||
// We're the main thread!
|
||||
mr %r3,%r30
|
||||
1:
|
||||
mr %r4,%r31
|
||||
li %r5,0
|
||||
|
||||
// Kernel entry:
|
||||
// r3 = DT physical pointer
|
||||
// r4 = physical pointer to the kernel
|
||||
|
||||
|
||||
// Entrypoint (from elf_run)
|
||||
mtctr %r31
|
||||
bctr
|
||||
trap
|
||||
|
||||
.globl elf_secondary_hold_addr
|
||||
elf_secondary_hold_addr:
|
||||
.long 0
|
||||
|
||||
.globl elf_secondary_count
|
||||
elf_secondary_count:
|
||||
.long 0
|
||||
@@ -1,21 +1,3 @@
|
||||
#include <pci/io.h>
|
||||
|
||||
uint32_t read32(long addr)
|
||||
{
|
||||
return __builtin_bswap32(*(volatile uint32_t*)addr);
|
||||
}
|
||||
|
||||
uint32_t read32n(long addr)
|
||||
{
|
||||
return *(volatile uint32_t*)addr;
|
||||
}
|
||||
|
||||
void write32(long addr, uint32_t val)
|
||||
{
|
||||
*(volatile uint32_t*)addr = __builtin_bswap32(val);
|
||||
}
|
||||
|
||||
void write32n(long addr, uint32_t val)
|
||||
{
|
||||
*(volatile uint32_t*)addr = val;
|
||||
}
|
||||
|
||||
@@ -3,10 +3,24 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t read32(long addr);
|
||||
uint32_t read32n(long addr);
|
||||
static inline __attribute__((always_inline)) uint32_t read32(long addr)
|
||||
{
|
||||
return __builtin_bswap32(*(volatile uint32_t*)addr);
|
||||
}
|
||||
|
||||
void write32(long addr, uint32_t val);
|
||||
void write32n(long addr, uint32_t val);
|
||||
static inline __attribute__((always_inline)) uint32_t read32n(long addr)
|
||||
{
|
||||
return *(volatile uint32_t*)addr;
|
||||
}
|
||||
|
||||
static inline __attribute__((always_inline)) void write32(long addr, uint32_t val)
|
||||
{
|
||||
*(volatile uint32_t*)addr = __builtin_bswap32(val);
|
||||
}
|
||||
|
||||
static inline __attribute__((always_inline)) void write32n(long addr, uint32_t val)
|
||||
{
|
||||
*(volatile uint32_t*)addr = val;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user