Skip to content

Commit

Permalink
pongoOS 2.4.0
Browse files Browse the repository at this point in the history
AES support including Apple A7.
Kernel changes across the board.
  • Loading branch information
woachk committed Nov 5, 2020
1 parent b5a3474 commit b8bcd34
Show file tree
Hide file tree
Showing 15 changed files with 547 additions and 171 deletions.
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ifeq ($(HOST_OS),Linux)
endif
endif

PONGO_VERSION := 2.3.3-$(shell git log -1 --pretty=format:"%H" | cut -c1-8)
PONGO_VERSION := 2.4.0-$(shell git log -1 --pretty=format:"%H" | cut -c1-8)
ROOT := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SRC := $(ROOT)/src
AUX := $(ROOT)/tools
Expand All @@ -31,8 +31,8 @@ EMBEDDED_LDFLAGS ?= -nostdlib -static -Wl,-fatal_warnings -Wl,-dead_strip
EMBEDDED_CC_FLAGS ?= -Wall -Wunused-label -Werror -O3 -flto -ffreestanding -U__nonnull -nostdlibinc -I$(LIB)/include $(EMBEDDED_LDFLAGS)

# Pongo options
PONGO_LDFLAGS ?= -L$(LIB)/lib -lc -lm -lg -Wl,-preload -Wl,-no_uuid -Wl,-e,start -Wl,-order_file,$(SRC)/sym_order.txt -Wl,-image_base,0x418000000 -Wl,-sectalign,__DATA,__common,0x8
PONGO_CC_FLAGS ?= -DPONGO_VERSION='"$(PONGO_VERSION)"' -DAUTOBOOT -DPONGO_PRIVATE=1 -Djit_alloc=calloc -Djit_free=free -I$(SRC)/lib -I$(INC) -Iapple-include -I$(INC)/linux/ -I$(SRC)/kernel -I$(SRC)/drivers -I$(SRC)/linux/libfdt -I $(LIB)/libDER $(PONGO_LDFLAGS) $(CFLAGS) -DDER_TAG_SIZE=8
PONGO_LDFLAGS ?= -L$(LIB)/lib -lc -lm -lg -Wl,-preload -Wl,-no_uuid -Wl,-e,start -Wl,-order_file,$(SRC)/sym_order.txt -Wl,-image_base,0x100000000 -Wl,-sectalign,__DATA,__common,0x8 -Wl,-segalign,0x4000
PONGO_CC_FLAGS ?= -DPONGO_VERSION='"$(PONGO_VERSION)"' -DAUTOBOOT -DPONGO_PRIVATE=1 -I$(SRC)/lib -I$(INC) -Iapple-include -I$(INC)/linux/ -I$(SRC)/kernel -I$(SRC)/drivers -I$(SRC)/linux/libfdt -I $(LIB)/libDER $(PONGO_LDFLAGS) $(CFLAGS) -DDER_TAG_SIZE=8

STAGE3_ENTRY_C := $(patsubst %, $(SRC)/boot/%, stage3.c clearhook.S patches.S demote_patch.S jump_to_image.S main.c)
PONGO_C := $(wildcard $(SRC)/kernel/*.c) $(wildcard $(SRC)/kernel/support/*.c) $(wildcard $(SRC)/dynamic/*.c) $(wildcard $(SRC)/kernel/*.S) $(wildcard $(SRC)/shell/*.c)
Expand Down
14 changes: 11 additions & 3 deletions src/boot/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,8 @@ start$l0:
mov x1, x0
mov x0, x9
mov x29, xzr
sub x5, x5, #0x400
and x5, x5, #~0xf
bl _set_exception_stack_core0
mov sp, x5
bl _set_execution_stack_core0
bl _trampoline_entry
b .

Expand Down Expand Up @@ -117,6 +115,16 @@ _set_exception_stack_core0:
msr spsel, #0
ret

.globl _set_execution_stack_core0
_set_execution_stack_core0:
msr spsel, #0
adrp x8, _sched_stack@PAGE
add x8, x8, _sched_stack@PAGEOFF
add x8, x8, #0x4000
and x8, x8, #~0xf
mov sp, x8
ret

.globl _smemcpy128
_smemcpy128:
cbz w2, nullsub
Expand Down
1 change: 1 addition & 0 deletions src/drivers/aes/aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ void aes_init(void)
case 0x8960:
case 0x7000:
case 0x7001:
aes_a7_init();
aes_impl = &aes_a7;
break;
case 0x8000:
Expand Down
138 changes: 137 additions & 1 deletion src/drivers/aes/aes_a7.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,147 @@
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <pongo.h>

#include "aes.h"
#include "aes_private.h"

static uintptr_t gAESBase;
static uint64_t gAESClockAddr;

#define rAES_CTL *(volatile uint32_t*)(gAESBase + 0x008)
#define rAES_IN_STS *(volatile uint32_t*)(gAESBase + 0x00c)
#define rAES_INPUT(n) *(volatile uint32_t*)(gAESBase + 0x040 + ((n) << 2))
#define rAES_OUT_STS *(volatile uint32_t*)(gAESBase + 0x050)
#define rAES_OUTPUT(n) *(volatile uint32_t*)(gAESBase + 0x080 + ((n) << 2))
#define rAES_KEY_CTL *(volatile uint32_t*)(gAESBase + 0x090)
#define rAES_KEY_WORD(n) *(volatile uint32_t*)(gAESBase + 0x0c0 + ((n) << 2))
#define rAES_IV_CTL *(volatile uint32_t*)(gAESBase + 0x0e0)
#define rAES_IV_WORD(n) *(volatile uint32_t*)(gAESBase + 0x100 + ((n) << 2))

void aes_a7_init(void)
{
gAESBase = gIOBase + 0x0a108000;
switch(socnum)
{
case 0x8960:
gAESClockAddr = gIOBase + 0x0e020100;
break;
case 0x7000:
case 0x7001:
gAESClockAddr = gIOBase + 0x0e0201e8;
break;
default:
panic("AES A7: counterfeit init call");
}
}

int aes_a7(uint32_t op, const void *src, void *dst, size_t len, const void *iv, const void *key)
{
return ENOSYS; // TODO
if(len < 0x10 || (len & 0xf))
{
panic("AES A7: Invalid data length");
}
const uint32_t *u32_key = key,
*u32_iv = iv,
*u32_src = src;
uint32_t *u32_dst = dst;
uint32_t keyid, bits, encrypt, mode;
switch(op & AES_KEY_MASK)
{
case AES_USER_KEY: keyid = 0; break;
case AES_UID: keyid = 1; break;
case AES_GID0: keyid = 2; break;
case AES_GID1: keyid = 3; break;
// Add default case if we ever change key mask
}
switch(op & AES_BITS_MASK)
{
case AES_128: bits = 0; break;
case AES_192: bits = 1; break;
case AES_256: bits = 2; break;
default: panic("AES A9: Invalid key length");
}
switch(op & AES_MODE_MASK)
{
case AES_ENCRYPT: encrypt = 1; break;
case AES_DECRYPT: encrypt = 0; break;
}
switch(op & AES_CIPHER_MASK)
{
case AES_CBC: mode = 1; break;
case AES_ECB: mode = 0; break;
}
uint32_t keysel = (mode << 13) | (encrypt << 12) | (bits << 6) | (keyid << 4);

clock_gate(gAESClockAddr, 1);

// Set key
if((op & AES_KEY_MASK) == AES_USER_KEY)
{
rAES_KEY_WORD(0) = u32_key[0];
rAES_KEY_WORD(1) = u32_key[1];
rAES_KEY_WORD(2) = u32_key[2];
rAES_KEY_WORD(3) = u32_key[3];
if(bits > 0)
{
rAES_KEY_WORD(4) = u32_key[4];
rAES_KEY_WORD(5) = u32_key[5];
if(bits > 1)
{
rAES_KEY_WORD(6) = u32_key[6];
rAES_KEY_WORD(7) = u32_key[7];
}
}
}
rAES_KEY_CTL = keysel | 1;

// Set IV
if(u32_iv)
{
rAES_IV_WORD(0) = u32_iv[0];
rAES_IV_WORD(1) = u32_iv[1];
rAES_IV_WORD(2) = u32_iv[2];
rAES_IV_WORD(3) = u32_iv[3];
}
else
{
rAES_IV_WORD(0) = 0;
rAES_IV_WORD(1) = 0;
rAES_IV_WORD(2) = 0;
rAES_IV_WORD(3) = 0;
}
rAES_IV_CTL = 1;

// AES block loop
for(size_t off = 0; off < len; off += 0x10)
{
// Wait for ready
while((rAES_IN_STS & 0x1) != 0x1) {}

// Load input
rAES_INPUT(0) = u32_src[0];
rAES_INPUT(1) = u32_src[1];
rAES_INPUT(2) = u32_src[2];
rAES_INPUT(3) = u32_src[3];

// Clock
rAES_CTL = 1;

// Wait for completion
while((rAES_OUT_STS & 0x1) != 0x1) {}

// Store output
u32_dst[0] = rAES_OUTPUT(0);
u32_dst[1] = rAES_OUTPUT(1);
u32_dst[2] = rAES_OUTPUT(2);
u32_dst[3] = rAES_OUTPUT(3);

u32_src += 4;
u32_dst += 4;
}

clock_gate(gAESClockAddr, 0);

return 0;
}
1 change: 1 addition & 0 deletions src/drivers/aes/aes_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <stdint.h>

void aes_init(void);
void aes_a7_init(void);
void aes_a9_init(void);
int aes_a7(uint32_t op, const void *src, void *dst, size_t len, const void *iv, const void *key);
int aes_a9(uint32_t op, const void *src, void *dst, size_t len, const void *iv, const void *key);
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/usb/synopsys_otg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1448,7 +1448,7 @@ ep0_out_interrupt() {
if (is_setup) {
// We've received a setup packet.

spin(4); // this is required because this interrupt is asserted *before* the DMA transfer is complete on some devices.. ugh
spin(2); // this is required because this interrupt is asserted *before* the DMA transfer is complete on some devices.. ugh
struct setup_packet *setup = ep_out_recv_setup_done(&ep0_out);
ep0.setup_packet = *setup;

Expand Down
23 changes: 23 additions & 0 deletions src/dynamic/modload.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ struct pongo_exports public_api[] = {
EXPORT_SYMBOL(hexdump),
EXPORT_SYMBOL(memcmp),
EXPORT_SYMBOL(map_range),
EXPORT_SYMBOL(linear_kvm_alloc),
EXPORT_SYMBOL(vm_flush_by_addr_all_asid),
EXPORT_SYMBOL(vatophys_force),
EXPORT_SYMBOL(serial_disable_rx),
EXPORT_SYMBOL(serial_enable_rx),
EXPORT_SYMBOL(__memset_chk),
Expand Down Expand Up @@ -248,3 +251,23 @@ void* resolve_symbol(const char* name) {
iprintf("usbloader-linker could not load this module!!\n");
return 0;
}
static struct pongo_module_info* head;
struct pongo_module_info* pongo_module_create(uint32_t segmentCount) {
struct pongo_module_info* mod = calloc(sizeof (struct pongo_module_info) + sizeof(struct pongo_module_segment_info) * segmentCount, 1);
disable_interrupts();
mod->next = head;
mod->segcount = segmentCount;
head = mod;
enable_interrupts();
return mod;
}
void pongo_module_print_list() {
struct pongo_module_info* cur = head;
while (cur) {
iprintf(" | %26s @ 0x%llx->0x%llx\n", cur->name, cur->vm_base, cur->vm_end);
for (uint32_t i = 0; i < cur->segcount; i++) {
iprintf(" |---> %22s @ 0x%08llx, size 0x%06llx (%s%s%s)\n", cur->segments[i].name, cur->vm_base + cur->segments[i].vm_addr, cur->segments[i].vm_size, cur->segments[i].prot & PROT_READ ? "r" : "-", cur->segments[i].prot & PROT_WRITE ? "w" : "-", cur->segments[i].prot & PROT_EXEC ? "x" : "-");
}
cur = cur->next;
}
}
51 changes: 42 additions & 9 deletions src/dynamic/modload_macho.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ void modload_cmd() {
uint64_t filesz_expected = 0;
uint64_t vmsz_needed = 0;
uint64_t base_vmaddr = -1;
uint32_t segmentCount = 0;
const struct symtab_command *symtab = NULL;
const struct dysymtab_command *dysymtab;
for (int i=0; i<mh->ncmds; i++) {
if (lc->cmd == LC_SEGMENT_64) {
segmentCount++;
struct segment_command_64 * sg = (struct segment_command_64*) lc;
//iprintf("found %s, vmaddr %llx, vmsz %llx, fileoff %llx, filesize %llx\n", sg->segname, sg->vmaddr, sg->vmsize, sg->fileoff, sg->filesize);
if (sg->vmaddr < base_vmaddr) base_vmaddr = sg->vmaddr;
Expand All @@ -64,17 +66,43 @@ void modload_cmd() {
//iprintf("need %llx, got %llx\n", filesz_expected, loader_xfer_recv_count);
if (!(filesz_expected > loader_xfer_recv_count)) {
uint64_t entrypoint;
uint8_t * allocto = alloc_contig(vmsz_needed);
uint8_t * allocto = alloc_contig((vmsz_needed + 0x3FFF) & ~0x3FFF);
uint64_t vma_base = linear_kvm_alloc(vmsz_needed);
struct pongo_module_info* module = pongo_module_create(segmentCount);
module->vm_base = vma_base;
module->vm_end = vma_base + vmsz_needed;
uint32_t segmentIndex = 0;

//iprintf("need vm %llx, got %p, base %llx\n", vmsz_needed, allocto, base_vmaddr);
struct load_command* lc = (struct load_command*) (mh + 1);
for (int i=0; i<mh->ncmds; i++) {
if (lc->cmd == LC_SEGMENT_64) {
struct segment_command_64 * sg = (struct segment_command_64*) lc;
memset(allocto + sg->vmaddr, 0, sg->vmsize);
memcpy(allocto + sg->vmaddr, loader_xfer_recv_data + sg->fileoff, sg->filesize);
struct pongo_module_segment_info* info = &module->segments[segmentIndex++];
info->name = strdup(sg->segname);
info->vm_addr = sg->vmaddr;
info->vm_size = sg->vmsize;

memset(allocto + sg->vmaddr - base_vmaddr, 0, sg->vmsize);
memcpy(allocto + sg->vmaddr - base_vmaddr, loader_xfer_recv_data + sg->fileoff, sg->filesize);

vm_protect_t prots = 0;
prots |= sg->initprot & VM_PROT_READ ? PROT_READ : 0;
prots |= sg->initprot & VM_PROT_WRITE ? PROT_WRITE : 0;
prots |= sg->initprot & VM_PROT_EXECUTE ? PROT_EXEC : 0;

info->prot = prots;

for (uint32_t page = 0; page < sg->vmsize; page += PAGE_SIZE) {
//fiprintf(stderr, "mapping %llx (%llx, %llx), %x\n", vma_base + page + sg->vmaddr - base_vmaddr, sg->vmaddr, sg->vmsize, prots);
uint64_t ppage = vatophys((uint64_t)(allocto + page + sg->vmaddr - base_vmaddr));
vm_space_map_page_physical_prot(&kernel_vm_space, vma_base + page + sg->vmaddr - base_vmaddr, ppage, prots | PROT_KERN_ONLY);
}

}
lc = (struct load_command*)(((char*)lc) + lc->cmdsize);
}

const struct relocation_info *extrel = (void *)((uintptr_t)allocto + dysymtab->extreloff);
const struct relocation_info *locrel = (void *)((uintptr_t)allocto + dysymtab->locreloff);
const struct nlist_64 *nlist = (struct nlist_64 *)((uintptr_t)allocto + symtab->symoff);
Expand All @@ -83,19 +111,19 @@ void modload_cmd() {
for (uint32_t sym_idx = 0; sym_idx < symtab->nsyms; sym_idx++) {
const struct nlist_64 *nl = &nlist[sym_idx];
uint32_t strx = nl->n_un.n_strx;
const char *name = (const char *)((uintptr_t)allocto + symtab->stroff + strx);
const char *name = (const char *)((uintptr_t)vma_base + symtab->stroff + strx);
// Check to see if this is the entry point symbol.
int cmp = strcmp(name, "_module_entry");
if (cmp == 0) {
entrypoint = nl->n_value + (uint64_t)allocto;
entrypoint = nl->n_value + (uint64_t)vma_base;
}
cmp = strcmp(name, "_module_name");
if (cmp == 0) {
modname = (const char**)(nl->n_value + (uint64_t)allocto);
modname = (const char**)(nl->n_value + (uint64_t)vma_base);
}
cmp = strcmp(name, "_exported_symbols");
cmp = strcmp(name, "_exported_symbols");
if (cmp == 0 && !exports) {
exports = (struct pongo_exports*)(nl->n_value + (uint64_t)allocto);
exports = (struct pongo_exports*)(nl->n_value + (uint64_t)vma_base);
}
}
for (uint32_t extrel_idx = 0; extrel_idx < dysymtab->nextrel; extrel_idx++) {
Expand Down Expand Up @@ -135,12 +163,17 @@ void modload_cmd() {
// slide it to the new base address.
uint64_t vmoff = ri->r_address;
uint64_t *reloc_ptr = (uint64_t *)((uintptr_t)allocto + vmoff);
*reloc_ptr = *reloc_ptr - base_vmaddr + ((uint64_t)allocto);
*reloc_ptr = *reloc_ptr - base_vmaddr + ((uint64_t)vma_base);
}
link_exports(exports);
if (!entrypoint) panic("no entryp");

iprintf("[modload_macho:+] Loaded module %s\n", modname ? *modname ? *modname : "<null>" : "<unknown>");
flush_tlb();
invalidate_icache();

module->name = strdup(modname ? *modname ? *modname : "<null>" : "<unknown>");
module->exports = exports;
((void (*)())entrypoint)();
} else puts ("[modload_macho:!] load module: truncated load");
} else puts("[modload_macho:!] load module: need dylib");
Expand Down
Loading

0 comments on commit b8bcd34

Please sign in to comment.