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

syslinux/iso2exe: menu can create usbkey/floppy
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Dec 14 15:43:12 2012 +0100 (2012-12-14)
parents 7d300004a3b8
children 58b695f73790
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@13691 25 #define BUFFERSZ 2*1024
pascal@13691 26 static char buffer[BUFFERSZ];
pascal@13691 27 static unsigned long initrd_addr, initrd_size;
pascal@13691 28
pascal@13691 29 static int may_exit_dos = 1;
pascal@13691 30 static void die(char *msg)
pascal@13691 31 {
pascal@13691 32 printf("%s.\n", msg);
pascal@13691 33 if (may_exit_dos)
pascal@13691 34 exit(1);
pascal@13691 35 while (1);
pascal@13691 36 }
pascal@13691 37
pascal@13691 38 static int vm86(void)
pascal@13691 39 {
pascal@13691 40 #asm
pascal@13691 41 smsw ax
pascal@13691 42 and ax, #1 // 0:realmode 1:vm86
pascal@13691 43 #endasm
pascal@13691 44 }
pascal@13691 45
pascal@13691 46 static struct mem {
pascal@13691 47 unsigned long base;
pascal@13691 48 int align;
pascal@13691 49 } kernelmem = { 0x100000, 0 };
pascal@13691 50
pascal@13691 51 #define initrdmem kernelmem
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@13691 62 push dword [_kernelmem] // 1A p->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@13691 84 mov [si+0x1F], al // bits 24..31, doesn't work for me :(
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@13691 91 static void load(struct mem *p, unsigned long size)
pascal@13691 92 {
pascal@13691 93 if (vm86())
pascal@13691 94 die("Need real mode");
pascal@13691 95 switch (p->align) {
pascal@13691 96 case 0: // kernel
pascal@13691 97 p->align = 4096;
pascal@13691 98 break;
pascal@13691 99 case 4096: // first initrd
pascal@13691 100 initrd_addr = p->base;
pascal@13691 101 p->align = 4;
pascal@13691 102 }
pascal@13691 103 while (size) {
pascal@13691 104 int n, s = sizeof(buffer);
pascal@13691 105 for (n = 0; n < s; n++) buffer[n] = 0;
pascal@13691 106 if (s > size) s = size;
pascal@13691 107 n = isoread(buffer, s);
pascal@13691 108 movehi();
pascal@13691 109 if (n != -1) {
pascal@13691 110 p->base += n;
pascal@13691 111 size -= n;
pascal@13691 112 }
pascal@13691 113 if (s != n) break;
pascal@13691 114 }
pascal@13691 115 initrd_size = p->base - initrd_addr;
pascal@13691 116 p->base += p->align - 1;
pascal@13691 117 p->base &= - p->align;
pascal@13691 118 }
pascal@13691 119
pascal@13691 120 static unsigned setupofs = 0;
pascal@13691 121
pascal@13691 122 void movesetup(void)
pascal@13691 123 {
pascal@13691 124 #asm
pascal@13691 125 pusha
pascal@13691 126 push #SETUP_SEGMENT
pascal@13691 127 pop es
pascal@13691 128 mov si, #_buffer
pascal@13691 129 mov di, _setupofs
pascal@13691 130 mov cx, #BUFFERSZ/2
pascal@13691 131 rep
pascal@13691 132 movsw
pascal@13691 133 mov _setupofs, di
pascal@13691 134 popa
pascal@13691 135 #endasm
pascal@13691 136 }
pascal@13691 137
pascal@13691 138 void loadkernel(void)
pascal@13691 139 {
pascal@13691 140 unsigned setup, n = BUFFERSZ;
pascal@13691 141 unsigned long syssize = 0;
pascal@13691 142
pascal@13691 143 do {
pascal@13691 144 isoread(buffer, n);
pascal@13691 145 if (setupofs == 0) {
pascal@13691 146 if (* (unsigned short *) (buffer + BOOTFLAG) != 0xAA55)
pascal@13691 147 die("The kernel is not bootable");
pascal@13691 148 setup = (1 + buffer[SETUPSECTORS]) << 9;
pascal@13691 149 if (setup == 512) setup = 5 << 9;
pascal@13691 150 syssize = * (unsigned long *) (buffer + SYSSIZE) << 4;
pascal@13691 151 version = * (unsigned short *) (buffer + VERSION);
pascal@13691 152 #define HDRS 0x53726448
pascal@13691 153 if (* (unsigned long *) (buffer + HEADER) != HDRS)
pascal@13691 154 version = 0;
pascal@13691 155 if (!version || !(buffer[LOADFLAGS] & 1)) {
pascal@13691 156 #undef ZIMAGE_SUPPORT /* Does not work... */
pascal@13691 157 #ifdef ZIMAGE_SUPPORT
pascal@13691 158 #asm
pascal@13691 159 pusha
pascal@13691 160 mov cx, #0x8000
pascal@13691 161 mov es, cx
pascal@13691 162 xor si, si
pascal@13691 163 xor di, di
pascal@13691 164 rep
pascal@13697 165 movsw // move 64K data
pascal@13691 166 push es
pascal@13691 167 pop ds
pascal@13691 168 push es
pascal@13691 169 pop ss
pascal@13697 170 mov ch, #0x70
pascal@13697 171 mov es, cx
pascal@13697 172 mov ch, #0x80
pascal@13697 173 rep
pascal@13697 174 seg cs
pascal@13697 175 movsw // move 64K code
pascal@13691 176 popa
pascal@13697 177 jmpi relocated, #0x7000
pascal@13691 178 relocated:
pascal@13691 179 #endasm
pascal@13691 180 kernelmem.base = 0x10000;
pascal@13697 181 if (syssize > 0x60000) /* 384K max */
pascal@13691 182 #endif
pascal@13691 183 die("Not a bzImage format");
pascal@13691 184 }
pascal@13691 185 if (version < 0x204)
pascal@13691 186 syssize &= 0x000FFFFFUL;
pascal@13691 187 if (version) {
pascal@13691 188 #ifdef REALMODE_SWITCH
pascal@13691 189 * (unsigned short *) (buffer + RMSWOFS) =
pascal@13691 190 realmode_switch;
pascal@13691 191 * (unsigned short *) (buffer + RMSWSEG) =
pascal@13691 192 getcs();
pascal@13691 193 #endif
pascal@13691 194 * (unsigned short *) (buffer + HEAPPTR) =
pascal@13691 195 0x9B00;
pascal@13691 196 // buffer[LOADFLAGS] |= 0x80;
pascal@13691 197 * (unsigned short *) (buffer + LOADERTYPE) |=
pascal@13691 198 0x80FF;
pascal@13691 199 }
pascal@13691 200 }
pascal@13691 201 movesetup();
pascal@13691 202 setup -= n;
pascal@13691 203 n = (setup > BUFFERSZ) ? BUFFERSZ : setup;
pascal@13691 204 } while (setup > 0);
pascal@13691 205
pascal@13691 206 load(&kernelmem, syssize);
pascal@13691 207 }
pascal@13691 208
pascal@13691 209 void loadinitrd(void)
pascal@13691 210 {
pascal@13691 211 if (version)
pascal@13691 212 load(&initrdmem, isofilesize);
pascal@13691 213 }
pascal@13691 214
pascal@13691 215 void bootlinux(char *cmdline)
pascal@13691 216 {
pascal@13691 217 #asm
pascal@13691 218 push #SETUP_SEGMENT
pascal@13691 219 pop es
pascal@13691 220 mov eax, _initrd_addr
pascal@13691 221 or eax, eax
pascal@13691 222 jz no_initrd
pascal@13691 223 mov di, #0x218
pascal@13691 224 stosd
pascal@13691 225 mov eax, _initrd_size
pascal@13691 226 stosd
pascal@13691 227 no_initrd:
pascal@13691 228 #endasm
pascal@13691 229 if (cmdline) {
pascal@13691 230 if (version <= 0x201) {
pascal@13691 231 #asm
pascal@13691 232 mov di, #0x0020
pascal@13691 233 mov ax, #0xA33F
pascal@13691 234 stosw
pascal@13691 235 mov ax, #CMDLINE_OFFSET
pascal@13691 236 stosw
pascal@13691 237 #endasm
pascal@13691 238 }
pascal@13691 239 else {
pascal@13691 240 #asm
pascal@13691 241 mov di, #0x0228
pascal@13691 242 mov eax, #SETUP_SEGMENT*16+CMDLINE_OFFSET
pascal@13691 243 stosd
pascal@13691 244 #endasm
pascal@13691 245 }
pascal@13691 246 #asm
pascal@13691 247 xchg ax, di
pascal@13691 248 mov si, .bootlinux.cmdline[bp]
pascal@13691 249 copy:
pascal@13691 250 lodsb
pascal@13691 251 stosb
pascal@13691 252 or al,al
pascal@13691 253 jne copy
pascal@13691 254 #endasm
pascal@13691 255 }
pascal@13691 256 #asm
pascal@13691 257 push es
pascal@13691 258 pop ds
pascal@13691 259 push ds
pascal@13691 260 pop ss
pascal@13691 261 mov sp, #CMDLINE_OFFSET
pascal@13691 262 jmpi 0, #0x9020
pascal@13691 263 #endasm
pascal@13691 264 }