diff --git a/loader/heap.c b/loader/heap.c
new file mode 100755
index 0000000..c90607b
--- /dev/null
+++ b/loader/heap.c
@@ -0,0 +1,133 @@
+/*
+* Copyright (c) 2018 naehrwert
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms and conditions of the GNU General Public License,
+* version 2, as published by the Free Software Foundation.
+*
+* This program is distributed in the hope it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see .
+*/
+
+#include
+#include "heap.h"
+
+typedef struct _hnode
+{
+ int used;
+ u32 size;
+ struct _hnode *prev;
+ struct _hnode *next;
+} hnode_t;
+
+typedef struct _heap
+{
+ u32 start;
+ hnode_t *first;
+} heap_t;
+
+static void _heap_create(heap_t *heap, u32 start)
+{
+ heap->start = start;
+ heap->first = NULL;
+}
+
+static u32 _heap_alloc(heap_t *heap, u32 size)
+{
+ hnode_t *node, *new;
+ int search = 1;
+
+ size = ALIGN(size, 0x10);
+
+ if (!heap->first)
+ {
+ node = (hnode_t *)heap->start;
+ node->used = 1;
+ node->size = size;
+ node->prev = NULL;
+ node->next = NULL;
+ heap->first = node;
+
+ return (u32)node + sizeof(hnode_t);
+ }
+
+ node = heap->first;
+ while (search)
+ {
+ if (!node->used && size + sizeof(hnode_t) < node->size)
+ {
+ new = (hnode_t *)((u32)node + sizeof(hnode_t) + size);
+
+ new->size = node->size - sizeof(hnode_t) - size;
+ node->size = size;
+ node->used = 1;
+ new->used = 0;
+ new->next = node->next;
+ new->prev = node;
+ node->next = new;
+
+ return (u32)node + sizeof(hnode_t);
+ }
+ if (node->next)
+ node = node->next;
+ else
+ search = 0;
+ }
+
+ new = (hnode_t *)((u32)node + sizeof(hnode_t) + node->size);
+ new->used = 1;
+ new->size = size;
+ new->prev = node;
+ new->next = NULL;
+ node->next = new;
+
+ return (u32)new + sizeof(hnode_t);
+}
+
+static void _heap_free(heap_t *heap, u32 addr)
+{
+ hnode_t *node = (hnode_t *)(addr - sizeof(hnode_t));
+ node->used = 0;
+ node = heap->first;
+ while (node)
+ {
+ if (!node->used)
+ if (node->prev && !node->prev->used)
+ {
+ node->prev->size += node->size + sizeof(hnode_t);
+ node->prev->next = node->next;
+ if (node->next)
+ node->next->prev = node->prev;
+ }
+ node = node->next;
+ }
+}
+
+static heap_t _heap;
+
+void heap_init(u32 base)
+{
+ _heap_create(&_heap, base);
+}
+
+void *malloc(u32 size)
+{
+ return (void *)_heap_alloc(&_heap, size);
+}
+
+void *calloc(u32 num, u32 size)
+{
+ void *res = (void *)_heap_alloc(&_heap, num * size);
+ memset(res, 0, num * size);
+ return res;
+}
+
+void free(void *buf)
+{
+ _heap_free(&_heap, (u32)buf);
+}
diff --git a/loader/heap.h b/loader/heap.h
new file mode 100755
index 0000000..e1ab6fa
--- /dev/null
+++ b/loader/heap.h
@@ -0,0 +1,27 @@
+/*
+* Copyright (c) 2018 naehrwert
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms and conditions of the GNU General Public License,
+* version 2, as published by the Free Software Foundation.
+*
+* This program is distributed in the hope it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see .
+*/
+
+#ifndef _HEAP_H_
+#define _HEAP_H_
+
+#include "types.h"
+
+void heap_init(u32 base);
+void *malloc(u32 size);
+void *calloc(u32 num, u32 size);
+void free(void *buf);
+
+#endif
diff --git a/loader/main.c b/loader/main.c
index 2ca9763..52c30e7 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -29,6 +29,7 @@
#include "pinmux.h"
#include "gpio.h"
#include "i2c.h"
+#include "uart.h"
static inline u32 read32(uintptr_t addr) {
return *(vu32 *)addr;
@@ -62,30 +63,30 @@ void enter_rcm() {
void config_hw(){
- printf_("Starting Initing hardware.");
+ printf_("Starting Initing hardware.\n");
fuse_disable_program();
printf_("[x] fuse program disabled\n");
- // Initialize counters, CLKM, BPMP(also called AVP in T124/T132) and other clocks based on 38.4MHz oscillator.
+ // Initialize oscillators
config_oscillators();
+ // My board didn't have UART port
+ // pinmux_config_uart(UART_D);
+ // clock_enable_uart(UART_D);
+ // uart_init(UART_D, 115200, UART_AO_TX_AO_RX);
+ // uart_invert(UART_D, 0, UART_INVERT_TXD);
+
+ uart_send(UART_D, (u8 *)"hekate: Hello!\r\n", 16);
+ uart_wait_xfer(UART_D, UART_TX_IDLE);
+
mc_enable();
printf_("[x] mc setup\n");
config_gpios();
printf_("[x] GPIO setup\n");
-
- //clock_enable_cl_dvfs();
- //printf_("[x] DVFS setup\n");
-
- //FIXME I2C Doesn't work!!!
- printf_("Fixme.I2C doesn't work");
- // clock_enable_i2c(I2C_1);
- // clock_enable_i2c(I2C_5);
-
}
-
+extern void pivot_stack(u32 stack_top);
__attribute__((section(".init")))
void _start() {
// u8 *buffer = (u8*)0x40020000;
@@ -98,6 +99,14 @@ void _start() {
dump_pkc();
config_hw();
+ //FIXME!!!->init memory
+ //Pivot the stack so we have enough space.
+// pivot_stack(0x40000000);
+
+ //Tegra/Horizon configuration goes to 0x80000000+, package2 goes to 0xA9800000, we place our heap in between.
+// heap_init(0x90020000);
+
+
enter_rcm();
}
diff --git a/loader/mc.c b/loader/mc.c
index e4c4962..c55ed4a 100644
--- a/loader/mc.c
+++ b/loader/mc.c
@@ -20,7 +20,25 @@
#include "util.h"
#include "mc.h"
+void mc_enable_ahb_redirect()
+{
+ CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) = CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) & 0xFFF7FFFF | 0x80000;
+ //MC(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE;
+ MC(MC_IRAM_BOM) = 0x40000000;
+ MC(MC_IRAM_TOM) = 0x4003F000;
+}
+
void mc_enable()
{
+ CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF | 0x40000000;
+ //Enable MC clock.
+ CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFFFFFFFE | 1;
+ //Enable EMC DLL clock.
+ CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & 0xFFFFBFFF | 0x4000;
+ CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x2000001; //Clear EMC and MC reset.
+ sleep(5);
+
+ //Enable ahb redirect
+ mc_enable_ahb_redirect();
}
\ No newline at end of file
diff --git a/loader/mc.h b/loader/mc.h
index 706f104..78b6217 100644
--- a/loader/mc.h
+++ b/loader/mc.h
@@ -15,4 +15,6 @@
* along with this program. If not, see .
*/
+#define MC_IRAM_BOM 0x65c
+#define MC_IRAM_TOM 0x660
void mc_enable();
\ No newline at end of file
diff --git a/loader/stack.S b/loader/stack.S
new file mode 100644
index 0000000..cb91e74
--- /dev/null
+++ b/loader/stack.S
@@ -0,0 +1,20 @@
+/*
+* Copyright (c) 2018 naehrwert
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms and conditions of the GNU General Public License,
+* version 2, as published by the Free Software Foundation.
+*
+* This program is distributed in the hope it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see .
+*/
+.globl pivot_stack
+.type pivot_stack, %function
+pivot_stack:
+ MOV SP, R0
+ BX LR