wok view linld/stuff/src/LOAD.CPP @ rev 20632

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