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.


(no commit message)
[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.1.1.1 $
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         ; We want the data segment to refer to INITSEG
55         ; (since we've defined variables in the same place as the code)
56         mov     ds, ax                  ; ax still contains INITSEG
57
58         ; Put the stack in the place where we were originally loaded.
59         ; By definition, there is nothing important there now.
60         mov     ax, 0
61         mov     ss, ax
62         mov     sp, (BOOTSEG << 4) + 512 - 2
63
64 load_setup:
65         ; Load the setup code.
66         mov     ax, word [setupStart]
67         mov     word [sec_count], ax
68         add     ax, [setupSize]
69         mov     word [max_sector], ax
70 .again:
71         mov     ax, [sec_count]
72         push    ax                      ; 1st param to ReadSector (log sec num)
73         push    word SETUPSEG           ; 2nd param to ReadSector (seg base)
74         sub     ax, [setupStart]        ; convert to 0-indexed
75         shl     ax, 9                   ; multiply by 512
76         push    ax                      ;  ...to get 3rd param (byte offset)
77
78         ; read the sector from the floppy
79         call    ReadSector
80         add     sp, 6                   ; clear 3 word params
81
82         ; on to next sector
83         inc     word [sec_count]
84
85         ; are we done?
86         mov     bx, word [max_sector]
87         cmp     word [sec_count], bx
88         jl      .again
89
90 load_kernel:
91         ; Load the kernel image from sectors KERN_START_SEC..n of the
92         ; floppy into memory at KERNSEG.  Note that there are 128 sectors
93         ; per 64K segment.  So, when figuring out which segment to
94         ; load the sector into, we shift right by 7 bits (which is
95         ; equivalent to dividing by 128).
96
97         ; Figure out start sector and max sector
98         mov     ax, word [kernelStart]
99         mov     word [sec_count], ax
100         add     ax, word [kernelSize]
101         mov     word [max_sector], ax
102 .again:
103         mov     ax, [sec_count]         ; logical sector on the floppy
104         push    ax                      ; 1st param to ReadSector (log sec num)
105         sub     ax, [kernelStart]       ; convert to 0-indexed
106         mov     cx, ax                  ; save in cx
107         shr     ax, 7                   ; divide by 128
108         shl     ax, 12                  ;  ...and multiply by 0x1000
109         add     ax, KERNSEG             ;  ...to get base relative to KERNSEG
110         push    ax                      ; 2nd param to ReadSector (seg base)
111         and     cx, 0x7f                ; mod sector by 128
112         shl     cx, 9                   ;  ...and multiply by 512
113         push    cx                      ; to get offset in segment (3rd parm)
114
115         ; read the sector from the floppy
116         call    ReadSector
117         add     sp, 6                   ; clear 3 word params
118
119         ; on to next sector
120         inc     word [sec_count]
121
122         ; have we loaded all of the sectors?
123         mov     bx, word [max_sector]
124         cmp     word [sec_count], bx
125         jl      .again
126
127         ; Now we've loaded the setup code and the kernel image.
128         ; Jump to setup code.
129         jmp     SETUPSEG:0
130
131 ; Read a sector from the floppy drive.
132 ; This code (and the rest of this boot sector) will have to
133 ; be re-written at some point so it reads more than one
134 ; sector at a time.
135 ;
136 ; Parameters:
137 ;     - "logical" sector number   [bp+8]
138 ;     - destination segment       [bp+6]
139 ;     - destination offset        [bp+4]
140 ReadSector:
141         push    bp                      ; set up stack frame
142         mov     bp, sp                  ; "
143         pusha                           ; save all registers
144
145 %if 0
146 ; debug params
147         mov     dx, [bp+8]
148         call    PrintHex
149         call    PrintNL
150         mov     dx, [bp+6]
151         call    PrintHex
152         call    PrintNL
153         mov     dx, [bp+4]
154         call    PrintHex
155         call    PrintNL
156 %endif
157
158         ; Sector = log_sec % SECTORS_PER_TRACK
159         ; Head = (log_sec / SECTORS_PER_TRACK) % HEADS
160         mov     ax, [bp+8]              ; get logical sector number from stack
161         xor     dx, dx                  ; dx is high part of dividend (== 0)
162         mov     bx, SECTORS_PER_TRACK   ; divisor
163         div     bx                      ; do the division
164         mov     [sec], dx               ; sector is the remainder
165         and     ax, 1                   ; same as mod by HEADS==2 (slight hack)
166         mov     [head], ax
167
168         ; Track = log_sec / (SECTORS_PER_TRACK*HEADS)
169         mov     ax, [bp+8]              ; get logical sector number again
170         xor     dx, dx                  ; dx is high part of dividend
171         mov     bx, SECTORS_PER_TRACK*2 ; divisor
172         div     bx                      ; do the division
173         mov     [track], ax             ; track is quotient
174
175 %if 0
176 ; debugging code
177         mov     dx, [sec]
178         call    PrintHex
179         call    PrintNL
180         mov     dx, [head]
181         call    PrintHex
182         call    PrintNL
183         mov     dx, [track]
184         call    PrintHex
185         call    PrintNL
186 %endif
187
188         ; Now, try to actually read the sector from the floppy,
189         ; retrying up to 3 times.
190
191         mov     [num_retries], byte 0
192
193 .again:
194         mov     ax, [bp+6]              ; dest segment...
195         mov     es, ax                  ;   goes in es
196         mov     ax, (0x02 << 8) | 1     ; function = 02h in ah,
197                                         ;   # secs = 1 in al
198         mov     bx, [track]             ; track number...
199         mov     ch, bl                  ;   goes in ch
200         mov     bx, [sec]               ; sector number...
201         mov     cl, bl                  ;   goes in cl...
202         inc     cl                      ;   but it must be 1-based, not 0-based
203         mov     bx, [head]              ; head number...
204         mov     dh, bl                  ;   goes in dh
205         xor     dl, dl                  ; hard code drive=0
206         mov     bx, [bp+4]              ; offset goes in bx
207                                         ;   (es:bx points to buffer)
208
209         ; Call the BIOS Read Diskette Sectors service
210         int     0x13
211
212         ; If the carry flag is NOT set, then there was no error
213         ; and we're done.
214         jnc     .done
215
216         ; Error - code stored in ah
217         mov     dx, ax
218         call PrintHex
219         inc     byte [num_retries]
220         cmp     byte [num_retries], 3
221         jne     .again
222
223         ; If we got here, we failed thrice, so we give up
224         mov     dx, 0xdead
225         call    PrintHex
226 .here:  jmp     .here
227
228 .done:
229         popa                            ; restore all regisiters
230         pop     bp                      ; leave stack frame
231         ret
232
233 ; Include utility routines
234 %include "util.asm"
235
236 ; ----------------------------------------------------------------------
237 ; Variables
238 ; ----------------------------------------------------------------------
239
240 ; These are used by ReadSector
241 head: dw 0
242 track: dw 0
243 sec: dw 0
244 num_retries: db 0
245
246 ; Used for loops reading sectors from floppy
247 sec_count: dw 0
248 max_sector: dw 0
249
250 ; Padding to make the PFAT Boot Record sit just before the BIOS signature.
251 Pad_From_Symbol PFAT_BOOT_RECORD_OFFSET, BeginText
252
253 ; PFAT boot record
254 ; Describes how to load the setup program and kernel.
255 ; The default values are appropriate for creating a boot
256 ; floppy by concatenating the boot sector, setup program,
257 ; and kernel image.  The buildFat program will change
258 ; these values if the boot floppy is formatted as a PFAT
259 ; filesystem.
260         dw      0
261         dw      0
262
263         dw      0
264         dw      0
265
266         dw      0
267         dw      0
268
269         dw      0
270         dw      0
271
272         dw      0
273         dw      0
274
275 ;; part of pfat boot record
276 setupStart:             
277         dw      1                       ; by default, setup is at first sector  
278
279 ;; part of pfat boot record
280 setupSize:
281         dw      NUM_SETUP_SECTORS       ; number of sectors in setup
282
283 ;; part of pfat boot record
284 kernelStart:
285         dw      1+NUM_SETUP_SECTORS     ; default start sector for kernel
286
287 ;; part of pfat boot record
288 kernelSize:
289         dw      NUM_KERN_SECTORS+2*NUM_BIOS_SECTORS+NUM_VGA_BIOS_SECTORS+NUM_VMXASSIST_SECTORS
290
291
292 ; Finish by writing the BIOS signature to mark this as
293 ; a valid boot sector.
294 Pad_From_Symbol BIOS_SIGNATURE_OFFSET, BeginText
295 Signature   dw 0xAA55   ; BIOS controls this to ensure this is a boot sector