Magellan Linux

Contents of /trunk/linterm_tools/fw_builder/make-nk/boot.S

Parent Directory Parent Directory | Revision Log Revision Log


Revision 658 - (show annotations) (download)
Mon Jan 14 16:57:24 2008 UTC (16 years, 3 months ago) by niro
File size: 10464 byte(s)
initial import

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 " video=nscfb:vmode:1024x768-16,vfreq:75 splash=silent"
426 .ascii " reboot=bios"
427 .byte 0x0
428
429
430 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
431
432 setup_sig1: .word 0xAA55
433 setup_sig2: .word 0x5A5A
434
435 eof: