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 / bootsect.asm
1 ; Boot sector for GeekOS
2 ; Copyright (c) 2001, David H. Hovemeyer <daveho@cs.umd.edu>
3 ; $Revision: 1.1.1.1 $
4
5 ; This is free software.  You are permitted to use,
6 ; redistribute, and modify it as specified in the file "COPYING".
7
8 ; Loads setup code and a program image from sectors 1..n of a floppy
9 ; and executes the setup code (which will in turn execute
10 ; the program image).
11
12 ; Some of this code is adapted from Kernel Toolkit 0.2
13 ; and Linux version 2.2.x, so the following copyrights apply:
14
15 ; Copyright (C) 1991, 1992 Linus Torvalds
16 ; modified by Drew Eckhardt
17 ; modified by Bruce Evans (bde)
18 ; adapted for Kernel Toolkit by Luigi Sgro
19
20 %include "defs.asm"
21
22 ; This macro is used to calculate padding needed
23 ; to ensure that the boot sector is exactly 512 bytes
24 ; in size.  The argument is the desired offset to be
25 ; padded to.
26 %macro PadFromStart 1
27         times (%1 - ($ - BeginText)) db 0
28 %endmacro
29
30 KERN_START_SEC equ (NUM_SETUP_SECTORS + 1)
31
32 BIOS_SIGNATURE_OFFSET equ 510
33
34 ; ----------------------------------------------------------------------
35 ; The actual code
36 ; ----------------------------------------------------------------------
37
38 [BITS 16]
39 [ORG 0x0]
40
41 BeginText:      ; needed to calculate padding bytes to fill the sector
42
43         ; Copy the boot sector into INITSEG.
44         mov     ax, BOOTSEG
45         mov     ds, ax                  ; source segment for string copy
46         xor     si, si                  ; source index for string copy
47         mov     ax, INITSEG
48         mov     es, ax                  ; destination segment for string copy
49         xor     di, di                  ; destination index for string copy
50         cld                             ; clear direction flag
51         mov     cx, 256                 ; number of words to copy
52         rep     movsw                   ; copy 512 bytes
53
54         jmp     INITSEG:after_move
55
56 after_move:
57         ; Now we're executing in INITSEG
58
59         ; We want the data segment to refer to INITSEG
60         ; (since we've defined variables in the same place as the code)
61         mov     ds, ax                  ; ax still contains INITSEG
62
63         ; Put the stack in the place where we were originally loaded.
64         ; By definition, there is nothing important there now.
65         mov     ax, 0
66         mov     ss, ax
67         mov     sp, (BOOTSEG << 4) + 512 - 2
68
69 load_setup:
70         ; Load the setup code.
71         mov     word [sec_count], 1
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         dec     ax                      ; 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         cmp     word [sec_count], NUM_SETUP_SECTORS
89         jle     .again
90
91 load_kernel:
92         ; Load the kernel image from sectors KERN_START_SEC..n of the
93         ; floppy into memory at KERNSEG.  Note that there are 128 sectors
94         ; per 64K segment.  So, when figuring out which segment to
95         ; load the sector into, we shift right by 7 bits (which is
96         ; equivalent to dividing by 128).
97         mov     word [sec_count], KERN_START_SEC
98 .again:
99         mov     ax, [sec_count]         ; logical sector on the floppy
100         push    ax                      ; 1st param to ReadSector (log sec num)
101         sub     ax, KERN_START_SEC      ; convert to 0-indexed
102         mov     cx, ax                  ; save in cx
103         shr     ax, 7                   ; divide by 128
104         shl     ax, 12                  ;  ...and multiply by 0x1000
105         add     ax, KERNSEG             ;  ...to get base relative to KERNSEG
106         push    ax                      ; 2nd param to ReadSector (seg base)
107         and     cx, 0x7f                ; mod sector by 128
108         shl     cx, 9                   ;  ...and multiply by 512
109         push    cx                      ; to get offset in segment (3rd parm)
110
111         ; read the sector from the floppy
112         call    ReadSector
113         add     sp, 6                   ; clear 3 word params
114
115         ; on to next sector
116         inc     word [sec_count]
117
118         ; have we loaded all of the sectors?
119         cmp     word [sec_count], KERN_START_SEC+NUM_KERN_SECTORS
120         jl      .again
121
122         ; Now we've loaded the setup code and the kernel image.
123         ; Jump to setup code.
124         jmp     SETUPSEG:0
125
126 ; Read a sector from the floppy drive.
127 ; This code (and the rest of this boot sector) will have to
128 ; be re-written at some point so it reads more than one
129 ; sector at a time.
130 ;
131 ; Parameters:
132 ;     - "logical" sector number   [bp+8]
133 ;     - destination segment       [bp+6]
134 ;     - destination offset        [bp+4]
135 ReadSector:
136         push    bp                      ; set up stack frame
137         mov     bp, sp                  ; "
138         pusha                           ; save all registers
139
140 %if 0
141 ; debug params
142         mov     dx, [bp+8]
143         call    PrintHex
144         call    PrintNL
145         mov     dx, [bp+6]
146         call    PrintHex
147         call    PrintNL
148         mov     dx, [bp+4]
149         call    PrintHex
150         call    PrintNL
151 %endif
152
153         ; Sector = log_sec % SECTORS_PER_TRACK
154         ; Head = (log_sec / SECTORS_PER_TRACK) % HEADS
155         mov     ax, [bp+8]              ; get logical sector number from stack
156         xor     dx, dx                  ; dx is high part of dividend (== 0)
157         mov     bx, SECTORS_PER_TRACK   ; divisor
158         div     bx                      ; do the division
159         mov     [sec], dx               ; sector is the remainder
160         and     ax, 1                   ; same as mod by HEADS==2 (slight hack)
161         mov     [head], ax
162
163         ; Track = log_sec / (SECTORS_PER_TRACK*HEADS)
164         mov     ax, [bp+8]              ; get logical sector number again
165         xor     dx, dx                  ; dx is high part of dividend
166         mov     bx, SECTORS_PER_TRACK*2 ; divisor
167         div     bx                      ; do the division
168         mov     [track], ax             ; track is quotient
169
170 %if 0
171 ; debugging code
172         mov     dx, [sec]
173         call    PrintHex
174         call    PrintNL
175         mov     dx, [head]
176         call    PrintHex
177         call    PrintNL
178         mov     dx, [track]
179         call    PrintHex
180         call    PrintNL
181 %endif
182
183         ; Now, try to actually read the sector from the floppy,
184         ; retrying up to 3 times.
185
186         mov     [num_retries], byte 0
187
188 .again:
189         mov     ax, [bp+6]              ; dest segment...
190         mov     es, ax                  ;   goes in es
191         mov     ax, (0x02 << 8) | 1     ; function = 02h in ah,
192                                         ;   # secs = 1 in al
193         mov     bx, [track]             ; track number...
194         mov     ch, bl                  ;   goes in ch
195         mov     bx, [sec]               ; sector number...
196         mov     cl, bl                  ;   goes in cl...
197         inc     cl                      ;   but it must be 1-based, not 0-based
198         mov     bx, [head]              ; head number...
199         mov     dh, bl                  ;   goes in dh
200         xor     dl, dl                  ; hard code drive=0
201         mov     bx, [bp+4]              ; offset goes in bx
202                                         ;   (es:bx points to buffer)
203
204         ; Call the BIOS Read Diskette Sectors service
205         int     0x13
206
207         ; If the carry flag is NOT set, then there was no error
208         ; and we're done.
209         jnc     .done
210
211         ; Error - code stored in ah
212         mov     dx, ax
213         call PrintHex
214         inc     byte [num_retries]
215         cmp     byte [num_retries], 3
216         jne     .again
217
218         ; If we got here, we failed thrice, so we give up
219         mov     dx, 0xdead
220         call    PrintHex
221 .here:  jmp     .here
222
223 .done:
224         popa                            ; restore all regisiters
225         pop     bp                      ; leave stack frame
226         ret
227
228 ; Include utility routines
229 %include "util.asm"
230
231 ; ----------------------------------------------------------------------
232 ; Variables
233 ; ----------------------------------------------------------------------
234
235 ; These are used by ReadSector
236 head: dw 0
237 track: dw 0
238 sec: dw 0
239 num_retries: db 0
240
241
242 ; Used for loops reading sectors from floppy
243 sec_count: dw 0
244
245
246 PadFromStart BIOS_SIGNATURE_OFFSET
247 Signature   dw 0xAA55   ; BIOS controls this to ensure this is a boot sector