diff options
author | Aidan MacDonald <amachronic@protonmail.com> | 2022-03-05 14:28:57 +0000 |
---|---|---|
committer | Aidan MacDonald <amachronic@protonmail.com> | 2022-03-24 23:40:07 +0000 |
commit | 90cb0b0ae541303b3efb5ddbdc2ff8adab26cb49 (patch) | |
tree | 02e2468f8b5da220aab97664481cd485b7e11b35 | |
parent | 53a92f0ecce72ec92084a23a4f22679d2c01e22a (diff) | |
download | rockbox-90cb0b0ae541303b3efb5ddbdc2ff8adab26cb49.tar.gz rockbox-90cb0b0ae541303b3efb5ddbdc2ff8adab26cb49.zip |
x1000: bootloader: add mainline Linux boot option
This adds a *very basic* Linux loader to the Rockbox bootloader,
which allows running a mainline Linux kernel using the following
file layout on the SD card:
- /uImage
- /linux_cmdline.txt
The command line arguments are listed in linux_cmdline.txt, all
lines are concatenated together and whitespace is converted into
spaces. Comments aren't supported however.
The loader doesn't support the modern devicetree boot protocol,
so it can only pass command line arguments. It would be easy to
support an appended dtb though.
Change-Id: I373f465dbbdafe94738f619748cbb0278fc2c25f
-rw-r--r-- | bootloader/x1000/boot.c | 91 | ||||
-rw-r--r-- | bootloader/x1000/recovery.c | 1 | ||||
-rw-r--r-- | bootloader/x1000/x1000bootloader.h | 1 |
3 files changed, 93 insertions, 0 deletions
diff --git a/bootloader/x1000/boot.c b/bootloader/x1000/boot.c index ca69e2e057..153c2277aa 100644 --- a/bootloader/x1000/boot.c +++ b/bootloader/x1000/boot.c | |||
@@ -24,8 +24,11 @@ | |||
24 | #include "system.h" | 24 | #include "system.h" |
25 | #include "kernel.h" | 25 | #include "kernel.h" |
26 | #include "power.h" | 26 | #include "power.h" |
27 | #include "file.h" | ||
27 | #include "linuxboot.h" | 28 | #include "linuxboot.h" |
28 | #include "boot-x1000.h" | 29 | #include "boot-x1000.h" |
30 | #include <ctype.h> | ||
31 | #include <sys/types.h> | ||
29 | 32 | ||
30 | void boot_rockbox(void) | 33 | void boot_rockbox(void) |
31 | { | 34 | { |
@@ -53,6 +56,94 @@ void reboot(void) | |||
53 | } | 56 | } |
54 | 57 | ||
55 | /* | 58 | /* |
59 | * boot_linux() is intended for mainline kernels, and as such it | ||
60 | * should not need any major target-specific modifications. | ||
61 | */ | ||
62 | |||
63 | static int read_linux_args(const char* filename) | ||
64 | { | ||
65 | if(check_disk(false) != DISK_PRESENT) | ||
66 | return -1; | ||
67 | |||
68 | int ret; | ||
69 | |||
70 | size_t max_size; | ||
71 | int handle = core_alloc_maximum("args", &max_size, &buflib_ops_locked); | ||
72 | if(handle <= 0) { | ||
73 | splash(5*HZ, "Out of memory"); | ||
74 | return -2; | ||
75 | } | ||
76 | |||
77 | int fd = open(filename, O_RDONLY); | ||
78 | if(fd < 0) { | ||
79 | splash2(5*HZ, "Can't open args file", filename); | ||
80 | ret = -3; | ||
81 | goto err_free; | ||
82 | } | ||
83 | |||
84 | /* this isn't 100% correct but will be good enough */ | ||
85 | off_t fsize = filesize(fd); | ||
86 | if(fsize < 0 || fsize+1 > (off_t)max_size) { | ||
87 | splash(5*HZ, "Arguments too long"); | ||
88 | ret = -4; | ||
89 | goto err_close; | ||
90 | } | ||
91 | |||
92 | char* buf = core_get_data(handle); | ||
93 | core_shrink(handle, buf, fsize+1); | ||
94 | |||
95 | ssize_t rdres = read(fd, buf, fsize); | ||
96 | close(fd); | ||
97 | |||
98 | if(rdres != (ssize_t)fsize) { | ||
99 | splash(5*HZ, "Can't read args file"); | ||
100 | ret = -5; | ||
101 | goto err_free; | ||
102 | } | ||
103 | |||
104 | /* append a null terminator */ | ||
105 | char* end = buf + fsize; | ||
106 | *end = 0; | ||
107 | |||
108 | /* change all newlines, etc, to spaces */ | ||
109 | for(; buf != end; ++buf) | ||
110 | if(isspace(*buf)) | ||
111 | *buf = ' '; | ||
112 | |||
113 | return handle; | ||
114 | |||
115 | err_close: | ||
116 | close(fd); | ||
117 | err_free: | ||
118 | core_free(handle); | ||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * Provisional linux loading function: kernel is at "/uImage", | ||
124 | * contents of "/linux_cmdline.txt" are used as kernel arguments. | ||
125 | */ | ||
126 | void boot_linux(void) | ||
127 | { | ||
128 | struct uimage_header uh; | ||
129 | size_t img_length; | ||
130 | int handle = load_uimage_file("/uImage", &uh, &img_length); | ||
131 | if(handle < 0) | ||
132 | return; | ||
133 | |||
134 | int args_handle = read_linux_args("/linux_cmdline.txt"); | ||
135 | if(args_handle < 0) { | ||
136 | core_free(handle); | ||
137 | return; | ||
138 | } | ||
139 | |||
140 | x1000_boot_linux(core_get_data(handle), img_length, | ||
141 | (void*)uimage_get_load(&uh), | ||
142 | (void*)uimage_get_ep(&uh), | ||
143 | core_get_data(args_handle)); | ||
144 | } | ||
145 | |||
146 | /* | ||
56 | * WARNING: Original firmware can be finicky. | 147 | * WARNING: Original firmware can be finicky. |
57 | * Be careful when modifying this code. | 148 | * Be careful when modifying this code. |
58 | */ | 149 | */ |
diff --git a/bootloader/x1000/recovery.c b/bootloader/x1000/recovery.c index ffd6151858..de6b3961cd 100644 --- a/bootloader/x1000/recovery.c +++ b/bootloader/x1000/recovery.c | |||
@@ -47,6 +47,7 @@ static const struct menuitem recovery_items[] = { | |||
47 | #ifdef OF_RECOVERY_NAME | 47 | #ifdef OF_RECOVERY_NAME |
48 | {MENUITEM_ACTION, OF_RECOVERY_NAME, &boot_of_recovery}, | 48 | {MENUITEM_ACTION, OF_RECOVERY_NAME, &boot_of_recovery}, |
49 | #endif | 49 | #endif |
50 | {MENUITEM_ACTION, "Linux", &boot_linux}, | ||
50 | {MENUITEM_HEADING, "System", NULL}, | 51 | {MENUITEM_HEADING, "System", NULL}, |
51 | {MENUITEM_ACTION, "USB mode", &usb_mode}, | 52 | {MENUITEM_ACTION, "USB mode", &usb_mode}, |
52 | {MENUITEM_ACTION, "Shutdown", &shutdown}, | 53 | {MENUITEM_ACTION, "Shutdown", &shutdown}, |
diff --git a/bootloader/x1000/x1000bootloader.h b/bootloader/x1000/x1000bootloader.h index 88d4e3585b..587a820eaf 100644 --- a/bootloader/x1000/x1000bootloader.h +++ b/bootloader/x1000/x1000bootloader.h | |||
@@ -141,6 +141,7 @@ void bootloader_restore(void); | |||
141 | void boot_rockbox(void); | 141 | void boot_rockbox(void); |
142 | void boot_of_player(void); | 142 | void boot_of_player(void); |
143 | void boot_of_recovery(void); | 143 | void boot_of_recovery(void); |
144 | void boot_linux(void); | ||
144 | void shutdown(void); | 145 | void shutdown(void); |
145 | void reboot(void); | 146 | void reboot(void); |
146 | 147 | ||