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 +}