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