wok annotate syslinux/stuff/iso2exe/bootlinux.c @ rev 16025

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