wok diff syslinux/stuff/iso2exe/bootlinux.c @ rev 13691

syslinux: add iso2exe
author Pascal Bellard <pascal.bellard@slitaz.org>
date Thu Dec 13 14:33:27 2012 +0100 (2012-12-13)
parents
children d47403fdd900
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/syslinux/stuff/iso2exe/bootlinux.c	Thu Dec 13 14:33:27 2012 +0100
     1.3 @@ -0,0 +1,258 @@
     1.4 +#include <stdio.h>
     1.5 +#include "iso9660.h"
     1.6 +
     1.7 +static unsigned version;
     1.8 +#define SETUPSECTORS	0x1F1
     1.9 +#define ROFLAG		0x1F2
    1.10 +#define SYSSIZE		0x1F4
    1.11 +#define VIDEOMODE	0x1FA
    1.12 +#define BOOTFLAG	0x1FE
    1.13 +#define HEADER		0x202
    1.14 +#define VERSION		0x206
    1.15 +#define RMSWOFS		0x208
    1.16 +#define RMSWSEG		0x20A
    1.17 +#define LOADERTYPE	0x210
    1.18 +#define LOADFLAGS	0x211
    1.19 +#define SYSTEMCODE	0x214
    1.20 +#define INITRDCODE	0x218
    1.21 +#define INITRDSIZE	0x21C
    1.22 +#define HEAPPTR		0x224
    1.23 +#define CMDLINE		0x228
    1.24 +
    1.25 +#define SETUP_SEGMENT	0x9000
    1.26 +#define CMDLINE_OFFSET	0x9E00
    1.27 +
    1.28 +#define BUFFERSZ	2*1024
    1.29 +static char buffer[BUFFERSZ];
    1.30 +static unsigned long initrd_addr, initrd_size;
    1.31 +
    1.32 +static int may_exit_dos = 1;
    1.33 +static void die(char *msg)
    1.34 +{
    1.35 +	printf("%s.\n", msg);
    1.36 +	if (may_exit_dos)
    1.37 +		exit(1);
    1.38 +	while (1);
    1.39 +}
    1.40 +
    1.41 +static int vm86(void)
    1.42 +{
    1.43 +#asm
    1.44 +		smsw	ax
    1.45 +		and	ax, #1		// 0:realmode	1:vm86
    1.46 +#endasm
    1.47 +} 
    1.48 +
    1.49 +static struct mem {
    1.50 +	unsigned long base;
    1.51 +	int align;
    1.52 +} kernelmem = { 0x100000, 0 };
    1.53 +
    1.54 +#define initrdmem kernelmem
    1.55 +
    1.56 +static void movehi(void)
    1.57 +{
    1.58 +#asm
    1.59 +		pusha
    1.60 +		xor	di, di		// 30
    1.61 +		mov	cx, #9		// 2E..1E
    1.62 +zero1:
    1.63 +		push	di
    1.64 +		loop	zero1
    1.65 +		push	dword [_kernelmem]	// 1A p->base
    1.66 +		push	#-1		// 18
    1.67 +		push	di		// 16
    1.68 +		xor	eax, eax
    1.69 +		cdq
    1.70 +		mov	dx, ds
    1.71 +		shl	edx, #4
    1.72 +		mov	ax, #_buffer
    1.73 +		add	edx, eax
    1.74 +		push	edx		// 12 linear_address(buffer)
    1.75 +		push	#-1		// 10
    1.76 +		mov	cl, #8		// 0E..00
    1.77 +zero2:
    1.78 +		push	di
    1.79 +		loop	zero2
    1.80 +		mov	ch, #BUFFERSZ/512
    1.81 +		push	ss
    1.82 +		pop	es
    1.83 +		mov	si, sp
    1.84 +		mov	ax, #0x8793
    1.85 +		mov	[si+0x15], al
    1.86 +		xchg	[si+0x1D], al
    1.87 +		mov	[si+0x1F], al	// bits 24..31, doesn't work for me :(
    1.88 +		int	0x15
    1.89 +		add	sp, #0x30
    1.90 +		popa
    1.91 +#endasm
    1.92 +}
    1.93 +
    1.94 +static void load(struct mem *p, unsigned long size)
    1.95 +{
    1.96 +	if (vm86())
    1.97 +		die("Need real mode");
    1.98 +	switch (p->align) {
    1.99 +	case 0:	// kernel
   1.100 +		p->align = 4096;
   1.101 +		break;
   1.102 +	case 4096: // first initrd
   1.103 +		initrd_addr = p->base;
   1.104 +		p->align = 4;
   1.105 +	}
   1.106 +	while (size) {
   1.107 +		int n, s = sizeof(buffer);
   1.108 +		for (n = 0; n < s; n++) buffer[n] = 0;
   1.109 +		if (s > size) s = size;
   1.110 +		n = isoread(buffer, s);
   1.111 +		movehi();
   1.112 +		if (n != -1) {
   1.113 +			p->base += n;
   1.114 +			size -= n;
   1.115 +		}
   1.116 +		if (s != n) break;
   1.117 +	}
   1.118 +	initrd_size = p->base - initrd_addr;
   1.119 +	p->base += p->align - 1;
   1.120 +	p->base &= - p->align;
   1.121 +}
   1.122 +
   1.123 +static unsigned setupofs = 0;
   1.124 +
   1.125 +void movesetup(void)
   1.126 +{
   1.127 +#asm
   1.128 +		pusha
   1.129 +		push	#SETUP_SEGMENT
   1.130 +		pop	es
   1.131 +		mov	si, #_buffer
   1.132 +		mov	di, _setupofs
   1.133 +		mov	cx, #BUFFERSZ/2
   1.134 +		rep
   1.135 +		  movsw
   1.136 +		mov	_setupofs, di
   1.137 +		popa
   1.138 +#endasm
   1.139 +}
   1.140 +
   1.141 +void loadkernel(void)
   1.142 +{
   1.143 +	unsigned setup, n = BUFFERSZ;
   1.144 +	unsigned long syssize = 0;
   1.145 +
   1.146 +	do {
   1.147 +		isoread(buffer, n);
   1.148 +		if (setupofs == 0) {
   1.149 +			if (* (unsigned short *) (buffer + BOOTFLAG) != 0xAA55)
   1.150 +				die("The kernel is not bootable");
   1.151 +			setup = (1 + buffer[SETUPSECTORS]) << 9;
   1.152 +			if (setup == 512) setup = 5 << 9;
   1.153 +			syssize = * (unsigned long  *) (buffer + SYSSIZE) << 4;
   1.154 +			version = * (unsigned short *) (buffer + VERSION);
   1.155 +#define HDRS	0x53726448
   1.156 +			if (* (unsigned long *) (buffer + HEADER) != HDRS)
   1.157 +				version = 0;
   1.158 +			if (!version || !(buffer[LOADFLAGS] & 1)) {
   1.159 +#undef ZIMAGE_SUPPORT	/* Does not work... */
   1.160 +#ifdef ZIMAGE_SUPPORT
   1.161 +#asm
   1.162 +		pusha
   1.163 +		mov	cx, #0x8000
   1.164 +		mov	es, cx
   1.165 +		xor	si, si
   1.166 +		xor	di, di
   1.167 +		rep
   1.168 +		  movsw
   1.169 +		push	es
   1.170 +		pop	ds
   1.171 +		push	es
   1.172 +		pop	ss
   1.173 +		popa
   1.174 +		jmpi	relocated, #0x8000
   1.175 +relocated:
   1.176 +#endasm
   1.177 +				kernelmem.base = 0x10000;
   1.178 +				if (syssize > 0x70000)
   1.179 +#endif
   1.180 +				die("Not a bzImage format");
   1.181 +			}
   1.182 +			if (version < 0x204)
   1.183 +				syssize &= 0x000FFFFFUL;
   1.184 +			if (version) {
   1.185 +#ifdef REALMODE_SWITCH
   1.186 +				* (unsigned short *) (buffer + RMSWOFS) = 
   1.187 +					realmode_switch;
   1.188 +				* (unsigned short *) (buffer + RMSWSEG) = 
   1.189 +					getcs();
   1.190 +#endif
   1.191 +				* (unsigned short *) (buffer + HEAPPTR) = 
   1.192 +					0x9B00;
   1.193 +				// buffer[LOADFLAGS] |= 0x80;
   1.194 +				* (unsigned short *) (buffer + LOADERTYPE) |= 
   1.195 +					0x80FF;
   1.196 +			}
   1.197 +		}
   1.198 +		movesetup();
   1.199 +		setup -= n;
   1.200 +		n = (setup > BUFFERSZ) ? BUFFERSZ : setup;
   1.201 +	} while (setup > 0);
   1.202 +
   1.203 +	load(&kernelmem, syssize);
   1.204 +}
   1.205 +
   1.206 +void loadinitrd(void)
   1.207 +{
   1.208 +	if (version)
   1.209 +		load(&initrdmem, isofilesize);
   1.210 +}
   1.211 +
   1.212 +void bootlinux(char *cmdline)
   1.213 +{
   1.214 +#asm
   1.215 +	push	#SETUP_SEGMENT
   1.216 +	pop	es
   1.217 +	mov	eax, _initrd_addr
   1.218 +	or	eax, eax
   1.219 +	jz	no_initrd
   1.220 +	mov	di, #0x218
   1.221 +	stosd
   1.222 +	mov	eax, _initrd_size
   1.223 +	stosd
   1.224 +no_initrd:
   1.225 +#endasm
   1.226 +	if (cmdline) {
   1.227 +		if (version <= 0x201) {
   1.228 +#asm
   1.229 +		mov	di, #0x0020
   1.230 +		mov	ax, #0xA33F
   1.231 +		stosw
   1.232 +		mov	ax, #CMDLINE_OFFSET
   1.233 +		stosw
   1.234 +#endasm
   1.235 +		}
   1.236 +		else {
   1.237 +#asm
   1.238 +		mov	di, #0x0228
   1.239 +		mov	eax, #SETUP_SEGMENT*16+CMDLINE_OFFSET
   1.240 +		stosd
   1.241 +#endasm
   1.242 +		}
   1.243 +#asm
   1.244 +		xchg	ax, di
   1.245 +		mov	si, .bootlinux.cmdline[bp]
   1.246 +copy:
   1.247 +		lodsb
   1.248 +		stosb
   1.249 +		or	al,al
   1.250 +		jne	copy
   1.251 +#endasm
   1.252 +	}
   1.253 +#asm
   1.254 +	push	es
   1.255 +	pop	ds
   1.256 +	push	ds
   1.257 +	pop	ss
   1.258 +	mov	sp, #CMDLINE_OFFSET
   1.259 +	jmpi	0, #0x9020
   1.260 +#endasm
   1.261 +}