forked from cirosantilli/x86-bare-metal-examples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bios_disk_load.S
92 lines (72 loc) · 2.1 KB
/
bios_disk_load.S
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
# Bios disk load
# int 13h
Load one more sector from the disk
besides the first 512 bytes and do something with it.
Expected output: "a"
Grub 2.0 makes several calls to it under `grub-core/boot/i386/pc`
TODO: not working on:
- Bochs: `BOUND_GdMa: fails bounds test`.
- GRUB `chainloader` through big.img
Does work on QEMU and ThinkPad T400.
## int 13
BIOS call used for disk operations.
## Bibliography
- https://en.wikipedia.org/wiki/INT_13H
- http://wiki.osdev.org/ATA_in_x86_RealMode_%28BIOS%29
- https://thiscouldbebetter.wordpress.com/2011/03/15/creating-a-bootable-program-in-assembly-language/
- http://stackoverflow.com/questions/19381434/cannot-read-disk-sectors-in-assembly-language
- http://stackoverflow.com/questions/15497842/read-a-sector-from-hard-drive-with-int-13h
*/
#include "common.h"
BEGIN
CLEAR
/*
Reset disk. TODO is this really needed?
Was suggested in one tutorial.
*/
/*
mov $0, %ah
mov $0x80, %dl
int $0x13
*/
/* Read sectors into memory */
mov $2, %ah
/* Number of sectors to read. */
mov $1, %al
/*
Drive number. Starts at 0x80, second one is 0x81. TODO why not from 0?
The BIOS stores the right number on dl as an initial state,
but we may be destroying it before, and are lazy to properly store it somewhere.
http://stackoverflow.com/a/19387093/895245
*/
mov $0x80, %dl
/* cylinder number */
mov $0, %ch
/* Head number */
mov $0, %dh
/* Starting sector number. 2 because 1 was already loaded. */
mov $2, %cl
/*
Where to load to.
Must coincide with our stage2 for the linking to work.
The address is calculated as:
16 * ES + BX
*/
mov $stage2, %bx
int $0x13
jmp stage2
/*
Our linker script will put this section on the right place in memory:
just after the magic bytes.
*/
.section .stage2
stage2:
PUTC $'a
hlt
/*
We could use `.org` here to fill up the second sector to a multiple of 512 bytes.
But the linker does that beautifully with `. = ALIGN(512)` for any size of stage2,
so we use that instead.
*/
/*.org 512*/