* better
[mascara-docs.git] / amd64 / bareMetalOS-0.5.2 / pure64.boot0 / src / init_hdd.asm
blob68a8d02c893a183ad52ac61bde3d494348d6d209
1 ; =============================================================================
2 ; Pure64 -- a 64-bit OS loader written in Assembly for x86-64 systems
3 ; Copyright (C) 2008-2011 Return Infinity -- see LICENSE.TXT
5 ; INIT HDD
6 ; =============================================================================
9 hdd_setup:
10 ; Read first sector of HDD into memory
11 xor rax, rax
12 mov rdi, hdbuffer
13 push rdi
14 mov rcx, 1
15 call readsectors
16 pop rdi
18 cmp byte [cfg_mbr], 0x01 ; Did we boot from a MBR drive
19 jne hdd_setup_no_mbr ; If not then we already have the correct sector
21 ; Grab the partition offset value for the first partition
22 mov eax, [rdi+0x01C6]
23 mov [fat16_PartitionOffset], eax
25 ; Read the first sector of the first partition
26 mov rdi, hdbuffer
27 push rdi
28 mov rcx, 1
29 call readsectors
30 pop rdi
32 hdd_setup_no_mbr:
33 ; Get the values we need to start using fat16
34 mov ax, [rdi+0x0b]
35 mov [fat16_BytesPerSector], ax ; This will probably be 512
36 mov al, [rdi+0x0d]
37 mov [fat16_SectorsPerCluster], al ; This will be 128 or less (Max cluster size is 64KiB)
38 mov ax, [rdi+0x0e]
39 mov [fat16_ReservedSectors], ax
40 mov [fat16_FatStart], eax
41 mov al, [rdi+0x10]
42 mov [fat16_Fats], al ; This will probably be 2
43 mov ax, [rdi+0x11]
44 mov [fat16_RootDirEnts], ax
45 mov ax, [rdi+0x16]
46 mov [fat16_SectorsPerFat], ax
48 ; Find out how many sectors are on the disk
49 xor eax, eax
50 mov ax, [rdi+0x13]
51 cmp ax, 0x0000
52 jne lessthan65536sectors
53 mov eax, [rdi+0x20]
54 lessthan65536sectors:
55 mov [fat16_TotalSectors], eax
57 ; Calculate the size in MiB
58 xor rax, rax
59 mov eax, [fat16_TotalSectors]
60 mov [hd1_maxlba], rax
61 shr rax, 11 ; rax = rax * 512 / 1048576
62 mov [hd1_size], eax ; in mebibytes (MiB)
64 ; Create a string of the harddrive size
65 mov rdi, hdtempstring
66 call os_int_to_string
68 xor rax, rax
69 xor rbx, rbx
70 mov ax, [fat16_SectorsPerFat]
71 shl ax, 1 ; quick multiply by two
72 add ax, [fat16_ReservedSectors]
73 mov [fat16_RootStart], eax
74 mov bx, [fat16_RootDirEnts]
75 shr ebx, 4 ; bx = (bx * 32) / 512
76 add ebx, eax ; BX now holds the datastart sector number
77 mov [fat16_DataStart], ebx
79 ret
82 ; -----------------------------------------------------------------------------
83 ; readsectors -- Read sectors on the hard drive
84 ; IN: RAX = starting sector to read
85 ; RCX = number of sectors to read (1 - 256)
86 ; RDI = memory location to store sectors
87 ; OUT: RAX = RAX + number of sectors that were read
88 ; RCX = number of sectors that were read (0 on error)
89 ; RDI = RDI + (number of sectors * 512)
90 ; All other registers preserved
91 readsectors:
92 push rdx
93 push rcx
94 push rbx
95 push rax
97 push rcx ; Save RCX for use in the read loop
98 mov rbx, rcx ; Store number of sectors to read
99 cmp rcx, 256
100 jg readsectors_fail ; Over 256? Fail!
101 jne readsectors_skip ; Not 256? No need to modify CL
102 xor rcx, rcx ; 0 translates to 256
103 readsectors_skip:
105 push rax ; Save RAX since we are about to overwrite it
106 mov dx, 0x01F2 ; 0x01F2 - Sector count Port 7:0
107 mov al, cl ; Read CL sectors
108 out dx, al
109 pop rax ; Restore RAX which is our sector number
110 inc dx ; 0x01F3 - LBA Low Port 7:0
111 out dx, al
112 inc dx ; 0x01F4 - LBA Mid Port 15:8
113 shr rax, 8
114 out dx, al
115 inc dx ; 0x01F5 - LBA High Port 23:16
116 shr rax, 8
117 out dx, al
118 inc dx ; 0x01F6 - Device Port. Bit 6 set for LBA mode, Bit 4 for device (0 = master, 1 = slave), Bits 3-0 for LBA "Extra High" (27:24)
119 shr rax, 8
120 and al, 00001111b ; Clear bits 4-7 just to be safe
121 or al, 01000000b ; Turn bit 6 on since we want to use LBA addressing, leave device at 0 (master)
122 out dx, al
123 inc dx ; 0x01F7 - Command Port
124 mov al, 0x20 ; Read sector(s). 0x24 if LBA48
125 out dx, al
127 mov rcx, 4
128 readsectors_wait:
129 in al, dx ; Read status from 0x01F7
130 test al, 0x80 ; BSY flag set?
131 jne readsectors_retry
132 test al, 0x08 ; DRQ set?
133 jne readsectors_dataready
134 readsectors_retry:
135 dec rcx
136 jg readsectors_wait
137 readsectors_nextsector:
138 in al, dx ; Read status from 0x01F7
139 test al, 0x80 ; BSY flag set?
140 jne readsectors_nextsector
141 test al, 0x21 ; ERR or DF set?
142 jne readsectors_fail
144 readsectors_dataready:
145 sub dx, 7 ; Data port (0x1F0)
146 mov rcx, 256 ; Read
147 rep insw ; Copy a 512 byte sector to RDI
148 add dx, 7 ; Set DX back to status register (0x01F7)
149 in al, dx ; Delay ~400ns to allow drive to set new values of BSY and DRQ
150 in al, dx
151 in al, dx
152 in al, dx
154 dec rbx ; RBX is the "sectors to read" counter
155 cmp rbx, 0
156 jne readsectors_nextsector
158 pop rcx
159 pop rax
160 pop rbx
161 add rax, rcx
162 pop rcx
163 pop rdx
166 readsectors_fail:
167 pop rcx
168 pop rax
169 pop rbx
170 pop rcx
171 pop rdx
172 xor rcx, rcx ; Set RCX to 0 since nothing was read
174 ; -----------------------------------------------------------------------------
177 ; =============================================================================
178 ; EOF