Contents of /trunk/linterm_tools/fw_builder/make-nk/boot.S
Parent Directory | Revision Log
Revision 661 -
(show annotations)
(download)
Mon Jan 14 17:27:56 2008 UTC (16 years, 8 months ago) by niro
File size: 10554 byte(s)
Mon Jan 14 17:27:56 2008 UTC (16 years, 8 months ago) by niro
File size: 10554 byte(s)
added cvsignore
1 | ! 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 | ; .ascii " root=/dev/sda1 lang=us quiet tz=Europe/Amsterdam" |
425 | .ascii " root=/dev/ram0 init=/linuxrc ramdisk_size=16384 " |
426 | .ascii " video=nscfb:vmode:1024x768-16,vfreq:75 splash=silent" |
427 | .ascii " dousb nopata " |
428 | .ascii " reboot=bios" |
429 | .byte 0x0 |
430 | |
431 | |
432 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
433 | |
434 | setup_sig1: .word 0xAA55 |
435 | setup_sig2: .word 0x5A5A |
436 | |
437 | eof: |