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.


Partially working - looking at the load sector for vm kernel
[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.4 $
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 load_kernel:
93         ; Load the kernel image from sectors KERN_START_SEC..n of the
94         ; floppy into memory at KERNSEG.  Note that there are 128 sectors
95         ; per 64K segment.  So, when figuring out which segment to
96         ; load the sector into, we shift right by 7 bits (which is
97         ; equivalent to dividing by 128).
98
99         ; Figure out start sector and max sector
100
101         mov     ax, word [kernelStart]
102         mov     word [sec_count], ax
103         add     ax, word [kernelSize]
104         mov     word [max_sector], ax
105 .again:
106         mov     ax, [sec_count]         ; logical sector on the floppy
107 ;       mov     dx, ax
108 ;       call    PrintHex
109 ;       call    PrintNL
110         push    ax                      ; 1st param to ReadSector (log sec num)
111         sub     ax, [kernelStart]       ; convert to 0-indexed
112         mov     cx, ax                  ; save in cx
113         shr     ax, 7                   ; divide by 128
114         shl     ax, 12                  ;  ...and multiply by 0x1000
115         add     ax, KERNSEG             ;  ...to get base relative to KERNSEG
116 ;       mov     dx, ax
117 ;       call    PrintHex
118 ;       call    PrintNL
119         push    ax                      ; 2nd param to ReadSector (seg base)
120         and     cx, 0x7f                ; mod sector by 128
121         shl     cx, 9                   ;  ...and multiply by 512
122         push    cx                      ; to get offset in segment (3rd parm)
123 ;       mov     dx, cx
124 ;       call    PrintHex
125 ;       call    PrintNL
126
127
128         ; read the sector from the floppy
129         call    ReadSector
130         add     sp, 6                   ; clear 3 word params
131
132
133         ; on to next sector
134         inc     word [sec_count]
135
136         ; have we loaded all of the sectors?
137         mov     bx, word [max_sector]
138         cmp     word [sec_count], bx
139         jl      .again
140
141 load_vm:
142         ; Load the guest image starting at 1MB
143         ; floppy into memory at KERNSEG.  Note that there are 128 sectors
144         ; per 64K segment.  So, when figuring out which segment to
145         ; load the sector  into, we shift right by 7 bits (which is
146         ; equivalent to dividing by 128).
147
148         ; Figure out start sector and max sector
149         mov     ax, word [vmStart]
150         mov     word [sec_count], ax
151         add     ax, word [vmSize]
152         mov     word [max_sector], ax
153 .again2:
154
155         mov     ax, [sec_count]         ; logical sector on the floppy
156         push    ax                      ; 1st param to ReadSector (log sec num)
157
158         mov     dx, ax
159         call    PrintHex
160         call    PrintNL
161
162         mov     ax, VMSEG               ;  ...to get base relative to VMSEG
163         push    ax                      ; 2nd param to ReadSector (seg base)
164         
165 ;       mov     dx, ax          ; 
166 ;       call    PrintHex
167 ;       call    PrintNL
168
169         mov     ax, 2000h               ; Always write at the start of the segment
170         push    ax              ; 3rd parameter
171
172         mov     dx, ax
173         call    PrintHex
174         call    PrintNL
175
176         ; read the sector from the floppy
177         call    ReadSector
178         add     sp, 6                   ; clear 3 word params
179
180         push    9000h
181         pop     es
182
183         mov     dx, word [es:2000] ;
184         call    PrintHex
185         call    PrintNL
186         
187         
188
189 ; execute bios call
190
191         push    cx
192         push    si
193         push    bx
194         push    es              ; 
195
196         push    cs
197         pop     es
198         mov     si, bootsect_gdt
199         mov     ax, 0x8700      ;
200         int     0x15
201         adc     ax, 0
202
203         mov     dx, ax
204         call    PrintHex
205         call    PrintNL
206
207         pop     es              ;
208         pop     bx
209         pop     si
210         pop     cx
211         
212         ; on to next sector
213         inc     word [sec_count]
214
215
216         ; update the low->high copy table for the bios
217 ;       mov     ax, word [bootsect_src_base] ;
218 ;       add     ax, 512
219 ;       mov     dx,ax;
220 ;       call    PrintHex
221 ;       adc     byte [bootsect_src_base+2], 0
222 ;       mov     word [bootsect_src_base],ax
223
224         mov     ax, word [bootsect_dst_base] ;
225         add     ax, 512
226         adc     byte [bootsect_dst_base+2], 0
227         mov     word [bootsect_dst_base],ax
228         
229         ; have we loaded all of the sectors?
230
231         mov     bx, word [max_sector]
232         cmp     word [sec_count], bx
233
234         jmp     .out 
235         jl      .again2
236
237 .out:   
238         ; Now we've loaded the setup code and the kernel image.
239         ; Jump to setup code.
240         jmp     SETUPSEG:0
241
242 ; Read a sector from the floppy drive.
243 ; This code (and the rest of this boot sector) will have to
244 ; be re-written at some point so it reads more than one
245 ; sector at a time.
246 ;
247 ; Parameters:
248 ;     - "logical" sector number   [bp+8]
249 ;     - destination segment       [bp+6]
250 ;     - destination offset        [bp+4]
251 ReadSector:
252         push    bp                      ; set up stack frame
253         mov     bp, sp                  ; "
254         pusha                           ; save all registers
255
256 %if 0
257 ; debug params
258         mov     dx, [bp+8]
259         call    PrintHex
260         call    PrintNL
261         mov     dx, [bp+6]
262         call    PrintHex
263         call    PrintNL
264         mov     dx, [bp+4]
265         call    PrintHex
266         call    PrintNL
267 %endif
268
269         ; Sector = log_sec % SECTORS_PER_TRACK
270         ; Head = (log_sec / SECTORS_PER_TRACK) % HEADS
271         mov     ax, [bp+8]              ; get logical sector number from stack
272         xor     dx, dx                  ; dx is high part of dividend (== 0)
273         mov     bx, SECTORS_PER_TRACK   ; divisor
274         div     bx                      ; do the division
275         mov     [sec], dx               ; sector is the remainder
276         and     ax, 1                   ; same as mod by HEADS==2 (slight hack)
277         mov     [head], ax
278
279         ; Track = log_sec / (SECTORS_PER_TRACK*HEADS)
280         mov     ax, [bp+8]              ; get logical sector number again
281         xor     dx, dx                  ; dx is high part of dividend
282         mov     bx, SECTORS_PER_TRACK*2 ; divisor
283         div     bx                      ; do the division
284         mov     [track], ax             ; track is quotient
285
286 %if 0
287 ; debugging code
288         mov     dx, [sec]
289         call    PrintHex
290         call    PrintNL
291         mov     dx, [head]
292         call    PrintHex
293         call    PrintNL
294         mov     dx, [track]
295         call    PrintHex
296         call    PrintNL
297 %endif
298
299         ; Now, try to actually read the sector from the floppy,
300         ; retrying up to 3 times.
301
302         mov     [num_retries], byte 0
303
304 .again:
305         mov     ax, [bp+6]              ; dest segment...
306         mov     es, ax                  ;   goes in es
307         mov     ax, (0x02 << 8) | 1     ; function = 02h in ah,
308                                         ;   # secs = 1 in al
309         mov     bx, [track]             ; track number...
310         mov     ch, bl                  ;   goes in ch
311         mov     bx, [sec]               ; sector number...
312         mov     cl, bl                  ;   goes in cl...
313         inc     cl                      ;   but it must be 1-based, not 0-based
314         mov     bx, [head]              ; head number...
315         mov     dh, bl                  ;   goes in dh
316         xor     dl, dl                  ; hard code drive=0
317         mov     bx, [bp+4]              ; offset goes in bx
318                                         ;   (es:bx points to buffer)
319
320
321         ; Call the BIOS Read Diskette Sectors service
322         int     0x13
323
324         ; If the carry flag is NOT set, then there was no error
325         ; and we're done.
326         jnc     .done
327
328         ; Error - code stored in ah
329         mov     dx, ax
330         call PrintHex
331         inc     byte [num_retries]
332         cmp     byte [num_retries], 3
333         jne     .again
334
335         ; If we got here, we failed thrice, so we give up
336         mov     dx, 0xdead
337         call    PrintHex
338 .here:  jmp     .here
339
340 .done:
341         popa                            ; restore all regisiters
342         pop     bp                      ; leave stack frame
343         ret
344
345 ; Include utility routines:
346 ;%include "util.asm"
347 ; REPLACED WITH FOLLOWING WHICH MUST BE COMPILED 16 FOR USE IN THIS CODE
348 PrintHex:
349         pusha
350         mov   cx, 4             ; 4 hex digits
351 .PrintDigit:
352         rol   dx, 4             ; rotate so that lowest 4 bits are used
353         mov   ax, 0E0Fh         ; ah = request, al = mask for nybble
354         and   al, dl
355         add   al, 90h           ; convert al to ascii hex (four instructions)
356         daa                     ; I've spent 1 hour to understand how it works..
357         adc   al, 40h
358         daa
359         int   10h
360         loop  .PrintDigit
361         popa
362         ret
363
364 ; Print a newline.
365 PrintNL:                        ; print CR and NL
366         push    ax
367         mov     ax, 0E0Dh       ; CR
368         int     10h
369         mov     al, 0Ah         ; LF
370         int     10h
371         pop     ax
372         ret
373
374
375
376 ; ----------------------------------------------------------------------
377 ; Variables
378 ; ----------------------------------------------------------------------
379
380 ; These are used by ReadSector
381 head: dw 0
382 track: dw 0
383 sec: dw 0
384 num_retries: db 0
385
386 ; Used for loops reading sectors from floppy
387 sec_count: dw 0
388 max_sector: dw 0
389
390
391
392
393 bootsect_gdt:
394         dw      0,0,0,0
395         dw      0,0,0,0
396 bootsect_src:
397         dw      0x200-1                
398 bootsect_src_base:
399         db      0,02,9          ;       ! base = 0x092000 
400         db      0x93            ;       ! typbyte
401         dw      0               ;       ! limit16,base24 =0
402 bootsect_dst:
403         dw      0x200-1
404 bootsect_dst_base:
405         db      0,0,0x10        ;       ! base = 0x100000
406         db      0x93            ;       ! typbyte
407         dw      0               ;       ! limit16,base24 =0
408         dw      0,0,0,0         ;       ! BIOS CS
409         dw      0,0,0,0         ;       ! BIOS DS
410
411
412 ; Padding to make the PFAT Boot Record sit just before the BIOS signature.
413 ;Pad_From_Symbol PFAT_BOOT_RECORD_OFFSET, BeginText
414
415 ; PFAT boot record
416 ; Describes how to load the setup program and kernel.
417 ; The default values are appropriate for creating a boot
418 ; floppy by concatenating the boot sector, setup program,
419 ; and kernel image.  The buildFat program will change
420 ; these values if the boot floppy is formatted as a PFAT
421 ; filesystem.
422         dw      0
423         dw      0
424
425         dw      0
426         dw      0
427
428         dw      0
429         dw      0
430
431         dw      0
432         dw      0
433
434         dw      0
435         dw      0
436
437 ;; part of pfat boot record
438 setupStart:             
439         dw      1                       ; by default, setup is at first sector  
440
441 ;; part of pfat boot record
442 setupSize:
443         dw      NUM_SETUP_SECTORS       ; number of sectors in setup
444
445 ;; part of pfat boot record
446 kernelStart:
447         dw      1+NUM_SETUP_SECTORS     ; default start sector for kernel
448
449 ;; part of pfat boot record
450 kernelSize:
451         dw      NUM_KERN_SECTORS
452
453         ;; part of pfat boot record
454 vmStart:
455         dw      1+NUM_SETUP_SECTORS+NUM_KERN_SECTORS
456         ;; part of pfat boot record
457
458 vmSize:
459         dw      NUM_VM_KERNEL_SECTORS
460
461
462         ; Finish by writing the BIOS signature to mark this as
463 ; a valid boot sector.
464 Pad_From_Symbol BIOS_SIGNATURE_OFFSET, BeginText
465 Signature   dw 0xAA55   ; BIOS controls this to ensure this is a boot sector