wok annotate linld/stuff/src/LOAD.CPP @ rev 20745

azpainter: update WGET_URL
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Feb 10 10:35:42 2019 +0100 (15 months ago)
parents 57d97be431f4
children cbcb33ee9044
rev   line source
pascal@19515 1 // This file is distributed under GPL
pascal@19515 2
pascal@19515 3 #include "crtl.h"
pascal@19515 4 #include "common.h"
pascal@19515 5
pascal@19515 6 /***************
pascal@19515 7 Memory layout assumed by kernel boot process
pascal@19515 8 --------------------------------------------
pascal@19515 9 Note: claims that kernel setup is relocatable are
pascal@19515 10 still not 100% valid:
pascal@19515 11 bzImage decompressing trashes 10000-8ffff range,
pascal@19515 12 so rm loader -> pm kernel info is lost if it was here...
pascal@19515 13 So I had to stick to 90000.
pascal@19515 14
pascal@19515 15 10000000+------------------------+ <- 256m
pascal@19515 16 | initrd | initrd is at top of mem, but
pascal@19515 17 | | not higher than 256m
pascal@19515 18 +------------------------+
pascal@19515 19 +------------------------+
pascal@19515 20 | bzImage | bzImage is at 1m
pascal@19515 21 | | VCPI/XMS/64k offset tricks used...
pascal@19515 22 00100000+------------------------+ <- 1m
pascal@19515 23 | video, BIOS etc | Do not use.
pascal@19515 24 000A0000+------------------------+
pascal@19515 25 | Reserved for BIOS | Do not use. Reserved for BIOS EBDA.
pascal@19515 26 0009A000+------------------------+ <- stack top for kernel rm code
pascal@19515 27 | Cmdline |
pascal@19515 28 00098000+------------------------+ <- heap top for kernel rm code
pascal@19515 29 | Kernel setup | The kernel real-mode code.
pascal@19515 30 00090200+------------------------+
pascal@19515 31 | Kernel boot sector | The kernel legacy boot sector.
pascal@19515 32 00090000+------------------------+
pascal@19515 33 | Zapped by ungzip | Historically zImages were loaded here
pascal@19515 34 | (zImage once was here) | bzImages use this space for ungzipping
pascal@19515 35 00010000+------------------------+
pascal@19515 36 | Boot loader | <- Boot sector entry point 0000:7C00
pascal@19515 37 00001000+------------------------+
pascal@19515 38 | Reserved for MBR/BIOS |
pascal@19515 39 00000800+------------------------+
pascal@19515 40 | Typically used by MBR |
pascal@19515 41 00000600+------------------------+
pascal@19515 42 | BIOS use only |
pascal@19515 43 00000000+------------------------+
pascal@19515 44 */
pascal@19515 45
pascal@19538 46 struct kernelparams_t {
pascal@20458 47 s8 setup_sects; // 01F1 The size of the setup in sectors
pascal@19515 48 // boot sector is NOT included here
pascal@19515 49 u16 ro_flag; // 01F2 If set, the root is mounted readonly
pascal@19515 50 u16 syssize; // 01F4 DO NOT USE - for bootsect.S use only:
pascal@19515 51 // size of pm part of kernel
pascal@19515 52 // (in 16 byte units, rounded up)
pascal@19515 53 u16 swap_dev; // 01F6 DO NOT USE - obsolete
pascal@19515 54 u16 ram_size; // 01F8 DO NOT USE - for bootsect.S use only:
pascal@19515 55 // if nonzero then kernel
pascal@19515 56 // (driver/block/ramdisk.c: rd_load())
pascal@19515 57 // will try to load the contents for the ramdisk
pascal@19515 58 // from the "root_dev" which MUST then have the
pascal@19515 59 // floppyMAJOR
pascal@19515 60 // The file-system on that floppy must be MINIX
pascal@19515 61 // If rd_load() succeeds it sets the root_dev
pascal@19515 62 // to the ramdisk for mounting it
pascal@19515 63 u16 vid_mode; // 01FA Video mode control
pascal@19515 64 u16 root_dev; // 01FC Default root device number
pascal@19515 65 u16 boot_flag; // 01FE 0xAA55 magic number
pascal@19515 66 u16 jump; // 0200 Jump instruction
pascal@19515 67 u32 header; // 0202 Magic signature "HdrS"
pascal@19515 68 u16 version; // 0206 Boot protocol version supported
pascal@19515 69 u16 realmode_switch_ofs; // 0208 Hook called just before rm->pm
pascal@19515 70 u16 realmode_switch_seg;
pascal@19515 71 u16 start_sys_seg; // 020E
pascal@19515 72 u16 kernel_version; // 020C Points to kernel version string
pascal@19515 73 u8 type_of_loader; // 0210 Boot loader identifier
pascal@19515 74 u8 loadflags; // 0211 Boot protocol option flags
pascal@19515 75 u16 setup_move_size;// 0212 Move to high memory size (used with hooks)
pascal@19515 76 u32 code32_start; // 0214 Boot loader hook (see below)
pascal@19515 77 u32 initrd_buf; // 0218 initrd load address (set by boot loader)
pascal@19515 78 u32 initrd_size; // 021C initrd size (set by boot loader)
pascal@19515 79 u32 bootsect_kludge;// 0220 DO NOT USE - for bootsect.S use only
pascal@19515 80 u16 heap_end_ptr; // 0224 Free memory after setup end
pascal@19515 81 u16 pad1; // 0226 Unused
pascal@19515 82 u32 cmd_line_ptr; // 0228 32-bit pointer to the kernel command line
pascal@19515 83 u8 pad30[0x400-0x22c]; // 022C
pascal@19515 84 // 02D0 up to 32 20-byte mem info structs from
pascal@19515 85 // int 0x15 fn 0xe820
pascal@19515 86 }; //__attribute((packed));
pascal@19515 87
pascal@19538 88 struct first1k_t {
pascal@19538 89 // these two set by rm setup:
pascal@19538 90 u16 curr_curs; // 0000 saved cursor position
pascal@19538 91 u16 ext_mem_size; // 0002 extended memory size in Kb (from int 0x15 fn 0x88)
pascal@19538 92 u8 pad00[0x20-4];
pascal@19538 93 // old-style cmdline (not used in LINLD (yet?))
pascal@19636 94 u32 cl_magic_ofs;
pascal@19636 95 //u16 cl_magic; // 0020 commandline magic number (=0xA33F)
pascal@19636 96 //u16 cl_ofs; // 0022 commandline offset
pascal@19538 97 u8 pad10[0x80-0x24];
pascal@19538 98 // these two set by rm setup:
pascal@19538 99 u8 hd0_disk_par[16]; // 0080 hd0-disk-parameter from intvector 0x41
pascal@19538 100 u8 hd1_disk_par[16]; // 0090 hd1-disk-parameter from intvector 0x46
pascal@19538 101 u8 pad20[0x01e0-0xa0];
pascal@19538 102 // this is set by rm setup:
pascal@19538 103 u32 alt_mem_size; // 01E0 extended memory size in Kb (from int 0x15 fn 0xe801)
pascal@19571 104 u8 pad28[0x01f1-0x1e4];
pascal@19538 105 struct kernelparams_t params;
pascal@19538 106 }; //__attribute((packed));
pascal@19538 107
pascal@19515 108 #if sizeof(first1k_t)!=0x400
pascal@19515 109 #error BUG: Bad first1k
pascal@19515 110 #endif
pascal@19515 111
pascal@19515 112 const u32 HdrS = 'H' + ('d'<<8) + (u32('r')<<16) + (u32('S')<<24);
pascal@19515 113
pascal@19515 114 // register value to launch the kernel real mode code
pascal@19515 115 #ifdef NO386
pascal@19900 116 u32 csip;
pascal@19515 117 extern "C" u16 topseg();
pascal@19515 118 #else
pascal@19900 119 u32 csip=0x90200000;
pascal@19515 120 #define topseg() 0x9000
pascal@19515 121 #endif
pascal@20745 122 u16 rm_size;
pascal@20745 123 static u8 pm_high; // @ = @rm_size + 2, see JUMP.ASM
pascal@20745 124 static u8* rm_buf; // @ = @rm_size + 3, see JUMP.ASM
pascal@20745 125 struct image_himem imgs[2];
pascal@20745 126
pascal@20634 127 u32 base_himem = _1m+_64k;
pascal@19515 128
pascal@19515 129 static const char kernel_file_error[] = "Can't use kernel file";
pascal@19515 130 char* load_kernel() {
pascal@19515 131
pascal@19636 132 struct image_himem *m = &pm;
pascal@20634 133 #define _rm_buf(m) (((u8**)(m))[-1])
pascal@20634 134 #define _pm_high (((u8*)(m))[-3])
pascal@20634 135 #define _rm_size (*(u16*)((u8*)(m)-5))
pascal@19515 136 #ifdef NO386
pascal@20745 137 #define _csip (*(u32*)((u8*)(m)-9))
pascal@19636 138 *((u16 *)&csip+1)=topseg()+0x20;
pascal@20632 139 #else
pascal@20632 140 #define _csip csip
pascal@19515 141 #endif
pascal@19515 142 // Open kernel, read first kb, check it
pascal@19636 143 m->errmsg = kernel_file_error;
pascal@19636 144 open_image(kernel_name, m);
pascal@19515 145
pascal@19515 146 char *version_string;
pascal@19515 147 {
pascal@19538 148 struct kernelparams_t *kernelparams;
pascal@20632 149 kernelparams = &(((first1k_t*) (_rm_buf(m) = (u8 *)malloc_or_die(_32k)))->params);
pascal@19636 150 #define first1k ((first1k_t*)((u8 *)kernelparams-0x1F1))
pascal@19515 151
pascal@20510 152 do {
pascal@19515 153 // Do not use malloc below until heap_top adjustment (see <*>)
pascal@20542 154 if (read(m->fd, rm_buf, 0x200) == 0x200) {
pascal@19515 155
pascal@20542 156 lseekcur(m->fd,-0x200);
pascal@19571 157 if(kernelparams->setup_sects == 0) {
pascal@19515 158 #if 1
pascal@19515 159 if(* (int *) &first1k->pad10[0x3F-0x24] == 0x3AE8) {
pascal@20632 160 _csip+=0xFFE00042;
pascal@19515 161 }
pascal@19515 162 else
pascal@19515 163 #endif
pascal@19538 164 kernelparams->setup_sects=4;
pascal@19515 165 }
pascal@19636 166 if((kernelparams->setup_sects)>=(_32k/512) || // 0th sector not counted
pascal@19636 167 kernelparams->boot_flag != 0xAA55)
pascal@20454 168 die("Not a kernel");
pascal@20632 169 heap_top = _rm_buf(m)+(_rm_size=0x200*(kernelparams->setup_sects+1)); // <*>
pascal@20632 170 m->size -= _rm_size;
pascal@20632 171 m->chunk_size -= _rm_size;
pascal@19515 172
pascal@19515 173 // Read remaining rm loader
pascal@20632 174 if (read(m->fd, rm_buf, _rm_size) == _rm_size) break;
pascal@20510 175 }
pascal@20510 176 die(kernel_file_error);
pascal@20510 177 } while (0);
pascal@19515 178
pascal@19515 179 // Tell rm loader some info
pascal@19515 180
pascal@20528 181 if((int)vid_mode) kernelparams->vid_mode = vid_mode;
pascal@20528 182 if((int)root_dev) kernelparams->root_dev = root_dev;
pascal@20485 183 version_string = "";
pascal@19515 184
pascal@19515 185 #if 1
pascal@19538 186 if(kernelparams->header == HdrS) { // starting linux 1.3.73
pascal@19538 187 if(kernelparams->loadflags & 1) {
pascal@19515 188 #else
pascal@19538 189 if((kernelparams->header != HdrS) || (kernelparams->loadflags & 1) == 0)
pascal@19515 190 die("I can't load bzImage low");
pascal@19515 191 {
pascal@19515 192 {
pascal@19515 193 #endif
pascal@19515 194 pm_high++;
pascal@19515 195
pascal@19515 196 // Hook on int15 to work around fn 88 DOS breakage
pascal@19515 197 hook_int15_88();
pascal@19515 198 }
pascal@19538 199 if(kernelparams->kernel_version)
pascal@19538 200 version_string = (char *) first1k+kernelparams->kernel_version+0x200;
pascal@19538 201 kernelparams->type_of_loader = 0xff; // kernel do not know us (yet :-)
pascal@19538 202 if(kernelparams->version >= 0x201) {
pascal@19515 203 // * offset limit of the setup heap
pascal@19515 204 // heap_end_ptr appears to be relative to the start of setup (ofs 0x0200)
pascal@19538 205 kernelparams->heap_end_ptr = _32k-0x0200;
pascal@19538 206 kernelparams->loadflags |= 0x80; // says to rm loader it's ok to use heap
pascal@19515 207 }
pascal@19515 208 // * if we will ever stop moving ourself to 0x90000
pascal@19515 209 // we must say setup.S how much to move
pascal@19538 210 //kernelparams->setup_move_size = _32k;
pascal@19538 211 if(kernelparams->version >= 0x202) { // starting linux 2.4.0-test3-pre3
pascal@19538 212 kernelparams->cmd_line_ptr = (((u32)(topseg()+0x0800))<<4);
pascal@19515 213 goto cmd_line_ok;
pascal@19515 214 }
pascal@19515 215 }
pascal@19636 216 first1k->cl_magic_ofs = 0x8000A33F;
pascal@19515 217 }
pascal@19515 218
pascal@19515 219 cmd_line_ok:
pascal@19515 220 // Check and enable A20 if needed
pascal@19515 221 enable_a20_or_die();
pascal@19515 222
pascal@19515 223 // Read remaining kernel (pm part)
pascal@19515 224 // Try to load kernel high, maybe even blindly storing it
pascal@19515 225 // in unallocated memory as a last resort
pascal@19515 226
pascal@19571 227 {
pascal@19571 228 struct image_himem *m = &pm;
pascal@20542 229 if((u16)(((m->fallback=(u32((u16(_CS)+0x1FFF)&0xF000)<<4))+m->size)>>4) >
pascal@20632 230 topseg() || _pm_high) {
pascal@20634 231 m->fallback = base_himem;
pascal@19515 232 }
pascal@19515 233
pascal@19571 234 load_image(m);
pascal@19571 235 }
pascal@19515 236 return version_string;
pascal@19515 237 }
pascal@19515 238
pascal@20634 239 struct initrdparams_t {
pascal@20634 240 u32 header; // 0202 Magic signature "HdrS"
pascal@20634 241 u16 version; // 0206 Boot protocol version supported
pascal@20634 242 u16 realmode_switch_ofs; // 0208 Hook called just before rm->pm
pascal@20634 243 u16 realmode_switch_seg;
pascal@20634 244 u16 start_sys_seg; // 020E
pascal@20634 245 u16 kernel_version; // 020C Points to kernel version string
pascal@20634 246 u8 type_of_loader; // 0210 Boot loader identifier
pascal@20634 247 u8 loadflags; // 0211 Boot protocol option flags
pascal@20634 248 u16 setup_move_size;// 0212 Move to high memory size (used with hooks)
pascal@20634 249 u32 code32_start; // 0214 Boot loader hook (see below)
pascal@20634 250 u32 initrd_buf; // 0218 initrd load address (set by boot loader)
pascal@20634 251 u32 initrd_size; // 021C initrd size (set by boot loader)
pascal@20634 252 };
pascal@20634 253
pascal@19515 254 // Read initrd if needed
pascal@19515 255 void load_initrd() {
pascal@19515 256 struct image_himem *m = &initrd;
pascal@19899 257 if (!initrd_name && !m->fd) return;
pascal@20538 258 #if defined(__BORLANDC__) && defined(NO386)
pascal@20538 259 #pragma option -3
pascal@20538 260 asm{
pascal@20538 261 .386p
pascal@20538 262 }
pascal@20538 263 #endif
pascal@19636 264 m->errmsg = "Can't use initrd file";
pascal@19636 265
pascal@19636 266 open_image(initrd_name, m);
pascal@19636 267
pascal@20542 268 if ((m->fallback=(memtop()-m->size)&(~PAGE_MASK))-m[-1].fallback < m[-1].size) {
pascal@19636 269 close(m->fd);
pascal@19538 270 puts(m->errmsg);
pascal@19515 271 return;
pascal@19515 272 }
pascal@19515 273
pascal@19515 274 load_image(m);
pascal@20634 275
pascal@20634 276 struct initrdparams_t *initrdparams = ((struct initrdparams_t *)&(((first1k_t*) _rm_buf(m-1))->params.header));
pascal@20634 277 if(initrdparams->header == HdrS) {
pascal@20634 278 initrdparams->initrd_buf = m->fallback;
pascal@20634 279 initrdparams->initrd_size = m->size;
pascal@19515 280 }
pascal@19515 281 }