Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


moved guest files to kernel image
[palacios.git] / palacios / src / geekos / fd_boot.asm
1 ; Boot sector for GeekOS
2 ; Copyright (c) 2001,2004 David H. Hovemeyer <daveho@cs.umd.edu>
3 ; Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
4 ; $Revision: 1.6 $
5
6 ; This is free software.  You are permitted to use,
7 ; redistribute, and modify it as specified in the file "COPYING".
8
9 ; Loads setup code and a program image from sectors 1..n of a floppy
10 ; and executes the setup code (which will in turn execute
11 ; the program image).
12
13 ; Some of this code is adapted from Kernel Toolkit 0.2
14 ; and Linux version 2.2.x, so the following copyrights apply:
15
16 ; Copyright (C) 1991, 1992 Linus Torvalds
17 ; modified by Drew Eckhardt
18 ; modified by Bruce Evans (bde)
19 ; adapted for Kernel Toolkit by Luigi Sgro
20
21 %include "defs.asm"
22
23 ; Pad to desired offset from start symbol.
24 ;    Usage: Pad_From_Symbol offset, symbol
25 %macro Pad_From_Symbol 2
26         times (%1 - ($ - %2)) db 0
27 %endmacro
28
29 ; ----------------------------------------------------------------------
30 ; The actual code
31 ; ----------------------------------------------------------------------
32
33 [BITS 16]
34 [ORG 0x0]
35
36 BeginText:      ; needed to calculate padding bytes to fill the sector
37
38         ; Copy the boot sector into INITSEG.
39         mov     ax, BOOTSEG
40         mov     ds, ax                  ; source segment for string copy
41         xor     si, si                  ; source index for string copy
42         mov     ax, INITSEG
43         mov     es, ax                  ; destination segment for string copy
44         xor     di, di                  ; destination index for string copy
45         cld                             ; clear direction flag
46         mov     cx, 256                 ; number of words to copy
47         rep     movsw                   ; copy 512 bytes
48
49         jmp     INITSEG:after_move
50
51 after_move:
52         ; Now we're executing in INITSEG
53
54
55         ; We want the data segment to refer to INITSEG
56         ; (since we've defined variables in the same place as the code)
57         mov     ds, ax                  ; ax still contains INITSEG
58
59         ; Put the stack in the place where we were originally loaded.
60         ; By definition, there is nothing important there now.
61         mov     ax, 0
62         mov     ss, ax
63         mov     sp, (BOOTSEG << 4) + 512 - 2
64
65
66 load_setup:
67         ; Load the setup code.
68         mov     ax, word [setupStart]
69         mov     word [sec_count], ax
70         add     ax, [setupSize]
71         mov     word [max_sector], ax
72 .again:
73         mov     ax, [sec_count]
74         push    ax                      ; 1st param to ReadSector (log sec num)
75         push    word SETUPSEG           ; 2nd param to ReadSector (seg base)
76         sub     ax, [setupStart]        ; convert to 0-indexed
77         shl     ax, 9                   ; multiply by 512
78         push    ax                      ;  ...to get 3rd param (byte offset)
79
80         ; read the sector from the floppy
81         call    ReadSector
82         add     sp, 6                   ; clear 3 word params
83
84         ; on to next sector
85         inc     word [sec_count]
86
87         ; are we done?
88         mov     bx, word [max_sector]
89         cmp     word [sec_count], bx
90         jl      .again
91
92
93         
94 load_kernel:
95         ; Load the kernel image from sectors KERN_START_SEC..n of the
96         ; floppy into memory at KERNSEG.  Note that there are 128 sectors
97         ; per 64K segment.  So, when figuring out which segment to
98         ; load the sector into, we shift right by 7 bits (which is
99         ; equivalent to dividing by 128).
100
101         ; Figure out start sector and max sector
102
103         mov     ax, word [kernelStart]
104         mov     word [sec_count], ax
105         add     ax, word [kernelSize]
106         mov     word [max_sector], ax
107
108         
109 .again2:
110
111         mov     ax, [sec_count]         ; logical sector on the floppy
112         push    ax                      ; 1st param to ReadSector (log sec num)
113
114 ;       mov     dx, ax
115 ;       call    PrintHex
116 ;       call    PrintNL
117
118         mov     ax, VMSEG               ;  ...to get base relative to VMSEG
119         push    ax                      ; 2nd param to ReadSector (seg base)
120         
121 ;       mov     dx, ax          ; 
122 ;       call    PrintHex
123 ;       call    PrintNL
124
125         mov     ax, 2000h               ; Always write at the start of the segment
126         push    ax              ; 3rd parameter
127
128 ;       mov     dx, ax
129 ;       call    PrintHex
130 ;       call    PrintNL
131
132         ; read the sector from the floppy
133         call    ReadSector
134         add     sp, 6                   ; clear 3 word params
135
136         push    VMSEG
137         pop     es
138
139 ;       mov     dx, word [es:2000h] ;
140 ;       call    PrintHex
141 ;       call    PrintNL
142         
143         
144
145 ; execute bios call
146
147         push    cx
148         push    si
149         push    bx
150         push    es              ; 
151
152         push    cs
153         pop     es
154         mov     si, bootsect_gdt
155         mov     ah, 87h
156
157         mov     cx, 100h
158
159         int     0x15
160         
161         adc     ax, 0
162
163 ;       mov     dx, ax  
164 ;       call    PrintHex
165 ;       call    PrintNL
166
167
168
169         pop     es              ;
170         pop     bx
171         pop     si
172         pop     cx
173         
174         ; on to next sector
175         inc     word [sec_count]
176
177
178         ; update the low->high copy table for the bios
179 ;       mov     ax, word [bootsect_src_base] ;
180 ;       add     ax, 512
181 ;       mov     dx,ax;
182 ;       call    PrintHex
183 ;       adc     byte [bootsect_src_base+2], 0
184 ;       mov     word [bootsect_src_base],ax
185
186         mov     ax, word [bootsect_dst_base] ;
187         add     ax, 512
188         adc     byte [bootsect_dst_base+2], 0
189         mov     word [bootsect_dst_base],ax
190         
191         ; have we loaded all of the sectors?
192
193         mov     bx, word [max_sector]
194         cmp     word [sec_count], bx
195
196
197 .stall
198 ;       jmp     .skip
199         jl      .again2
200
201 .skip
202         ; Now we've loaded the setup code and the kernel image.
203         ; Jump to setup code.
204         jmp     SETUPSEG:0
205
206 ; Read a sector from the floppy drive.
207 ; This code (and the rest of this boot sector) will have to
208 ; be re-written at some point so it reads more than one
209 ; sector at a time.
210 ;
211 ; Parameters:
212 ;     - "logical" sector number   [bp+8]
213 ;     - destination segment       [bp+6]
214 ;     - destination offset        [bp+4]
215 ReadSector:
216         push    bp                      ; set up stack frame
217         mov     bp, sp                  ; "
218         pusha                           ; save all registers
219
220 %if 0
221 ; debug params
222         mov     dx, [bp+8]
223         call    PrintHex
224         call    PrintNL
225         mov     dx, [bp+6]
226         call    PrintHex
227         call    PrintNL
228         mov     dx, [bp+4]
229         call    PrintHex
230         call    PrintNL
231 %endif
232
233         ; Sector = log_sec % SECTORS_PER_TRACK
234         ; Head = (log_sec / SECTORS_PER_TRACK) % HEADS
235         mov     ax, [bp+8]              ; get logical sector number from stack
236         xor     dx, dx                  ; dx is high part of dividend (== 0)
237         mov     bx, SECTORS_PER_TRACK   ; divisor
238         div     bx                      ; do the division
239         mov     [sec], dx               ; sector is the remainder
240         and     ax, 1                   ; same as mod by HEADS==2 (slight hack)
241         mov     [head], ax
242
243         ; Track = log_sec / (SECTORS_PER_TRACK*HEADS)
244         mov     ax, [bp+8]              ; get logical sector number again
245         xor     dx, dx                  ; dx is high part of dividend
246         mov     bx, SECTORS_PER_TRACK*2 ; divisor
247         div     bx                      ; do the division
248         mov     [track], ax             ; track is quotient
249
250 %if 0
251 ; debugging code
252         mov     dx, [sec]
253         call    PrintHex
254         call    PrintNL
255         mov     dx, [head]
256         call    PrintHex
257         call    PrintNL
258         mov     dx, [track]
259         call    PrintHex
260         call    PrintNL
261 %endif
262
263         ; Now, try to actually read the sector from the floppy,
264         ; retrying up to 3 times.
265
266         mov     [num_retries], byte 0
267
268 .again:
269         mov     ax, [bp+6]              ; dest segment...
270         mov     es, ax                  ;   goes in es
271         mov     ax, (0x02 << 8) | 1     ; function = 02h in ah,
272                                         ;   # secs = 1 in al
273         mov     bx, [track]             ; track number...
274         mov     ch, bl                  ;   goes in ch
275         mov     bx, [sec]               ; sector number...
276         mov     cl, bl                  ;   goes in cl...
277         inc     cl                      ;   but it must be 1-based, not 0-based
278         mov     bx, [head]              ; head number...
279         mov     dh, bl                  ;   goes in dh
280         xor     dl, dl                  ; hard code drive=0
281         mov     bx, [bp+4]              ; offset goes in bx
282                                         ;   (es:bx points to buffer)
283         ; Call the BIOS Read Diskette Sectors service
284         int     0x13
285         
286         ; If the carry flag is NOT set, then there was no error
287         ; and we're done.
288         jnc     .done
289
290         ; Error - code stored in ah
291         mov     dx, ax
292         call PrintHex
293         inc     byte [num_retries]
294         cmp     byte [num_retries], 3
295         jne     .again
296
297         ; If we got here, we failed thrice, so we give up
298         mov     dx, 0xdead
299         call    PrintHex
300 .here:  jmp     .here
301
302 .done:
303         popa                            ; restore all regisiters
304         pop     bp                      ; leave stack frame
305         ret
306
307 ; Include utility routines:
308 ;%include "util.asm"
309 ; REPLACED WITH FOLLOWING WHICH MUST BE COMPILED 16 FOR USE IN THIS CODE
310 PrintHex:
311         pusha
312         mov   cx, 4             ; 4 hex digits
313 .PrintDigit:
314         rol   dx, 4             ; rotate so that lowest 4 bits are used
315         mov   ax, 0E0Fh         ; ah = request, al = mask for nybble
316         and   al, dl
317         add   al, 90h           ; convert al to ascii hex (four instructions)
318         daa                     ; I've spent 1 hour to understand how it works..
319         adc   al, 40h
320         daa
321         int   10h
322         loop  .PrintDigit
323         popa
324         ret
325
326 ; Print a newline.
327 PrintNL:                        ; print CR and NL
328         push    ax
329         mov     ax, 0E0Dh       ; CR
330         int     10h
331         mov     al, 0Ah         ; LF
332         int     10h
333         pop     ax
334         ret
335
336
337
338 ; ----------------------------------------------------------------------
339 ; Variables
340 ; ----------------------------------------------------------------------
341
342 ; These are used by ReadSector
343 head: dw 0
344 track: dw 0
345 sec: dw 0
346 num_retries: db 0
347
348 ; Used for loops reading sectors from floppy
349 sec_count: dw 0
350 max_sector: dw 0
351
352
353
354
355 bootsect_gdt:
356         dw      0,0,0,0
357         dw      0,0,0,0
358 bootsect_src:
359         dw      0xffff                
360 bootsect_src_base:
361         db      0,0x20,0x08             ;       ! base = 0x082000 
362         db      0x93            ;       ! typbyte
363         dw      0               ;       ! limit16,base24 =0
364 bootsect_dst:
365         dw      0xffff
366 bootsect_dst_base:
367         db      0,0,0x10        ;       ! base = 0x100000
368         db      0x93            ;       ! typbyte
369         dw      0               ;       ! limit16,base24 =0
370         dw      0,0,0,0         ;       ! BIOS CS
371         dw      0,0,0,0         ;       ! BIOS DS
372
373
374 ; Padding to make the PFAT Boot Record sit just before the BIOS signature.
375 ;Pad_From_Symbol PFAT_BOOT_RECORD_OFFSET, BeginText
376
377 ; PFAT boot record
378 ; Describes how to load the setup program and kernel.
379 ; The default values are appropriate for creating a boot
380 ; floppy by concatenating the boot sector, setup program,
381 ; and kernel image.  The buildFat program will change
382 ; these values if the boot floppy is formatted as a PFAT
383 ; filesystem.
384         dw      0
385         dw      0
386
387         dw      0
388         dw      0
389
390         dw      0
391         dw      0
392
393         dw      0
394         dw      0
395
396         dw      0
397         dw      0
398
399 ;; part of pfat boot record
400 setupStart:             
401         dw      1                       ; by default, setup is at first sector  
402
403 ;; part of pfat boot record
404 setupSize:
405         dw      NUM_SETUP_SECTORS       ; number of sectors in setup
406
407 ;; part of pfat boot record
408 kernelStart:
409         dw      1+NUM_SETUP_SECTORS     ; default start sector for kernel
410
411 ;; part of pfat boot record
412 kernelSize:
413         dw      NUM_KERN_SECTORS
414
415
416
417
418         ; Finish by writing the BIOS signature to mark this as
419 ; a valid boot sector.
420 Pad_From_Symbol BIOS_SIGNATURE_OFFSET, BeginText
421 Signature   dw 0xAA55   ; BIOS controls this to ensure this is a boot sector