wok diff 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 diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/linld/stuff/src/TAZBOOT.CPP	Tue Nov 22 21:19:01 2016 +0100
     1.3 @@ -0,0 +1,228 @@
     1.4 +// This file is distributed under GPL
     1.5 +//
     1.6 +// TAZBOOT main() lives here
     1.7 +
     1.8 +#include "crtl.h"
     1.9 +#include "crtlx.h"
    1.10 +#include "common.h"
    1.11 +#include "iso9660.h"
    1.12 +
    1.13 +static void usage()
    1.14 +{
    1.15 +	puts("Usage: tazboot [[@commands]|[kernel=<bzimage>] \
    1.16 +[initrd=<rootfs>[,<rootfs2>...]] [bootfrom=<isofile>] ...]\r\n\n\
    1.17 +Defaults: tazboot kernel=bzImage auto\r\n\n\
    1.18 +Examples for tazboot.cmd:\r\n\n\
    1.19 +  bootfrom=\\isos\\slitaz-4.0.iso\r\n\
    1.20 +  kernel=boot/bzImage\r\n\
    1.21 +  initrd=boot/rootfs4.gz,boot/rootfs3.gz,boot/rootfs2.gz,boot/rootfs1.gz,\\slitaz\\extrafs.gz\r\n\
    1.22 +  rw root=/dev/null vga=normal autologin\r\n\n\
    1.23 +  kernel=\\slitaz\\elks\r\n\
    1.24 +  root=/dev/bda1 ro\r\n");
    1.25 +	exit(1);
    1.26 +}
    1.27 +
    1.28 +#define MAXINITRD 10
    1.29 +static struct initrd_state {
    1.30 +	u32 ofs[MAXINITRD];
    1.31 +	u32 size[MAXINITRD];
    1.32 +	u16 cnt;
    1.33 +} initrd_state;
    1.34 +
    1.35 +static void next_chunk(struct image_himem *m)
    1.36 +{
    1.37 +	m->chunk_size = 0;
    1.38 +	if (m->state >= initrd_state.cnt) return;
    1.39 +	lseek(m->fd,initrd_state.ofs[m->state],SEEK_SET);
    1.40 +	m->chunk_size = initrd_state.size[m->state];
    1.41 +	m->state++;
    1.42 +}
    1.43 +
    1.44 +static void addinitrd()
    1.45 +{
    1.46 +	if (initrd_state.cnt >= MAXINITRD) return;
    1.47 +	initrd_state.size[initrd_state.cnt] = isofilesize;
    1.48 +	initrd_state.ofs[initrd_state.cnt] = isofileofs;
    1.49 +	initrd_state.cnt++;
    1.50 +	initrd.size += (isofilesize+3)&-4;
    1.51 +}
    1.52 +
    1.53 +static void load_initrds()
    1.54 +{
    1.55 +	if (!initrd.size) return;
    1.56 +	initrd.next_chunk = next_chunk;
    1.57 +	initrd.fd = isofd;
    1.58 +	initrd.state = 0;
    1.59 +	next_chunk(&initrd);
    1.60 +	load_initrd();
    1.61 +}
    1.62 +
    1.63 +static void pm_next_chunk(struct image_himem *m)
    1.64 +{
    1.65 +	if (!m->state++) m->chunk_size = m->size;
    1.66 +}
    1.67 +
    1.68 +static void isokernel()
    1.69 +{
    1.70 +	pm.size = (isofilesize+3)&-4;
    1.71 +	pm.fd = isofd;
    1.72 +	pm.next_chunk = pm_next_chunk;
    1.73 +}
    1.74 +
    1.75 +char _cmdline[256];
    1.76 +const char *cmdline = (const char *) _cmdline;
    1.77 +extern int skip_xmmalloc;
    1.78 +static void bootiso(char **iso)
    1.79 +{
    1.80 +	char *init = " rdinit=/init.exe", *mode="menu";
    1.81 +	char *s, c, rootfs[16], fallback[16];
    1.82 +	int restart, isknoppix = 0;
    1.83 +	unsigned long magic;
    1.84 +	
    1.85 +	if (!*iso || isoreset(*iso) < 0) return;
    1.86 +	skip_xmmalloc++;
    1.87 +	isoopen("boot") >= 0 ||
    1.88 +	isoopen("live") >= 0 ||	// debian
    1.89 +	isoopen("casper") >= 0;	// ubuntu
    1.90 +	if (iso[1] && !strcmp(mode = iso[1], "text"))
    1.91 +		init = "";
    1.92 +	do {
    1.93 +		if (isoopen(mode) >= 0		||	// custom
    1.94 +		    isoopen("bzImage") >= 0	|| 	// SliTaz
    1.95 +		    isoopen("vmlinuz") >= 0	||	// misc
    1.96 +		    (isoopen("linux") >= 0 && ++isknoppix)) {
    1.97 +			isokernel();
    1.98 +			magic = kver2ul(load_kernel());
    1.99 +			break;
   1.100 +		}
   1.101 +	} while (isoopen("isolinux") >= 0);		// Knoppix
   1.102 +	fallback[0] = 0;
   1.103 +	for (c = 0, restart = 1; isoreaddir(restart) == 0; restart = 0) {
   1.104 +		if (strstr(isofilename, ".gz"))
   1.105 +			strcpy(fallback, isofilename);
   1.106 +		if (strhead(isofilename, "rootfs") 
   1.107 +			|| c > isofilename[6]) continue;
   1.108 +		strcpy(rootfs, isofilename);
   1.109 +		c = isofilename[6];
   1.110 +	}
   1.111 +
   1.112 +	strcpy(_cmdline,"rw root=/dev/null autologin bootfrom=");
   1.113 +	strcat(_cmdline,*iso);
   1.114 +	if (magic < 0x20630)
   1.115 +		init = ""; // Does not support multiple initramfs
   1.116 +
   1.117 +	if (magic > 0) {
   1.118 +		char *initrd = fallback;
   1.119 +
   1.120 +		if (rootfs[0]) {
   1.121 +			initrd = rootfs;
   1.122 +			if (rootfs[6] != '.' && isoopen("rootfs.gz") >= 0)
   1.123 +				addinitrd();	// for loram
   1.124 +		}
   1.125 +		if (isoopen(initrd) >= 0) {
   1.126 +			addinitrd();
   1.127 +		}
   1.128 +		if (*init && lseek(isofd, 20L, SEEK_SET) != -1 &&
   1.129 +		    read(isofd, &isofileofs, 4) == 4 &&
   1.130 +		    read(isofd, &magic, 4) == 4) {
   1.131 +			isofileofs &= 0xFFFFL;
   1.132 +			isofilesize = magic & 0xFFFFL;
   1.133 +			isofileofs -= 0xC0L + isofilesize;
   1.134 +			if (isofilesize) addinitrd();
   1.135 +			else init="";
   1.136 +		}
   1.137 +		load_initrds();
   1.138 +		strcat(_cmdline,init);
   1.139 +		strcat(_cmdline," mode=");
   1.140 +		strcat(_cmdline,mode);
   1.141 +		strcat(_cmdline," magic=");
   1.142 +		strcat(_cmdline,ultoa(magic));
   1.143 +	}
   1.144 +	if (isknoppix) {
   1.145 +		if (iso[0][1] == ':')
   1.146 +			*iso += 2;
   1.147 +		for (s = *iso; *s; s++)
   1.148 +			if (*s == '\\') *s = '/';
   1.149 +	}
   1.150 +	close(isofd);
   1.151 +	boot_kernel();
   1.152 +}
   1.153 +
   1.154 +u16 root_dev;
   1.155 +u16 vid_mode;
   1.156 +const char* kernel_name = "bzImage";
   1.157 +const char* initrd_name;
   1.158 +int main(int argc, char *argv[])
   1.159 +{
   1.160 +	char *iso = NULL;
   1.161 +	argv[0] = progname();
   1.162 +	bootiso(argv);	// iso ? parsing is /init.exe stuff !
   1.163 +	if (argc >= 2)
   1.164 +		bootiso(argv + 1);
   1.165 +
   1.166 +	chdirname(*argv);
   1.167 +	if (argc < 2) {
   1.168 +dousage:
   1.169 +		usage();
   1.170 +	}
   1.171 +	for (int i=1; i < argc; i++) {
   1.172 +		char *s=argv[i];
   1.173 +		if (strhead(s,"kernel=") == 0)
   1.174 +			kernel_name = s + 7;
   1.175 +		if (strhead(s,"image=") == 0)
   1.176 +			kernel_name = s + 6;
   1.177 +		else if (strhead(s,"initrd=") == 0)
   1.178 +			initrd_name = s + 7;
   1.179 +		else if (strhead(s,"bootfrom=") == 0)
   1.180 +			iso = s + 9;
   1.181 +		else if (strhead(s,"iso=") == 0)
   1.182 +			iso = s + 4;
   1.183 +		else if(strhead(s,"vga=") == 0) {
   1.184 +			s+=4;
   1.185 +			const char c = *s|0x20;
   1.186 +			if (c == 'a') vid_mode = -3;
   1.187 +			else if (c == 'e') vid_mode = -2;
   1.188 +			else if (c == 'n') vid_mode = -1;
   1.189 +			else vid_mode = strtol(s);
   1.190 +		}
   1.191 +		else if(strhead(s,"-f") == 0) {
   1.192 +			skip_xmmalloc++;
   1.193 +		}
   1.194 +		else {
   1.195 +			if(strhead(s,"root=") == 0) {
   1.196 +				root_dev = strtol(s+5);
   1.197 +			}
   1.198 +			if(strhead(s,"mem=") == 0) {
   1.199 +				topmem = strtol(s+4);
   1.200 +			}
   1.201 +			if (_cmdline[0]) strcat(_cmdline," ");
   1.202 +			strcat(_cmdline,s);
   1.203 +		}
   1.204 +	}
   1.205 +	if (iso && isoreset(iso) >= 0) {
   1.206 +		char *s = (char *) initrd_name;
   1.207 +		if (isoopen((char *) kernel_name) >= 0) {
   1.208 +			isokernel();
   1.209 +			load_kernel();
   1.210 +		}
   1.211 +		if (s) {
   1.212 +			while (*s) {
   1.213 +				char *p, c;
   1.214 +				for (p = s; *s && *s != ','; s++);
   1.215 +				c = *s; *s = 0;
   1.216 +				if (isoopen(p) >= 0) {
   1.217 +					addinitrd();
   1.218 +				}
   1.219 +				*s = c;
   1.220 +				if (c) s++;
   1.221 +			}
   1.222 +			load_initrds();
   1.223 +		}
   1.224 +	}
   1.225 +	else {
   1.226 +		load_kernel();
   1.227 +		load_initrd();
   1.228 +	}
   1.229 +	boot_kernel();
   1.230 +	return _AX;
   1.231 +}