Annotation of /trunk/linterm_tools/fw_builder/make-nk/boot.S
Parent Directory | Revision Log
Revision 661 -
(hide annotations)
(download)
Mon Jan 14 17:27:56 2008 UTC (16 years, 4 months ago) by niro
File size: 10554 byte(s)
Mon Jan 14 17:27:56 2008 UTC (16 years, 4 months ago) by niro
File size: 10554 byte(s)
added cvsignore
1 | niro | 658 | ! Linux kernel setup for WYSE Winterm devices (at least WT3320SE) |
2 | ! Based on setup code for AMD Élan devices by Anders Larsen | ||
3 | ! | ||
4 | ! Winterm version Copyright (C) 2005 by Wilmer van der Gaast | ||
5 | ! | ||
6 | ! Portions are Copyright (C) 2000 by Denis Hatebur and TueViT Essen | ||
7 | ! Portions are Copyright (C) 2000 by Anders Larsen and Baumer Ident GmbH | ||
8 | ! | ||
9 | ! Derived from setup.S Copyright (C) 1991-1997 Linus Torvalds et al. | ||
10 | ! | ||
11 | ! This program is free software; you can redistribute it and/or modify | ||
12 | ! it under the terms of the GNU General Public License as published by | ||
13 | ! the Free Software Foundation; either version 2 of the License, or | ||
14 | ! (at your option) any later version. | ||
15 | ! | ||
16 | ! This program is distributed in the hope that it will be useful, | ||
17 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | ! GNU General Public License for more details. | ||
20 | ! | ||
21 | ! You should have received a copy of the GNU General Public License | ||
22 | ! along with this program. If not, write to the Free Software | ||
23 | ! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | |||
25 | #include <asm/segment.h> | ||
26 | |||
27 | .org 0x0 | ||
28 | .text | ||
29 | |||
30 | USE32 | ||
31 | entry CODE1 | ||
32 | |||
33 | .org 0x1e0 | ||
34 | |||
35 | ; Note: This is the size of *extended* memory, i.e. the memory above | ||
36 | ; the 1M mark! | ||
37 | mem_size: .long 0 | ||
38 | |||
39 | .org 0x1f1 | ||
40 | |||
41 | .byte 0 ; setup_sects | ||
42 | .word 0 ; read-only rootfs? | ||
43 | .long 0 ; syssize (not necessary in protocol 2.02) | ||
44 | .word 0 ; ram_size (don't use!) | ||
45 | .word 0xffff ; vid_mode | ||
46 | .word 0x0100 ; root_dev | ||
47 | .word 0xaa55 ; magic! | ||
48 | |||
49 | start: | ||
50 | .word 0 | ||
51 | ! ------------------------ start of header -------------------------------- | ||
52 | ! | ||
53 | ! SETUP-header, must start at CS:2 (old 0x9020:2) | ||
54 | ! | ||
55 | .ascii "HdrS" ! Signature for SETUP-header | ||
56 | .word 0x0202 ! Version number of header format | ||
57 | ! (must be >= 0x0105 | ||
58 | ! else old loadlin-1.5 will fail) | ||
59 | realmode_swtch: .word 0,0 ! default_switch,SETUPSEG | ||
60 | start_sys_seg: .word 0x1000 | ||
61 | .word kernel_version !pointing to kernel version string | ||
62 | ! note: above part of header is compatible with loadlin-1.5 (header v1.5), | ||
63 | ! must not change it | ||
64 | |||
65 | type_of_loader: .byte 0xff ! = 0, old one (LILO, Loadlin, | ||
66 | ! Bootlin, SYSLX, bootsect...) | ||
67 | ! else it is set by the loader: | ||
68 | ! 0xTV: T=0 for LILO | ||
69 | ! T=1 for Loadlin | ||
70 | ! T=2 for bootsect-loader | ||
71 | ! T=3 for SYSLX | ||
72 | ! T=4 for ETHERBOOT | ||
73 | ! V = version | ||
74 | wloadflags: ! flags, unused bits must be zero (RFU) | ||
75 | .byte 0x01 | ||
76 | |||
77 | |||
78 | setup_move_size: .word 0x8000 ! size to move, when we (setup) are not | ||
79 | ! loaded at 0x90000. We will move ourselves | ||
80 | ! to 0x90000 then just before jumping into | ||
81 | ! the kernel. However, only the loader | ||
82 | ! know how much of data behind us also needs | ||
83 | ! to be loaded. | ||
84 | code32_start: ! here loaders can put a different | ||
85 | .long 0x100000 ! 0x100000 = default for big kernel | ||
86 | |||
87 | |||
88 | ramdisk_image: .long 0 ! address of loaded ramdisk image | ||
89 | ! Here the loader (or kernel generator) puts | ||
90 | ! the 32-bit address were it loaded the image. | ||
91 | ! This only will be interpreted by the kernel. | ||
92 | ramdisk_size: .long 0 ! its size in bytes | ||
93 | bootsect_kludge: | ||
94 | .word 0,0 | ||
95 | heap_end_ptr: .word 0x9010+eof/16 ! space from here (exclusive) down to | ||
96 | ! end of setup code can be used by setup | ||
97 | ! for local heap purposes. | ||
98 | |||
99 | ! ------------------------ end of header ---------------------------------- | ||
100 | |||
101 | |||
102 | |||
103 | |||
104 | .org 0x1000 | ||
105 | |||
106 | start_of_setup: | ||
107 | |||
108 | CODE1: | ||
109 | cli ! Disable Interrupts | ||
110 | |||
111 | call nl_out | ||
112 | |||
113 | mov al, #'W | ||
114 | call ch_out | ||
115 | mov al, #'I | ||
116 | call ch_out | ||
117 | |||
118 | mov al, #0x80 | ||
119 | out #0x70, al ! Disable NMIs | ||
120 | |||
121 | mov al, #'L | ||
122 | call ch_out | ||
123 | call ch_out | ||
124 | mov al, #'O | ||
125 | call ch_out | ||
126 | |||
127 | call nl_out | ||
128 | |||
129 | mov esi, kernel_version+0x90000 | ||
130 | call str_out | ||
131 | call nl_out | ||
132 | |||
133 | mov esi, params_head+0x90000 | ||
134 | call str_out | ||
135 | mov esi, kernelparam+0x90000 | ||
136 | call str_out | ||
137 | call nl_out | ||
138 | |||
139 | mov eax, kernelparam+0x90000 | ||
140 | mov [0x90228], eax | ||
141 | |||
142 | ; Only do memory detection (and initrd move) if it's not specified yet | ||
143 | mov eax, [mem_size+0x90000] | ||
144 | or eax, eax | ||
145 | jz do_mem_detect | ||
146 | |||
147 | ; Hurray for indirect jumps... | ||
148 | mov ecx, skip_mem_detect+0x90000 | ||
149 | jmp ecx | ||
150 | |||
151 | do_mem_detect: | ||
152 | mov esi, memcount_msg+0x90000 | ||
153 | call str_out | ||
154 | |||
155 | ; Disable memory caching for the memory test, it might spoil the | ||
156 | ; results | ||
157 | mov eax, cr0 | ||
158 | or eax, 0x40000000 | ||
159 | mov cr0, eax | ||
160 | wbinvd | ||
161 | |||
162 | ; Start testing memory at the 8MB mark, so we assume there is at | ||
163 | ; least that much (most Winterms have at least 32MB anyway) | ||
164 | mov edi, 8*1048576-4 | ||
165 | memsize_loop: | ||
166 | mov eax, [edi] | ||
167 | xor eax, 0x55555555 ; This part is kind of fragile, mov [edi], eax && | ||
168 | xor [edi], 0x55555555 ; cmp [edi], eax always returns ZF, even if [edi] | ||
169 | cmp eax, [edi] ; is not memory, for example. This works though. | ||
170 | jne memsize_found | ||
171 | xor [edi], 0x55555555 ; Restore memory, there might be an initrd here. | ||
172 | add edi, 65536 | ||
173 | jmp memsize_loop | ||
174 | memsize_found: | ||
175 | sub edi, 65532 | ||
176 | mov eax, edi | ||
177 | call hex_out | ||
178 | |||
179 | ; Kernel wants this value in 1K blocks, and not counting "conventional" | ||
180 | ; memory. | ||
181 | shr eax, 10 | ||
182 | sub eax, 1024 | ||
183 | mov [mem_size+0x90000], eax | ||
184 | |||
185 | ; nl_out touches al, so don't do this earlier | ||
186 | call nl_out | ||
187 | |||
188 | ; Turn memory cache back on, or the rest will be sloooooow :-) | ||
189 | mov eax, cr0 | ||
190 | and eax, 0x9fffffff | ||
191 | mov cr0, eax | ||
192 | |||
193 | ; Now let's see, do we have a RAM-disk? If so, we should try to keep | ||
194 | ; it as high in memory as possible. Don't start at the first byte with | ||
195 | ; moving, this would make a mess if there's an overlap. | ||
196 | ; We'll go backwards. | ||
197 | cmp dword [ramdisk_image+0x90000], 0 | ||
198 | jz skip_mem_detect | ||
199 | |||
200 | mov esi, rdmove_msg+0x90000 | ||
201 | call str_out | ||
202 | |||
203 | mov esi, [ramdisk_image+0x90000] | ||
204 | add esi, [ramdisk_size+0x90000] | ||
205 | sub esi, 4 | ||
206 | |||
207 | ; edi still contains the memory size in bytes! | ||
208 | sub edi, [ramdisk_size+0x90000] | ||
209 | and edi, 0xfffe0000 | ||
210 | mov [ramdisk_image+0x90000], edi ; Save the position now already | ||
211 | add edi, [ramdisk_size+0x90000] | ||
212 | sub edi, 4 | ||
213 | |||
214 | ; Count the number of DWORDS we have to move | ||
215 | mov ecx, [ramdisk_size+0x90000] | ||
216 | add ecx, 3 | ||
217 | shr ecx, 2 | ||
218 | |||
219 | std | ||
220 | rep | ||
221 | movsd | ||
222 | cld | ||
223 | |||
224 | ; Dump the new position. Not too useful, but nice for debugging. | ||
225 | mov eax, [ramdisk_image+0x90000] | ||
226 | call hex_out | ||
227 | call nl_out | ||
228 | |||
229 | skip_mem_detect: | ||
230 | ; Old place for memory size, don't know if any recent kernel really | ||
231 | ; cares, but just to be sure.. | ||
232 | mov eax, [mem_size+0x90000] | ||
233 | mov [0x90002], ax | ||
234 | |||
235 | ; Set up IDT/GDTs that are useful for the kernel | ||
236 | seg ds | ||
237 | lidt [idt_48+0x90000] ! load idt with 0,0 | ||
238 | seg ds | ||
239 | lgdt [gdt_48+0x90000] ! load gdt with whatever appropriate | ||
240 | |||
241 | ! make sure any possible coprocessor is properly reset.. | ||
242 | |||
243 | xor ax,ax | ||
244 | out #0xf0,al | ||
245 | call delay | ||
246 | out #0xf1,al | ||
247 | call delay | ||
248 | |||
249 | ! well, that went ok, I hope. Now we have to reprogram the interrupts :-( | ||
250 | ! we put them right after the intel-reserved hardware interrupts, at | ||
251 | ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really | ||
252 | ! messed this up with the original PC, and they haven't been able to | ||
253 | ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f, | ||
254 | ! which is used for the internal hardware interrupts as well. We just | ||
255 | ! have to reprogram the 8259's, and it isn't fun. | ||
256 | |||
257 | mov al,#0x11 ! initialization sequence | ||
258 | out #0x20,al ! send it to 8259A-1 | ||
259 | call delay | ||
260 | out #0xA0,al ! and to 8259A-2 | ||
261 | call delay | ||
262 | mov al,#0x20 ! start of hardware int's (0x20) | ||
263 | out #0x21,al | ||
264 | call delay | ||
265 | mov al,#0x28 ! start of hardware int's 2 (0x28) | ||
266 | out #0xA1,al | ||
267 | call delay | ||
268 | mov al,#0x04 ! 8259-1 is master | ||
269 | out #0x21,al | ||
270 | call delay | ||
271 | mov al,#0x02 ! 8259-2 is slave | ||
272 | out #0xA1,al | ||
273 | call delay | ||
274 | mov al,#0x01 ! 8086 mode for both | ||
275 | out #0x21,al | ||
276 | call delay | ||
277 | out #0xA1,al | ||
278 | call delay | ||
279 | mov al,#0xFF ! mask off all interrupts for now | ||
280 | out #0xA1,al | ||
281 | call delay | ||
282 | mov al,#0xFB ! mask all irq's but irq2 which | ||
283 | out #0x21,al ! is cascaded | ||
284 | |||
285 | mov esi, start_linux+0x90000 | ||
286 | call str_out | ||
287 | |||
288 | mov bx, #0 | ||
289 | mov esi, #0x90000 | ||
290 | |||
291 | ; JMP NEW_CS:00100000 | ||
292 | db 0xea | ||
293 | dd 0x100000 | ||
294 | dw 0x10 | ||
295 | |||
296 | ! | ||
297 | ! Delay is needed after doing I/O | ||
298 | ! | ||
299 | delay: | ||
300 | .word 0x00eb ! jmp $+2 | ||
301 | ret | ||
302 | |||
303 | !****************************************************** | ||
304 | ! Outputs Character: AL -> COM1 | ||
305 | !****************************************************** | ||
306 | ch_out: | ||
307 | ! ret | ||
308 | push eax | ||
309 | |||
310 | mov eax, #0x00008000 | ||
311 | loop3: sub eax, #0x1 | ||
312 | jnz loop3 | ||
313 | |||
314 | mov dx, #0x3f8+0x5 | ||
315 | ch_w: in al, dx | ||
316 | and al, #0x40 | ||
317 | jz ch_w | ||
318 | |||
319 | pop eax | ||
320 | |||
321 | ch_outw: | ||
322 | mov dx, #0x3f8 | ||
323 | out dx, al ! serial out .... only try | ||
324 | ret | ||
325 | |||
326 | !****************************************************** | ||
327 | ! Outputs a \r\n | ||
328 | !****************************************************** | ||
329 | nl_out: | ||
330 | mov al, 0x0d | ||
331 | call ch_out | ||
332 | mov al, 0x0a | ||
333 | call ch_out | ||
334 | ret | ||
335 | |||
336 | !****************************************************** | ||
337 | ! Outputs a String: [ESI] -> COM1 | ||
338 | !****************************************************** | ||
339 | str_out: | ||
340 | lodsb | ||
341 | or al, al | ||
342 | jz str_out_end | ||
343 | call ch_out | ||
344 | jmp str_out | ||
345 | str_out_end: | ||
346 | ret | ||
347 | |||
348 | !****************************************************** | ||
349 | ! Outputs a Hex number: EAX -> COM | ||
350 | !****************************************************** | ||
351 | hex_out: | ||
352 | mov ecx, 8 | ||
353 | |||
354 | ho_loop: | ||
355 | rol eax, #4 | ||
356 | push ax | ||
357 | and al, #0x0f | ||
358 | add al, #'0 | ||
359 | cmp al, #'9 | ||
360 | jbe ho_1 | ||
361 | add al, #7 | ||
362 | ho_1: call ch_out | ||
363 | pop ax | ||
364 | loop ho_loop | ||
365 | |||
366 | push ax | ||
367 | mov al, #0x20 | ||
368 | call ch_out | ||
369 | pop ax | ||
370 | |||
371 | ret | ||
372 | |||
373 | !****************************************************** | ||
374 | !**** D A T A ***************************************** | ||
375 | !****************************************************** | ||
376 | |||
377 | gdt_len: dw 0 | ||
378 | gdt_base: dd 0 | ||
379 | |||
380 | kernel_version: .ascii "Linux " | ||
381 | .ascii " " ; version goes here | ||
382 | .byte 0x0 | ||
383 | |||
384 | start_linux: .word 0x0a0d | ||
385 | .ascii "Starting Linux..." | ||
386 | .word 0x0a0d | ||
387 | .byte 0x0 | ||
388 | |||
389 | params_head: .ascii "Kernel parameters: " | ||
390 | .byte 0x0 | ||
391 | |||
392 | memcount_msg: .ascii "Counting memory... " | ||
393 | .byte 0x0 | ||
394 | |||
395 | rdmove_msg: .ascii "Moving initrd... " | ||
396 | .byte 0x0 | ||
397 | |||
398 | .align 16 | ||
399 | |||
400 | gdt: .word 0,0,0,0 | ||
401 | .word 0,0,0,0 | ||
402 | |||
403 | .word 0xFFFF ! 4Gb - (0x100000*0x1000 = 4Gb) | ||
404 | .word 0x0000 ! base address=0 | ||
405 | .word 0x9A00 ! code read/exec | ||
406 | .word 0x00CF ! granularity=4096, 386 (+5th nibble of limit) | ||
407 | |||
408 | .word 0xFFFF ! 4Gb - (0x100000*0x1000 = 4Gb) | ||
409 | .word 0x0000 ! base address=0 | ||
410 | .word 0x9200 ! data read/write | ||
411 | .word 0x00CF ! granularity=4096, 386 (+5th nibble of limit) | ||
412 | gdt_end: .word 0 | ||
413 | |||
414 | idt_48: .word 0 ! idt limit=0 | ||
415 | .long 0 ! idt base=0L | ||
416 | |||
417 | gdt_48: .word gdt_end-gdt ! | ||
418 | .long 0x90000+gdt ! gdt base = 0X9xxxx | ||
419 | |||
420 | |||
421 | .byte 0x0 | ||
422 | kernelparam: ;.ascii "console=ttyS0,38400N8" | ||
423 | ; .ascii " root=/dev/ram0 rw " | ||
424 | niro | 661 | ; .ascii " root=/dev/sda1 lang=us quiet tz=Europe/Amsterdam" |
425 | .ascii " root=/dev/ram0 init=/linuxrc ramdisk_size=16384 " | ||
426 | niro | 658 | .ascii " video=nscfb:vmode:1024x768-16,vfreq:75 splash=silent" |
427 | niro | 661 | .ascii " dousb nopata " |
428 | niro | 658 | .ascii " reboot=bios" |
429 | .byte 0x0 | ||
430 | |||
431 | |||
432 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
433 | |||
434 | setup_sig1: .word 0xAA55 | ||
435 | setup_sig2: .word 0x5A5A | ||
436 | |||
437 | eof: |