wok view syslinux/stuff/iso2exe/bootlinux.c @ rev 16022
syslinux/iso2exe: add zimage support
| author | Pascal Bellard <pascal.bellard@slitaz.org> | 
|---|---|
| date | Thu Mar 06 19:57:41 2014 +0000 (2014-03-06) | 
| parents | 825165c08d25 | 
| children | d814ca840c3c | 
 line source
     1 #include <stdio.h>
     2 #include "iso9660.h"
     4 static unsigned setup_version;
     5 #define SETUPSECTORS	0x1F1
     6 #define ROFLAG		0x1F2
     7 #define SYSSIZE		0x1F4
     8 #define VIDEOMODE	0x1FA
     9 #define BOOTFLAG	0x1FE
    10 #define HEADER		0x202
    11 #define VERSION		0x206
    12 #define RMSWOFS		0x208
    13 #define RMSWSEG		0x20A
    14 #define LOADERTYPE	0x210
    15 #define LOADFLAGS	0x211
    16 #define SYSTEMCODE	0x214
    17 #define INITRDCODE	0x218
    18 #define INITRDSIZE	0x21C
    19 #define HEAPPTR		0x224
    20 #define CMDLINE		0x228
    22 #define SETUP_SEGMENT	0x9000
    23 #define CMDLINE_OFFSET	0x9E00
    25 #define PAGE_BITS	12
    26 #define PAGE_SIZE	4096
    27 #define BUFFERSZ	2048		// lower than mix setup
    28 static char buffer[BUFFERSZ];
    29 static unsigned long initrd_addr = 0, initrd_size;
    31 static int may_exit_dos = 1;
    32 static void die(char *msg)
    33 {
    34 	printf("%s.\n", msg);
    35 	if (may_exit_dos)
    36 		exit(1);
    37 	while (1);
    38 }
    40 static int vm86(void)
    41 {
    42 #asm
    43 		smsw	ax
    44 		and	ax, #1		// 0:realmode	1:vm86
    45 #endasm
    46 } 
    48 static struct {
    49 	unsigned long base;
    50 	int align;
    51 } mem = { 0x100000, 0 };
    53 static void movehi(void)
    54 {
    55 #asm
    56 		pusha
    57 		xor	di, di		// 30
    58 		mov	cx, #9		// 2E..1E
    59 zero1:
    60 		push	di
    61 		loop	zero1
    62 		push	dword [_mem]	// 1A mem.base
    63 		push	#-1		// 18
    64 		push	di		// 16
    65 		xor	eax, eax
    66 		cdq
    67 		mov	dx, ds
    68 		shl	edx, #4
    69 		mov	ax, #_buffer
    70 		add	edx, eax
    71 		push	edx		// 12 linear_address(buffer)
    72 		push	#-1		// 10
    73 		mov	cl, #8		// 0E..00
    74 zero2:
    75 		push	di
    76 		loop	zero2
    77 		mov	ch, #BUFFERSZ/512
    78 		push	ss
    79 		pop	es
    80 		mov	si, sp
    81 		mov	ax, #0x8793
    82 		mov	[si+0x15], al
    83 		xchg	[si+0x1D], al
    84 		xchg	[si+0x1F], al	// bits 24..31
    85 		int	0x15
    86 		add	sp, #0x30
    87 		popa
    88 #endasm
    89 }
    91 #define ZIMAGE_SUPPORT
    93 #ifdef ZIMAGE_SUPPORT
    94 static int zimage = 0;
    95 static unsigned zimage_base;
    96 static unsigned getss(void)
    97 {
    98 #asm
    99 	mov	ax, ss
   100 #endasm
   101 }
   102 #endif
   104 static int versiondos;
   105 static int dosversion(void)
   106 {
   107 #asm
   108 		mov	ah, #0x30
   109 		int	0x21
   110 		cbw
   111 		mov	_versiondos, ax
   112 #endasm
   113 }
   115 static unsigned extendedramsizeinkb(void)
   116 {
   117 #asm
   118 		mov	ah, #0x88
   119 		int	0x15
   120 		jnc	gottop
   121 		xor	ax, ax
   122 gottop:
   123 #endasm
   124 }
   126 static void load(unsigned long size)
   127 {
   128 	if (vm86())
   129 		die("Need real mode");
   130 	switch (mem.align) {
   131 	case 0:	// kernel
   132 		switch (dosversion()) {
   133 		case 3: case 4: case 6: case 7: break;
   134 		default:
   135 			printf("DOS %d not supported.\nTrying anyway...\n",
   136 				versiondos);
   137 		}
   138 		mem.align = PAGE_SIZE;
   139 		break;
   140 	case PAGE_SIZE: // first initrd : keep 16M..48M for the kernel
   141 		if (extendedramsizeinkb() > 0xF000U && mem.base < 0x3000000)
   142 			mem.base = 0x3000000;
   143 		initrd_addr = mem.base;
   144 		mem.align = 4;
   145 	}
   146 	while (size) {
   147 		int n, s = sizeof(buffer);
   148 		for (n = 0; n < s; n++) buffer[n] = 0;
   149 		if (s > size) s = size;
   150 		if ((n = isoread(buffer, s)) < 0) break;
   151 		movehi();
   152 		mem.base += n;
   153 		size -= n;
   154 		if (s != n) break;	// end of file
   155 	}
   156 	initrd_size = mem.base - initrd_addr;
   157 	mem.base += mem.align - 1;
   158 	mem.base &= - mem.align;
   159 }
   161 static unsigned setupofs = 0;
   163 void movesetup(void)
   164 {
   165 #asm
   166 		pusha
   167 		push	#SETUP_SEGMENT
   168 		pop	es
   169 		mov	si, #_buffer
   170 		mov	di, _setupofs
   171 		mov	cx, #BUFFERSZ/2
   172 		rep
   173 		  movsw
   174 		mov	_setupofs, di
   175 		popa
   176 #endasm
   177 }
   179 static unsigned getcs(void)
   180 {
   181 #asm
   182 	mov	ax, cs
   183 #endasm
   184 }
   186 unsigned long loadkernel(void)
   187 {
   188 	unsigned setup, n = BUFFERSZ;
   189 	unsigned long syssize = 0, kernel_version = 0;
   191 	do {
   192 		isoread(buffer, n);
   193 		if (setupofs == 0) {
   194 			if (* (unsigned short *) (buffer + BOOTFLAG) != 0xAA55)
   195 				die("The kernel is not bootable");
   196 			setup = (1 + buffer[SETUPSECTORS]) << 9;
   197 			if (setup == 512) setup = 5 << 9;
   198 			syssize = * (unsigned long  *) (buffer + SYSSIZE) << 4;
   199 			setup_version = * (unsigned short *) (buffer + VERSION);
   200 #define HDRS	0x53726448
   201 			if (* (unsigned long *) (buffer + HEADER) != HDRS)
   202 				setup_version = 0;
   203 			if (setup_version < 0x204)
   204 				syssize &= 0x000FFFFFUL;
   205 			if (setup_version) {
   206 #ifdef REALMODE_SWITCH
   207 				extern int far_realmode_switch();
   208 #asm
   209 				jmp	end_realmode_switch
   210 _far_realmode_switch:
   211 				call	REALMODE_SWITCH
   212 				cli
   213 				mov	al, #0x80	// Disable NMI
   214 				out	0x70, al
   215 				retf
   216 end_realmode_switch:
   217 #endasm
   218 				* (unsigned short *) (buffer + RMSWOFS) = 
   219 					far_realmode_switch;
   220 				* (unsigned short *) (buffer + RMSWSEG) = 
   221 					getcs();
   222 #endif
   223 				mem.base =
   224 					* (unsigned long *) (buffer + SYSTEMCODE);
   225 				* (unsigned short *) (buffer + HEAPPTR) = 
   226 					0x9B00;
   227 				// buffer[LOADFLAGS] |= 0x80;
   228 				* (unsigned short *) (buffer + LOADERTYPE) |= 
   229 					0x80FF;
   230 			}
   231 			if (!setup_version || !(buffer[LOADFLAGS] & 1)) {
   232 #ifdef ZIMAGE_SUPPORT
   233 				zimage = 1;
   234 				zimage_base = getss() + 0x1000L;
   235 				mem.base = zimage_base * 16L; 
   236 				if (mem.base + syssize > SETUP_SEGMENT*16L - 32)
   237 					die("Out of memory");
   238 #else
   239 				die("Not a bzImage format");
   240 #endif
   241 			}
   242 		}
   243 		movesetup();
   244 		setup -= n;
   245 		n = (setup > BUFFERSZ) ? BUFFERSZ : setup;
   246 	} while (setup > 0);
   248 #asm
   249 		push	ds
   250 		push	#SETUP_SEGMENT
   251 		pop	ds
   252 		mov	si, #0x200
   253 		mov	eax, #0x53726448	// HdrS
   254 		cdq				// clear edx
   255 		cmp	[si+2], eax
   256 		jne	noversion
   257 		add	si, [si+14]
   258 		mov	cx, #3
   259 		xor	ax, ax
   260 nextdigit:
   261 		shl	al, #4
   262 		shl	ax, #4
   263 next:
   264 		lodsb
   265 		sub	al, #0x30
   266 		cmp	al, #9
   267 		jbe	nextdigit
   268 		shl	eax, #16
   269 		shld	edx, eax, #8
   270 		loop	next
   271 		pop	ds
   272 		mov	.loadkernel.kernel_version[bp], edx
   273 		push	ds
   274 noversion:
   275 		pop	ds
   276 #endasm
   277 	load(syssize);
   278 	return kernel_version;
   279 }
   281 void loadinitrd(void)
   282 {
   283 	if (setup_version && zimage == 0)
   284 		load(isofilesize);
   285 }
   287 void bootlinux(char *cmdline)
   288 {
   289 #asm
   290 	push	#SETUP_SEGMENT
   291 	pop	es
   292 	push	es
   293 	pop	ss
   294 	mov	sp, #CMDLINE_OFFSET
   295 	mov	eax, _initrd_addr
   296 	or	eax, eax
   297 	jz	no_initrd
   298 	mov	di, #0x218
   299 	stosd
   300 	mov	eax, _initrd_size
   301 	stosd
   302 no_initrd:
   303 #endasm
   304 	if (cmdline) {
   305 		if (setup_version <= 0x201) {
   306 #asm
   307 		mov	di, #0x0020
   308 		mov	ax, #0xA33F
   309 		stosw
   310 		mov	ax, #CMDLINE_OFFSET
   311 		stosw
   312 #endasm
   313 		}
   314 		else {
   315 #asm
   316 		mov	di, #0x0228
   317 		mov	eax, #SETUP_SEGMENT*16+CMDLINE_OFFSET
   318 		stosd
   319 #endasm
   320 		}
   321 #asm
   322 		xchg	ax, di
   323 		mov	si, .bootlinux.cmdline[bp]
   324 copy:
   325 		lodsb
   326 		stosb
   327 		or	al,al
   328 		jne	copy
   329 #endasm
   330 	}
   331 #ifdef ZIMAGE_SUPPORT
   332 	if (zimage) {
   333 #asm
   334 		mov	eax, _mem
   335 		shr	eax, #4		// top
   336 		mov	bx, _zimage_base
   337 		mov	dx, #0x1000
   338 		push	cs
   339 		pop	ds
   340 		mov	es, ax
   341 		push	es
   342 		mov	si, #sysmove
   343 		xor	di, di
   344 		push	di
   345 		mov	cx, #endsysmove-sysmove
   346 		rep
   347 		  movsb
   348 		retf
   349 sysmove:
   350 		mov	ds, bx
   351 		mov	es, dx
   352 		xor	di, di
   353 		xor	si, si
   354 		mov	cl, #8
   355 		rep
   356 		  movsw
   357 		inc	bx
   358 		inc	dx
   359 		cmp	ax,bx
   360 		jne	sysmove
   361 #endasm
   362 	}
   363 #endif
   364 #asm
   365 	push	ss
   366 	pop	ds
   367 	push	ds
   368 	pop	es
   369 	jmpi	0, #0x9020
   370 endsysmove:
   371 #endasm
   372 }