drivers/BCM2708ArmControl.cc \
drivers/BCM2708ClockDomains.cc \
drivers/BCM2708Gpio.cc \
- BCM2708PlatformStartup.cc
+ BCM2708PlatformStartup.cc \
+ chainloader_inc.s
ARCH = vc4
uint8_t part_ehd; /* end head */\r
uint8_t part_esect; /* end sector */\r
uint8_t part_ecyl; /* end cylinder */\r
+#if 0\r
+ uint16_t part_start_lo; /* absolute starting ... */\r
+ uint16_t part_start_hi; /* ... sector number */\r
+ uint16_t part_size_lo; /* partition size ... */\r
+ uint16_t part_size_hi; /* ... in sectors */\r
+#endif\r
uint32_t part_start;\r
uint32_t part_size;\r
} __attribute__((packed));\r
uint16_t mbr_sig;\r
} __attribute__((packed));\r
\r
+static_assert(sizeof(Mbr) >= 512, "What the fuck");\r
+\r
#define MBR_FAT16 0x04\r
#define MBR_FAT32 0x0B\r
#define MBR_FAT32_INT13 0x0C\r
#define MBR_LINUX 0x83\r
#define MBR_NTFS 0x07\r
\r
+static const char* mbr_fs_to_string(int fs) {\r
+ switch (fs) {\r
+ case MBR_FAT32:\r
+ return "FAT32";\r
+ case MBR_FAT32_INT13:\r
+ return "FAT32-INT13";\r
+ case MBR_FAT16_INT13:\r
+ return "FAT16-INT13";\r
+ case MBR_FAT16:\r
+ return "FAT16";\r
+ case MBR_LINUX:\r
+ return "Linux (ext2/ext3)";\r
+ case MBR_NTFS:\r
+ return "NTFS";\r
+ default:\r
+ return "<Unknown>";\r
+ }\r
+}\r
+\r
struct MbrImpl {\r
Mbr* mbr;\r
BlockDevice* mmc;\r
void read_mbr() {\r
logf("Reading master boot record ...\n");\r
\r
- if (!mmc->read_block(0, mbr))\r
+ if (!mmc->read_block(0, mbr)) {\r
panic("unable to read master boot record from the SD card");\r
+ }\r
\r
- if (!validate_signature())\r
+ if (!validate_signature()) {\r
panic("invalid master boot record signature (got 0x%x)", mbr->mbr_sig);\r
+ }\r
+\r
+ logf("MBR contents:\n");\r
+\r
+ for (int i = 0; i < 4; i++) {\r
+ MbrPartition& p = mbr->mbr_part[i];\r
+ printf(" %d: %s at:%d size:%d\n", i, mbr_fs_to_string(p.part_typ), p.part_start, p.part_size);\r
+ }\r
}\r
\r
MbrImpl() {\r
mbr = new Mbr;\r
mmc = get_sdhost_device();\r
- if (!mmc)\r
+ if (!mmc) {\r
panic("parent block device not initilalized!");\r
-\r
+ }\r
read_mbr();\r
logf("Disk ready!\n");\r
}\r
}\r
\r
void configure_pinmux() {\r
- logf("configuring pinmux ...\n");\r
-\r
GP_FSEL4 = 0x24000000;\r
GP_FSEL5 = 0x924;\r
\r
+ logf("waiting for pinmux pull update ...\n");\r
+\r
GP_PUD = 2;\r
mfence();\r
udelay(500);\r
GP_PUD = 0;\r
\r
- /* are these in bank 1 or 2? */\r
+ logf("waiting for pinmux clock update ...\n");\r
+\r
+ /* are these in bank 1 or 2? ah who gives a fuck ... */\r
GP_PUDCLK1 = GP_PUDCLK1_PUDCLKn32_SET;\r
GP_PUDCLK2 = GP_PUDCLK2_PUDCLKn64_SET;\r
udelay(500);\r
\r
+ logf("ok ...\n");\r
GP_PUDCLK1 = 0;\r
GP_PUDCLK2 = 0;\r
\r
\r
get_response();\r
\r
+ //printf("Cmd: 0x%x Resp: %08x %08x %08x %08x\n", current_cmd, r[0], r[1], r[2], r[3]);\r
+\r
if (SH_CMD & SH_CMD_FAIL_FLAG_SET) {\r
if (SH_HSTS & SDHSTS_ERROR_MASK) {\r
logf("ERROR: sdhost status: 0x%x\n", SH_HSTS);\r
\r
logf("SD card has arrived!\n", r);\r
\r
+ is_high_capacity = (r[0] & MMC_OCR_HCS) == MMC_OCR_HCS;\r
+\r
+ if (is_high_capacity)\r
+ logf("This is an SDHC card!\n");\r
+\r
return true;\r
\r
}\r
return false;\r
rca = SD_R6_RCA(r);\r
\r
+ logf("RCA = 0x%x\n", rca);\r
+\r
send_136_resp(MMC_SEND_CID, MMC_ARG_RCA(rca));\r
if (!wait_and_get_response())\r
return false;\r
return true;\r
}\r
\r
+//#define DUMP_READ\r
+\r
bool wait_for_fifo_data(uint32_t timeout = 100000) {\r
uint32_t t = timeout;\r
\r
while ((SH_HSTS & SH_HSTS_DATA_FLAG_SET) == 0) {\r
if (t == 0) {\r
putchar('\n');\r
- logf("ERROR: no FIFO data, timed out after %dus!\n", timeout);\r
+ logf("ERROR: no FIFO data, timed out after %dus!\n", timeout)\r
return false;\r
}\r
t--;\r
}\r
\r
void drain_fifo() {\r
+ /* fuck me with a rake ... gently */\r
+\r
wait();\r
\r
while (SH_HSTS & SH_HSTS_DATA_FLAG_SET) {\r
/* drain useful data from FIFO */\r
for (i = 0; i < 128; i++) {\r
/* wait for FIFO */\r
- if (!wait_for_fifo_data())\r
+ if (!wait_for_fifo_data()) {\r
break;\r
+ }\r
\r
uint32_t hsts_err = SH_HSTS & SDHSTS_ERROR_MASK;\r
if (hsts_err) {\r
bool select_card() {\r
send(MMC_SELECT_CARD, MMC_ARG_RCA(rca));\r
\r
- return wait();\r
+ if (!wait())\r
+ return false;\r
+\r
+ return true;\r
}\r
\r
bool init_card() {\r
void restart_controller() {\r
is_sdhc = false;\r
\r
+ logf("hcfg 0x%X, cdiv 0x%X, edm 0x%X, hsts 0x%X\n",\r
+ SH_HCFG,\r
+ SH_CDIV,\r
+ SH_EDM,\r
+ SH_HSTS);\r
+\r
logf("Restarting the eMMC controller ...\n");\r
\r
configure_pinmux();\r
if (init_card()) {\r
card_ready = true;\r
\r
- /* work around quirk / silicon bug */\r
- for (int i = 0; i < 3; i++)\r
- if (!read_block(0, nullptr))\r
+ /*\r
+ * looks like a silicon bug to me or a quirk of csd2, who knows\r
+ */\r
+ for (int i = 0; i < 3; i++) {\r
+ if (!read_block(0, nullptr)) {\r
panic("fifo flush cycle %d failed", i);\r
+ }\r
+ }\r
} else {\r
panic("failed to reinitialize the eMMC controller");\r
}\r
\r
BlockDevice* get_sdhost_device() {\r
return &g_SDHostDriver;\r
-}\r
+}
\ No newline at end of file
/* read device tree blob */
uint8_t* fdt = reinterpret_cast<uint8_t*>(DTB_LOAD_ADDRESS);
size_t sz = read_file(filename, fdt, false);
+ logf("FDT loaded at %X\n", (unsigned int) fdt);
void* v_fdt = reinterpret_cast<void*>(fdt);
res = fdt_setprop(v_fdt, node, "bootargs", cmdline, strlen((char*) cmdline) + 1);
- /* pass in a memory map (TODO: don't assume 256MB) */
+ /* pass in a memory map, skipping first meg for bootcode */
int memory = fdt_path_offset(v_fdt, "/memory");
if(memory < 0)
panic("no memory node in fdt");
+ /* start the memory map at 1M/16 and grow continuous for 256M
+ * TODO: does this disrupt I/O? */
+
+ char dtype[] = "memory";
uint8_t memmap[] = { 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x00, 0x00 };
res = fdt_setprop(v_fdt, memory, "reg", (void*) memmap, sizeof(memmap));
+ logf("(valid) fdt loaded at 0x%X\n", (unsigned int)fdt);
+
return fdt;
}
LoaderImpl() {
logf("Mounting boot partitiion ...\n");
- if(f_mount(&g_BootVolumeFs, ROOT_VOLUME_PREFIX, 1) != FR_OK)
- panic("failed to mount boot partition");
+ FRESULT r = f_mount(&g_BootVolumeFs, ROOT_VOLUME_PREFIX, 1);
+ if (r != FR_OK) {
+ panic("failed to mount boot partition, error: %d", (int)r);
+ }
+ logf("Boot partition mounted!\n");
- /* read the command-line */
+ /* read the command-line null-terminated */
uint8_t* cmdline;
- read_file("cmdline.txt", cmdline);
+ size_t cmdlen = read_file("cmdline.txt", cmdline);
+
+ logf("kernel cmdline: %s\n", cmdline);
/* load flat device tree */
uint8_t* fdt = load_fdt("rpi.dtb", cmdline);
linux_t kernel = reinterpret_cast<linux_t>(zImage);
size_t ksize = read_file("zImage", zImage, false);
+ logf("zImage loaded at 0x%X\n", (unsigned int)kernel);
/* flush the cache */
+ logf("Flushing....\n")
for (uint8_t* i = zImage; i < zImage + ksize; i += 32) {
__asm__ __volatile__ ("mcr p15,0,%0,c7,c10,1" : : "r" (i) : "memory");
}
teardown_hardware();
/* fire away -- this should never return */
- logf("Jumping to the kernel...\n");
+ logf("Jumping to the Linux kernel...\n");
kernel(0, ~0, fdt);
}
};
init_memory_pool(hs, start_of_heap);
}
+static const char* get_execution_mode_name() {
+ uint32_t cpsr = arm_get_cpsr() & ARM32_MODE_MASK;
+
+ switch (cpsr) {
+ case ARM32_USR:
+ return "User";
+ case ARM32_FIQ:
+ return "FIQ";
+ case ARM32_IRQ:
+ return "IRQ";
+ case ARM32_SVC:
+ return "Supervisor";
+ case ARM32_MON:
+ return "Secure Monitor";
+ case ARM32_ABT:
+ return "Abort";
+ case ARM32_UND:
+ return "Undefined Instruction";
+ case ARM32_HYP:
+ return "Hypervisor";
+ case ARM32_SYS:
+ return "System";
+ default:
+ return "Unknown Mode";
+ }
+}
+
void main(bool security_supported) {
/* wait for peripheral access */
while(ARM_ID != ARM_IDVAL);
logf("Security extensions are supported!\n");
}
+ logf("Execution mode: %s\n", get_execution_mode_name());
+
heap_init();
/* c++ runtime */
#include <lib/runtime.h>
struct arm_saved_state {
- uint32_t r[13]; /* General purpose register r0-r12 */
- uint32_t sp; /* Stack pointer r13 */
- uint32_t lr; /* Link register r14 */
- uint32_t pc; /* Program counter r15 */
- uint32_t cpsr; /* Current program status register */
- uint32_t fsr; /* Fault status */
- uint32_t far; /* Virtual Fault Address */
- uint32_t exception; /* exception number */
+ uint32_t r[13]; /* General purpose register r0-r12 */
+ uint32_t sp; /* Stack pointer r13 */
+ uint32_t lr; /* Link register r14 */
+ uint32_t pc; /* Program counter r15 */
+ uint32_t cpsr; /* Current program status register */
+ uint32_t fsr; /* Fault status */
+ uint32_t far; /* Virtual Fault Address */
+ uint32_t exception; /* exception number */
};
typedef struct arm_saved_state arm_saved_state_t;
extern "C" void sleh_fiq(arm_saved_state_t* regs) {
fatal_exception(regs, "FIQ");
-}
+}
\ No newline at end of file
setTag('GPIO');
}
-IODriverCreateSingletonInstance(BCM2708Gpio);
+IODriverCreateSingletonInstance(BCM2708Gpio);
\ No newline at end of file
"Booting Raspberry Pi....\n"\r
"Copyright 2016-2017 rpi-open-firmware authors \n"\r
"BUILDATE : %s %s \n",\r
- __DATE__, __TIME__\r
+ __DATE__, __TIME__,\r
);\r
\r
g_CPUID = cpuid;\r
empty_space:
.space 0x200
+/* MMIO-mapped registers for the interrupt table */
+
+.set IC0_BASE, 0x7e002000
+.set IC0_VADDR, 0x7e002030
+
+.set IC1_BASE, 0x7e002800
+.set IC1_VADDR, 0x7e002830
+
/* main entry point */
.globl _start