Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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     .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: