wok view linld/stuff/src/TAZBOOT.CPP @ rev 19515

linld: multi initrd support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Tue Nov 22 21:19:01 2016 +0100 (2016-11-22)
parents
children 7f92b23984dc
line source
1 // This file is distributed under GPL
2 //
3 // TAZBOOT main() lives here
5 #include "crtl.h"
6 #include "crtlx.h"
7 #include "common.h"
8 #include "iso9660.h"
10 static void usage()
11 {
12 puts("Usage: tazboot [[@commands]|[kernel=<bzimage>] \
13 [initrd=<rootfs>[,<rootfs2>...]] [bootfrom=<isofile>] ...]\r\n\n\
14 Defaults: tazboot kernel=bzImage auto\r\n\n\
15 Examples for tazboot.cmd:\r\n\n\
16 bootfrom=\\isos\\slitaz-4.0.iso\r\n\
17 kernel=boot/bzImage\r\n\
18 initrd=boot/rootfs4.gz,boot/rootfs3.gz,boot/rootfs2.gz,boot/rootfs1.gz,\\slitaz\\extrafs.gz\r\n\
19 rw root=/dev/null vga=normal autologin\r\n\n\
20 kernel=\\slitaz\\elks\r\n\
21 root=/dev/bda1 ro\r\n");
22 exit(1);
23 }
25 #define MAXINITRD 10
26 static struct initrd_state {
27 u32 ofs[MAXINITRD];
28 u32 size[MAXINITRD];
29 u16 cnt;
30 } initrd_state;
32 static void next_chunk(struct image_himem *m)
33 {
34 m->chunk_size = 0;
35 if (m->state >= initrd_state.cnt) return;
36 lseek(m->fd,initrd_state.ofs[m->state],SEEK_SET);
37 m->chunk_size = initrd_state.size[m->state];
38 m->state++;
39 }
41 static void addinitrd()
42 {
43 if (initrd_state.cnt >= MAXINITRD) return;
44 initrd_state.size[initrd_state.cnt] = isofilesize;
45 initrd_state.ofs[initrd_state.cnt] = isofileofs;
46 initrd_state.cnt++;
47 initrd.size += (isofilesize+3)&-4;
48 }
50 static void load_initrds()
51 {
52 if (!initrd.size) return;
53 initrd.next_chunk = next_chunk;
54 initrd.fd = isofd;
55 initrd.state = 0;
56 next_chunk(&initrd);
57 load_initrd();
58 }
60 static void pm_next_chunk(struct image_himem *m)
61 {
62 if (!m->state++) m->chunk_size = m->size;
63 }
65 static void isokernel()
66 {
67 pm.size = (isofilesize+3)&-4;
68 pm.fd = isofd;
69 pm.next_chunk = pm_next_chunk;
70 }
72 char _cmdline[256];
73 const char *cmdline = (const char *) _cmdline;
74 extern int skip_xmmalloc;
75 static void bootiso(char **iso)
76 {
77 char *init = " rdinit=/init.exe", *mode="menu";
78 char *s, c, rootfs[16], fallback[16];
79 int restart, isknoppix = 0;
80 unsigned long magic;
82 if (!*iso || isoreset(*iso) < 0) return;
83 skip_xmmalloc++;
84 isoopen("boot") >= 0 ||
85 isoopen("live") >= 0 || // debian
86 isoopen("casper") >= 0; // ubuntu
87 if (iso[1] && !strcmp(mode = iso[1], "text"))
88 init = "";
89 do {
90 if (isoopen(mode) >= 0 || // custom
91 isoopen("bzImage") >= 0 || // SliTaz
92 isoopen("vmlinuz") >= 0 || // misc
93 (isoopen("linux") >= 0 && ++isknoppix)) {
94 isokernel();
95 magic = kver2ul(load_kernel());
96 break;
97 }
98 } while (isoopen("isolinux") >= 0); // Knoppix
99 fallback[0] = 0;
100 for (c = 0, restart = 1; isoreaddir(restart) == 0; restart = 0) {
101 if (strstr(isofilename, ".gz"))
102 strcpy(fallback, isofilename);
103 if (strhead(isofilename, "rootfs")
104 || c > isofilename[6]) continue;
105 strcpy(rootfs, isofilename);
106 c = isofilename[6];
107 }
109 strcpy(_cmdline,"rw root=/dev/null autologin bootfrom=");
110 strcat(_cmdline,*iso);
111 if (magic < 0x20630)
112 init = ""; // Does not support multiple initramfs
114 if (magic > 0) {
115 char *initrd = fallback;
117 if (rootfs[0]) {
118 initrd = rootfs;
119 if (rootfs[6] != '.' && isoopen("rootfs.gz") >= 0)
120 addinitrd(); // for loram
121 }
122 if (isoopen(initrd) >= 0) {
123 addinitrd();
124 }
125 if (*init && lseek(isofd, 20L, SEEK_SET) != -1 &&
126 read(isofd, &isofileofs, 4) == 4 &&
127 read(isofd, &magic, 4) == 4) {
128 isofileofs &= 0xFFFFL;
129 isofilesize = magic & 0xFFFFL;
130 isofileofs -= 0xC0L + isofilesize;
131 if (isofilesize) addinitrd();
132 else init="";
133 }
134 load_initrds();
135 strcat(_cmdline,init);
136 strcat(_cmdline," mode=");
137 strcat(_cmdline,mode);
138 strcat(_cmdline," magic=");
139 strcat(_cmdline,ultoa(magic));
140 }
141 if (isknoppix) {
142 if (iso[0][1] == ':')
143 *iso += 2;
144 for (s = *iso; *s; s++)
145 if (*s == '\\') *s = '/';
146 }
147 close(isofd);
148 boot_kernel();
149 }
151 u16 root_dev;
152 u16 vid_mode;
153 const char* kernel_name = "bzImage";
154 const char* initrd_name;
155 int main(int argc, char *argv[])
156 {
157 char *iso = NULL;
158 argv[0] = progname();
159 bootiso(argv); // iso ? parsing is /init.exe stuff !
160 if (argc >= 2)
161 bootiso(argv + 1);
163 chdirname(*argv);
164 if (argc < 2) {
165 dousage:
166 usage();
167 }
168 for (int i=1; i < argc; i++) {
169 char *s=argv[i];
170 if (strhead(s,"kernel=") == 0)
171 kernel_name = s + 7;
172 if (strhead(s,"image=") == 0)
173 kernel_name = s + 6;
174 else if (strhead(s,"initrd=") == 0)
175 initrd_name = s + 7;
176 else if (strhead(s,"bootfrom=") == 0)
177 iso = s + 9;
178 else if (strhead(s,"iso=") == 0)
179 iso = s + 4;
180 else if(strhead(s,"vga=") == 0) {
181 s+=4;
182 const char c = *s|0x20;
183 if (c == 'a') vid_mode = -3;
184 else if (c == 'e') vid_mode = -2;
185 else if (c == 'n') vid_mode = -1;
186 else vid_mode = strtol(s);
187 }
188 else if(strhead(s,"-f") == 0) {
189 skip_xmmalloc++;
190 }
191 else {
192 if(strhead(s,"root=") == 0) {
193 root_dev = strtol(s+5);
194 }
195 if(strhead(s,"mem=") == 0) {
196 topmem = strtol(s+4);
197 }
198 if (_cmdline[0]) strcat(_cmdline," ");
199 strcat(_cmdline,s);
200 }
201 }
202 if (iso && isoreset(iso) >= 0) {
203 char *s = (char *) initrd_name;
204 if (isoopen((char *) kernel_name) >= 0) {
205 isokernel();
206 load_kernel();
207 }
208 if (s) {
209 while (*s) {
210 char *p, c;
211 for (p = s; *s && *s != ','; s++);
212 c = *s; *s = 0;
213 if (isoopen(p) >= 0) {
214 addinitrd();
215 }
216 *s = c;
217 if (c) s++;
218 }
219 load_initrds();
220 }
221 }
222 else {
223 load_kernel();
224 load_initrd();
225 }
226 boot_kernel();
227 return _AX;
228 }