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

syslinux/iso2exe: fix 16M hole
author Pascal Bellard <pascal.bellard@slitaz.org>
date Tue Mar 04 09:23:30 2014 +0000 (2014-03-04)
parents 3f0b08dbc9d3
children 825165c08d25
rev   line source
pascal@13691 1 #include <stdio.h>
pascal@13691 2 #include "iso9660.h"
pascal@13691 3
pascal@13691 4 static unsigned 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@13733 27 #define BUFFERSZ PAGE_SIZE
pascal@13691 28 static char buffer[BUFFERSZ];
pascal@13691 29 static unsigned long initrd_addr, 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@13691 48 static struct mem {
pascal@13691 49 unsigned long base;
pascal@13691 50 int align;
pascal@13691 51 } kernelmem = { 0x100000, 0 };
pascal@13691 52
pascal@13691 53 #define initrdmem kernelmem
pascal@13691 54
pascal@13691 55 static void movehi(void)
pascal@13691 56 {
pascal@13691 57 #asm
pascal@13691 58 pusha
pascal@13691 59 xor di, di // 30
pascal@13691 60 mov cx, #9 // 2E..1E
pascal@13691 61 zero1:
pascal@13691 62 push di
pascal@13691 63 loop zero1
pascal@13691 64 push dword [_kernelmem] // 1A p->base
pascal@13691 65 push #-1 // 18
pascal@13691 66 push di // 16
pascal@13691 67 xor eax, eax
pascal@13691 68 cdq
pascal@13691 69 mov dx, ds
pascal@13691 70 shl edx, #4
pascal@13691 71 mov ax, #_buffer
pascal@13691 72 add edx, eax
pascal@13691 73 push edx // 12 linear_address(buffer)
pascal@13691 74 push #-1 // 10
pascal@13691 75 mov cl, #8 // 0E..00
pascal@13691 76 zero2:
pascal@13691 77 push di
pascal@13691 78 loop zero2
pascal@13691 79 mov ch, #BUFFERSZ/512
pascal@13691 80 push ss
pascal@13691 81 pop es
pascal@13691 82 mov si, sp
pascal@13691 83 mov ax, #0x8793
pascal@13691 84 mov [si+0x15], al
pascal@13691 85 xchg [si+0x1D], al
pascal@15980 86 mov [si+0x1F], al // bits 24..31
pascal@13691 87 int 0x15
pascal@13691 88 add sp, #0x30
pascal@13691 89 popa
pascal@13691 90 #endasm
pascal@13691 91 }
pascal@13691 92
pascal@13733 93 #undef ZIMAGE_SUPPORT /* Does not work... */
pascal@13733 94
pascal@13699 95 static int versiondos;
pascal@13699 96 static int dosversion(void)
pascal@13699 97 {
pascal@13699 98 #asm
pascal@13699 99 mov ah, #0x30
pascal@13699 100 int 0x21
pascal@13699 101 cbw
pascal@13699 102 mov _versiondos, ax
pascal@13699 103 #endasm
pascal@13699 104 }
pascal@13699 105
pascal@15981 106 static unsigned extendedramsizeinkb(void)
pascal@15981 107 {
pascal@15981 108 #asm
pascal@15981 109 mov ah, #0x88
pascal@15981 110 int 0x15
pascal@15981 111 jnc gottop
pascal@15981 112 xor ax, ax
pascal@15981 113 gottop:
pascal@15981 114 #endasm
pascal@15981 115 }
pascal@15981 116
pascal@13691 117 static void load(struct mem *p, unsigned long size)
pascal@13691 118 {
pascal@13691 119 if (vm86())
pascal@13691 120 die("Need real mode");
pascal@13691 121 switch (p->align) {
pascal@13691 122 case 0: // kernel
pascal@13699 123 switch (dosversion()) {
pascal@13699 124 case 3: case 4: case 6: break;
pascal@13699 125 default:
pascal@13699 126 printf("DOS %d not supported.\nTrying anyway...\n",
pascal@13699 127 versiondos);
pascal@13699 128 }
pascal@13733 129 p->align = PAGE_SIZE;
pascal@13691 130 break;
pascal@16002 131 case PAGE_SIZE: // first initrd : skip mapping hole before 16M
pascal@16002 132 if (extendedramsizeinkb() > 24000U && p->base < 0x1000000)
pascal@16002 133 p->base = 0x1000000;
pascal@16002 134 initrd_addr = p->base;
pascal@13691 135 p->align = 4;
pascal@13691 136 }
pascal@13691 137 while (size) {
pascal@13691 138 int n, s = sizeof(buffer);
pascal@13691 139 for (n = 0; n < s; n++) buffer[n] = 0;
pascal@13691 140 if (s > size) s = size;
pascal@13691 141 n = isoread(buffer, s);
pascal@13691 142 movehi();
pascal@13691 143 if (n != -1) {
pascal@13691 144 p->base += n;
pascal@13691 145 size -= n;
pascal@13691 146 }
pascal@13691 147 if (s != n) break;
pascal@13691 148 }
pascal@13691 149 initrd_size = p->base - initrd_addr;
pascal@13691 150 p->base += p->align - 1;
pascal@13691 151 p->base &= - p->align;
pascal@13691 152 }
pascal@13691 153
pascal@13691 154 static unsigned setupofs = 0;
pascal@13691 155
pascal@13691 156 void movesetup(void)
pascal@13691 157 {
pascal@13691 158 #asm
pascal@13691 159 pusha
pascal@13691 160 push #SETUP_SEGMENT
pascal@13691 161 pop es
pascal@13691 162 mov si, #_buffer
pascal@13691 163 mov di, _setupofs
pascal@13691 164 mov cx, #BUFFERSZ/2
pascal@13691 165 rep
pascal@13691 166 movsw
pascal@13691 167 mov _setupofs, di
pascal@13691 168 popa
pascal@13691 169 #endasm
pascal@13691 170 }
pascal@13691 171
pascal@14257 172 static unsigned getcs(void)
pascal@14257 173 {
pascal@14257 174 #asm
pascal@14257 175 mov ax, cs
pascal@14257 176 #endasm
pascal@14257 177 }
pascal@14257 178
pascal@14257 179 unsigned long loadkernel(void)
pascal@13691 180 {
pascal@13691 181 unsigned setup, n = BUFFERSZ;
pascal@14268 182 unsigned long syssize = 0, kernel_version = 0;
pascal@13691 183
pascal@13691 184 do {
pascal@13691 185 isoread(buffer, n);
pascal@13691 186 if (setupofs == 0) {
pascal@13691 187 if (* (unsigned short *) (buffer + BOOTFLAG) != 0xAA55)
pascal@13691 188 die("The kernel is not bootable");
pascal@13691 189 setup = (1 + buffer[SETUPSECTORS]) << 9;
pascal@13691 190 if (setup == 512) setup = 5 << 9;
pascal@13691 191 syssize = * (unsigned long *) (buffer + SYSSIZE) << 4;
pascal@13691 192 version = * (unsigned short *) (buffer + VERSION);
pascal@13691 193 #define HDRS 0x53726448
pascal@13691 194 if (* (unsigned long *) (buffer + HEADER) != HDRS)
pascal@13691 195 version = 0;
pascal@13733 196 if (version < 0x204)
pascal@13733 197 syssize &= 0x000FFFFFUL;
pascal@13733 198 if (version) {
pascal@13733 199 #ifdef REALMODE_SWITCH
pascal@13733 200 extern int far_realmode_switch();
pascal@13733 201 #asm
pascal@13733 202 jmp end_realmode_switch
pascal@13733 203 _far_realmode_switch:
pascal@14257 204 call REALMODE_SWITCH
pascal@13733 205 cli
pascal@13733 206 mov al, #0x80 // Disable NMI
pascal@13733 207 out 0x70, al
pascal@13733 208 retf
pascal@13733 209 end_realmode_switch:
pascal@13733 210 #endasm
pascal@13733 211 * (unsigned short *) (buffer + RMSWOFS) =
pascal@13733 212 far_realmode_switch;
pascal@13733 213 * (unsigned short *) (buffer + RMSWSEG) =
pascal@13733 214 getcs();
pascal@13733 215 #endif
pascal@13733 216 kernelmem.base =
pascal@13733 217 * (unsigned long *) (buffer + SYSTEMCODE);
pascal@13733 218 * (unsigned short *) (buffer + HEAPPTR) =
pascal@13733 219 0x9B00;
pascal@13733 220 // buffer[LOADFLAGS] |= 0x80;
pascal@13733 221 * (unsigned short *) (buffer + LOADERTYPE) |=
pascal@13733 222 0x80FF;
pascal@13733 223 }
pascal@13691 224 if (!version || !(buffer[LOADFLAGS] & 1)) {
pascal@13691 225 #ifdef ZIMAGE_SUPPORT
pascal@13691 226 #asm
pascal@13691 227 pusha
pascal@13691 228 mov cx, #0x8000
pascal@13691 229 mov es, cx
pascal@13691 230 xor si, si
pascal@13691 231 xor di, di
pascal@13691 232 rep
pascal@13697 233 movsw // move 64K data
pascal@13691 234 push es
pascal@13691 235 pop ds
pascal@13691 236 push es
pascal@13691 237 pop ss
pascal@13697 238 mov ch, #0x70
pascal@13697 239 mov es, cx
pascal@13697 240 mov ch, #0x80
pascal@13697 241 rep
pascal@13697 242 seg cs
pascal@13697 243 movsw // move 64K code
pascal@13691 244 popa
pascal@13697 245 jmpi relocated, #0x7000
pascal@13691 246 relocated:
pascal@13691 247 #endasm
pascal@13691 248 kernelmem.base = 0x10000;
pascal@13697 249 if (syssize > 0x60000) /* 384K max */
pascal@13691 250 #endif
pascal@13691 251 die("Not a bzImage format");
pascal@13691 252 }
pascal@13691 253 }
pascal@13691 254 movesetup();
pascal@13691 255 setup -= n;
pascal@13691 256 n = (setup > BUFFERSZ) ? BUFFERSZ : setup;
pascal@13691 257 } while (setup > 0);
pascal@13691 258
pascal@14257 259 #asm
pascal@14257 260 push ds
pascal@14257 261 push #SETUP_SEGMENT
pascal@14257 262 pop ds
pascal@14257 263 mov si, #0x200
pascal@14257 264 mov eax, #0x53726448 // HdrS
pascal@14257 265 cdq // clear edx
pascal@14257 266 cmp [si+2], eax
pascal@14257 267 jne noversion
pascal@14257 268 add si, [si+14]
pascal@14257 269 mov cx, #3
pascal@14257 270 xor ax, ax
pascal@14257 271 nextdigit:
pascal@14264 272 shl al, #4
pascal@14264 273 shl ax, #4
pascal@14257 274 next:
pascal@14257 275 lodsb
pascal@14257 276 sub al, #0x30
pascal@14257 277 cmp al, #9
pascal@14257 278 jbe nextdigit
pascal@14264 279 shl eax, #16
pascal@14264 280 shld edx, eax, #8
pascal@14257 281 loop next
pascal@14257 282 pop ds
pascal@14268 283 mov .loadkernel.kernel_version[bp], edx
pascal@14257 284 noversion:
pascal@14257 285 #endasm
pascal@13691 286 load(&kernelmem, syssize);
pascal@14268 287 return kernel_version;
pascal@13691 288 }
pascal@13691 289
pascal@13691 290 void loadinitrd(void)
pascal@13691 291 {
pascal@13691 292 if (version)
pascal@13691 293 load(&initrdmem, isofilesize);
pascal@13691 294 }
pascal@13691 295
pascal@13691 296 void bootlinux(char *cmdline)
pascal@13691 297 {
pascal@13691 298 #asm
pascal@13691 299 push #SETUP_SEGMENT
pascal@13691 300 pop es
pascal@13691 301 mov eax, _initrd_addr
pascal@13691 302 or eax, eax
pascal@13691 303 jz no_initrd
pascal@13691 304 mov di, #0x218
pascal@13691 305 stosd
pascal@13691 306 mov eax, _initrd_size
pascal@13691 307 stosd
pascal@13691 308 no_initrd:
pascal@13691 309 #endasm
pascal@13691 310 if (cmdline) {
pascal@13691 311 if (version <= 0x201) {
pascal@13691 312 #asm
pascal@13691 313 mov di, #0x0020
pascal@13691 314 mov ax, #0xA33F
pascal@13691 315 stosw
pascal@13691 316 mov ax, #CMDLINE_OFFSET
pascal@13691 317 stosw
pascal@13691 318 #endasm
pascal@13691 319 }
pascal@13691 320 else {
pascal@13691 321 #asm
pascal@13691 322 mov di, #0x0228
pascal@13691 323 mov eax, #SETUP_SEGMENT*16+CMDLINE_OFFSET
pascal@13691 324 stosd
pascal@13691 325 #endasm
pascal@13691 326 }
pascal@13691 327 #asm
pascal@13691 328 xchg ax, di
pascal@13691 329 mov si, .bootlinux.cmdline[bp]
pascal@13691 330 copy:
pascal@13691 331 lodsb
pascal@13691 332 stosb
pascal@13691 333 or al,al
pascal@13691 334 jne copy
pascal@13691 335 #endasm
pascal@13691 336 }
pascal@13691 337 #asm
pascal@13691 338 push es
pascal@13691 339 pop ds
pascal@13691 340 push ds
pascal@13691 341 pop ss
pascal@13691 342 mov sp, #CMDLINE_OFFSET
pascal@13691 343 jmpi 0, #0x9020
pascal@13691 344 #endasm
pascal@13691 345 }