improve loader and add libfdt to it
[rpi-open-firmware.git] / arm_chainloader / loader.cc
1 /*=============================================================================
2 Copyright (C) 2016 Kristina Brooks
3 All rights reserved.
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 FILE DESCRIPTION
16 Second stage bootloader.
17
18 =============================================================================*/
19
20 #include <drivers/fatfs/ff.h>
21 #include <chainloader.h>
22 #include <drivers/mailbox.hpp>
23 #include <libfdt.h>
24 #include <memory_map.h>
25
26 #define logf(fmt, ...) printf("[LDR:%s]: " fmt, __FUNCTION__, ##__VA_ARGS__);
27
28 FATFS g_BootVolumeFs;
29
30 #define ROOT_VOLUME_PREFIX "0:"
31 #define KERNEL_LOAD_ADDRESS 0x2000000
32
33 extern "C" {
34 void boot_linux(int zero, int machineID, void* dtb, void* kernel);
35 }
36
37 static_assert((MEM_USABLE_START+0x800000) < KERNEL_LOAD_ADDRESS,
38 "memory layout would not allow for kernel to be loaded at KERNEL_LOAD_ADDRESS, please check memory_map.h");
39
40 struct LoaderImpl {
41 inline bool file_exists(const char* path) {
42 return f_stat(path, NULL) == FR_OK;
43 }
44
45 bool read_file(const char* path, uint8_t*& dest, size_t& size, bool should_alloc = true) {
46 /* ensure file exists first */
47 if(!file_exists(path))
48 return false;
49
50 /* read entire file into buffer */
51 FIL fp;
52 f_open(&fp, path, FA_READ);
53
54 unsigned int len = f_size(&fp);
55
56 if(should_alloc) {
57 uint8_t* buffer = new uint8_t[len];
58 dest = buffer;
59 }
60
61 logf("%s: reading %d bytes to 0x%X (allocated=%d) ...\n", path, len, (unsigned int)dest, should_alloc);
62
63 size = len;
64
65 f_read(&fp, dest, len, &len);
66 f_close(&fp);
67
68 return true;
69 }
70
71 inline bool read_file(const char* path, uint8_t*& dest, bool should_alloc = true) {
72 size_t size;
73 return read_file(path, dest, size, should_alloc);
74 }
75
76 void* load_fdt(const char* filename, uint8_t* cmdline) {
77 /* read device tree blob */
78 uint8_t* fdt = reinterpret_cast<uint8_t*>(MEM_USABLE_START);
79 size_t sz;
80
81 if(!read_file(filename, fdt, sz, false)) {
82 panic("error reading fdt");
83 }
84
85 int res = fdt_check_header(reinterpret_cast<void*>(fdt));
86 if (res != 0) {
87 panic("fdt blob invalid, fdt_check_header returned %d", res);
88 }
89
90 logf("valid fdt loaded at 0x%X\n", (unsigned int)fdt);
91
92 return reinterpret_cast<void*>(fdt);
93 }
94
95 LoaderImpl() {
96 logf("Mounting boot partitiion ...\n");
97 FRESULT r = f_mount(&g_BootVolumeFs, ROOT_VOLUME_PREFIX, 1);
98 if (r != FR_OK) {
99 panic("failed to mount boot partition, error: %d", (int)r);
100 }
101 logf("Boot partition mounted!\n");
102
103 size_t sz;
104
105 /* dump cmdline.txt for test */
106 uint8_t* cmdline;
107
108 if(!read_file("cmdline.txt", cmdline, sz)) {
109 panic("error reading cmdline");
110 }
111
112 /* nul terminate it */
113 cmdline[sz - 1] = 0;
114 logf("kernel cmdline: %s\n", cmdline);
115
116 /* load flat device tree */
117 void* fdt = load_fdt("rpi.dtb", cmdline);
118 if (!fdt) {
119 panic("fdt pointer is null");
120 }
121
122 /* after load_fdt is done with it, we don't need it anymore */
123 delete[] cmdline;
124
125 /* read the kernel -- necessarily at fixed address */
126 uint8_t* zImage = reinterpret_cast<uint8_t*>(KERNEL_LOAD_ADDRESS);
127
128 if(!read_file("zImage", zImage, false)) {
129 panic("error reading zImage");
130 }
131
132 logf("zImage loaded at 0x%X\n", (unsigned int)zImage);
133 logf("Jumping to the Linux kernel...\n");
134
135 /* this should never return */
136 boot_linux(0, ~0, fdt, zImage);
137 }
138 };
139
140 static LoaderImpl STATIC_APP g_Loader {};
This page took 0.088638 seconds and 5 git commands to generate.