1e5476626SJessica Hamilton; Copyright 2005-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
2e5476626SJessica Hamilton; Distributed under the terms of the MIT License.
3e5476626SJessica Hamilton;
4e5476626SJessica Hamilton; Stage 1 boot code for the good (?) old BIOS for use as boot block of HD
5e5476626SJessica Hamilton; partitions. The offset of the partition in 512 byte blocks must be written at
6e5476626SJessica Hamilton; position PARTITION_OFFSET_OFFSET (32 bit little endian; makebootable does
7e5476626SJessica Hamilton; that) or otherwise the code can't find the partition.
84124da50SAlexander von Gluck IV; The partition must be BFS formatted. The haiku_loader hpkg file must be located
94124da50SAlexander von Gluck IV; at "system/packages/haiku_loader*" and the haiku_loader.bios_ia32 must be the
104124da50SAlexander von Gluck IV; first file in the haiku_loader package.
114124da50SAlexander von Gluck IV;
124124da50SAlexander von Gluck IV; The bios_ia32 stage 2 boot loader is loaded into memory at 0x1000:0x0000
134124da50SAlexander von Gluck IV; (linear address 0x10000) and entered at 0x:1000:0x0200 with parameters
144124da50SAlexander von Gluck IV; eax - partition offset in 512 byte blocks and dl - BIOS ID of the boot drive.
15e5476626SJessica Hamilton;
16e5476626SJessica Hamilton; Compile via:
17e5476626SJessica Hamilton; nasm -f bin -O5 -o stage1.bin stage1.S
18e5476626SJessica Hamilton
19e5476626SJessica Hamilton; 1 enables more informative error strings, that shouldn't be seen by the
20e5476626SJessica Hamilton; normal user, though.
21e5476626SJessica Hamilton%assign	DEBUG						0
22e5476626SJessica Hamilton
23e5476626SJessica Hamilton
24e5476626SJessica Hamilton; address/offset definitions
25e5476626SJessica Hamilton
26e5476626SJessica Hamilton%assign	BOOT_BLOCK_START_ADDRESS	0x7c00
27e5476626SJessica Hamilton%assign	STACK_ADDRESS				BOOT_BLOCK_START_ADDRESS
28e5476626SJessica Hamilton%assign	READ_BUFFER_STACK			STACK_ADDRESS - 0x2000
29e5476626SJessica Hamilton%assign	PARTITION_OFFSET_OFFSET		506
30e5476626SJessica Hamilton%assign	BFS_SUPERBLOCK_OFFSET		512
31e5476626SJessica Hamilton
32e5476626SJessica Hamilton
33e5476626SJessica Hamilton; BFS definitions
34e5476626SJessica Hamilton
35e5476626SJessica Hamilton%define SUPER_BLOCK_MAGIC1			'1SFB'		; nasm reverses '...' consts
36e5476626SJessica Hamilton%assign SUPER_BLOCK_MAGIC2			0xdd121031
37e5476626SJessica Hamilton%assign SUPER_BLOCK_MAGIC3			0x15b6830e
38e5476626SJessica Hamilton
39e5476626SJessica Hamilton%assign	INODE_MAGIC1				0x3bbe0ad9
40e5476626SJessica Hamilton
41e5476626SJessica Hamilton%assign	NUM_DIRECT_BLOCKS			12
42e5476626SJessica Hamilton
43e5476626SJessica Hamilton%assign	S_IFMT						00000170000o
44e5476626SJessica Hamilton%assign	S_IFDIR						00000040000o
45e5476626SJessica Hamilton
46e5476626SJessica Hamilton
47e5476626SJessica Hamilton; BIOS calls
48e5476626SJessica Hamilton
49e5476626SJessica Hamilton%assign	BIOS_VIDEO_SERVICES			0x10
50e5476626SJessica Hamilton%assign	BIOS_DISK_SERVICES			0x13
51e5476626SJessica Hamilton%assign	BIOS_KEYBOARD_SERVICES		0X16
52e5476626SJessica Hamilton%assign	BIOS_REBOOT					0X19
53e5476626SJessica Hamilton
54e5476626SJessica Hamilton; video services
55e5476626SJessica Hamilton%assign	WRITE_CHAR						0x0e	; al - char
56e5476626SJessica Hamilton												; bh - page?
57e5476626SJessica Hamilton
58e5476626SJessica Hamilton; disk services
59e5476626SJessica Hamilton%assign	READ_DISK_SECTORS				0x02	; dl	- drive
60e5476626SJessica Hamilton												; es:bx	- buffer
61e5476626SJessica Hamilton												; dh	- head (0 - 15)
62e5476626SJessica Hamilton												; ch	- track 7:0 (0 - 1023)
63e5476626SJessica Hamilton												; cl	- track 9:8,
64e5476626SJessica Hamilton												;		  sector (1 - 17)
65e5476626SJessica Hamilton												; al	- sector count
66e5476626SJessica Hamilton												; -> al - sectors read
67e5476626SJessica Hamilton%assign	READ_DRIVE_PARAMETERS			0x08	; dl - drive
68e5476626SJessica Hamilton												; -> cl - max cylinder 9:8
69e5476626SJessica Hamilton												;		- sectors per track
70e5476626SJessica Hamilton												;    ch - max cylinder 7:0
71e5476626SJessica Hamilton												;    dh - max head
72e5476626SJessica Hamilton												;    dl - number of drives (?)
73e5476626SJessica Hamilton%assign	CHECK_DISK_EXTENSIONS_PRESENT	0x41	; bx - 0x55aa
74e5476626SJessica Hamilton												; dl - drive
75e5476626SJessica Hamilton												; -> success: carry clear
76e5476626SJessica Hamilton												;    ah - extension version
77e5476626SJessica Hamilton												;    bx - 0xaa55
78e5476626SJessica Hamilton												;    cx - support bit mask
79e5476626SJessica Hamilton												; -> error: carry set
80e5476626SJessica Hamilton%assign	EXTENDED_READ					0x42	; dl - drive
81e5476626SJessica Hamilton												; ds:si - address packet
82e5476626SJessica Hamilton												; -> success: carry clear
83e5476626SJessica Hamilton												; -> error: carry set
84e5476626SJessica Hamilton
85e5476626SJessica Hamilton%assign FIXED_DISK_SUPPORT				0x1		; flag indicating fixed disk
86e5476626SJessica Hamilton												; extension command subset
87e5476626SJessica Hamilton
88e5476626SJessica Hamilton; keyboard services
89e5476626SJessica Hamilton%assign	READ_CHAR						0x00	; -> al - ASCII char
90e5476626SJessica Hamilton												;    ah - scan code
91e5476626SJessica Hamilton
92e5476626SJessica Hamilton
93e5476626SJessica Hamilton; nasm (0.98.38) doesn't seem to know pushad. popad works though.
94e5476626SJessica Hamilton%define	pushad		db	0x66, 0x60
95e5476626SJessica Hamilton
96e5476626SJessica Hamilton
97e5476626SJessica Hamilton; 16 bit code
98e5476626SJessica HamiltonSECTION .text
99e5476626SJessica HamiltonBITS 16
100e5476626SJessica HamiltonORG BOOT_BLOCK_START_ADDRESS					; start code at 0x7c00
101e5476626SJessica Hamilton
102e5476626SJessica Hamilton; nicer way to get the size of a structure
103e5476626SJessica Hamilton%define	sizeof(s)	s %+ _size
104e5476626SJessica Hamilton
105e5476626SJessica Hamilton; using a structure in a another structure definition
106e5476626SJessica Hamilton%macro	nstruc	1-2		1
107e5476626SJessica Hamilton					resb	sizeof(%1) * %2
108e5476626SJessica Hamilton%endmacro
109e5476626SJessica Hamilton
110e5476626SJessica Hamilton; 64 bit value
111e5476626SJessica Hamiltonstruc	quadword
112e5476626SJessica Hamilton	.lower			resd	1
113e5476626SJessica Hamilton	.upper			resd	1
114e5476626SJessica Hamiltonendstruc
115e5476626SJessica Hamilton
116e5476626SJessica Hamilton; address packet as required by the EXTENDED_READ BIOS call
117e5476626SJessica Hamiltonstruc	AddressPacket
118e5476626SJessica Hamilton	.packet_size	resb	1
119e5476626SJessica Hamilton	.reserved1		resb	1
120e5476626SJessica Hamilton	.block_count	resb	1
121e5476626SJessica Hamilton	.reserved2		resb	1
122e5476626SJessica Hamilton	.buffer			resd	1
123e5476626SJessica Hamilton	.offset			nstruc	quadword
124e5476626SJessica Hamilton;	.long_buffer	nstruc	quadword
125e5476626SJessica Hamilton	; We don't need the 64 bit buffer pointer. The 32 bit .buffer is more
126e5476626SJessica Hamilton	; than sufficient.
127e5476626SJessica Hamiltonendstruc
128e5476626SJessica Hamilton
129e5476626SJessica Hamilton; BFS block run
130e5476626SJessica Hamiltonstruc	BlockRun
131e5476626SJessica Hamilton	.allocation_group	resd	1
132e5476626SJessica Hamilton	.start				resw	1
133e5476626SJessica Hamilton	.length				resw	1
134e5476626SJessica Hamiltonendstruc
135e5476626SJessica Hamilton
136e5476626SJessica Hamilton; BFS superblock
137e5476626SJessica Hamiltonstruc	SuperBlock
138e5476626SJessica Hamilton	.name			resb	32
139e5476626SJessica Hamilton	.magic1			resd	1
140e5476626SJessica Hamilton	.fs_byte_order	resd	1
141e5476626SJessica Hamilton	.block_size		resd	1
142e5476626SJessica Hamilton	.block_shift	resd	1
143e5476626SJessica Hamilton	.num_blocks		nstruc	quadword
144e5476626SJessica Hamilton	.used_blocks	nstruc	quadword
145e5476626SJessica Hamilton	.inode_size		resd	1
146e5476626SJessica Hamilton	.magic2			resd	1
147e5476626SJessica Hamilton	.blocks_per_ag	resd	1
148e5476626SJessica Hamilton	.ag_shift		resd	1
149e5476626SJessica Hamilton	.num_args		resd	1
150e5476626SJessica Hamilton	.flags			resd	1
151e5476626SJessica Hamilton	.log_blocks		nstruc	BlockRun
152e5476626SJessica Hamilton	.log_start		nstruc	quadword
153e5476626SJessica Hamilton	.log_end		nstruc	quadword
154e5476626SJessica Hamilton	.magic3			resd	1
155e5476626SJessica Hamilton	.root_dir		nstruc	BlockRun
156e5476626SJessica Hamilton	.indices		nstruc	BlockRun
157e5476626SJessica Hamilton	.pad			resd	8
158e5476626SJessica Hamiltonendstruc
159e5476626SJessica Hamilton
160e5476626SJessica Hamilton; BFS inode data stream
161e5476626SJessica Hamiltonstruc	DataStream
162e5476626SJessica Hamilton	.direct						nstruc	BlockRun, NUM_DIRECT_BLOCKS
163e5476626SJessica Hamilton	.max_direct_range			nstruc	quadword
164e5476626SJessica Hamilton	.indirect					nstruc	BlockRun
165e5476626SJessica Hamilton	.max_indirect_range			nstruc	quadword
166e5476626SJessica Hamilton	.double_indirect			nstruc	BlockRun
167e5476626SJessica Hamilton	.max_double_indirect_range	nstruc	quadword
168e5476626SJessica Hamilton	.size						nstruc	quadword
169e5476626SJessica Hamiltonendstruc
170e5476626SJessica Hamilton
171e5476626SJessica Hamilton; BFS inode (shortened)
172e5476626SJessica Hamiltonstruc	BFSInode
173e5476626SJessica Hamilton	.magic1				resd	1
174e5476626SJessica Hamilton	.inode_num			nstruc	BlockRun
175e5476626SJessica Hamilton	.uid				resd	1
176e5476626SJessica Hamilton	.gid				resd	1
177e5476626SJessica Hamilton	.mode				resd	1
178e5476626SJessica Hamilton	.flags				resd	1
179e5476626SJessica Hamilton	.create_time		nstruc	quadword
180e5476626SJessica Hamilton	.last_modified_time	nstruc	quadword
181e5476626SJessica Hamilton	.parent				nstruc	BlockRun
182e5476626SJessica Hamilton	.attributes			nstruc	BlockRun
183e5476626SJessica Hamilton	.type				resd	1
184e5476626SJessica Hamilton	.inode_size			resd	1
185e5476626SJessica Hamilton	.etc				resd	1
186e5476626SJessica Hamilton	.data				nstruc	DataStream
187e5476626SJessica Hamilton	; ...
188e5476626SJessica Hamiltonendstruc
189e5476626SJessica Hamilton
190e5476626SJessica Hamilton; BFS B+ tree node
191e5476626SJessica Hamiltonstruc	BPlusTreeNode
192e5476626SJessica Hamilton	.left_link			nstruc	quadword
193e5476626SJessica Hamilton	.right_link			nstruc	quadword
194e5476626SJessica Hamilton	.overflow_link		nstruc	quadword
195e5476626SJessica Hamilton	.all_key_count		resw	1
196e5476626SJessica Hamilton	.all_key_length		resw	1
197e5476626SJessica Hamiltonendstruc
198e5476626SJessica Hamilton
199e5476626SJessica Hamilton; The beginning of a HPKG header
200e5476626SJessica Hamiltonstruc	HPKGHeader
201e5476626SJessica Hamilton	.magic				resd	1
202e5476626SJessica Hamilton	.header_size		resw	1
203e5476626SJessica Hamilton	; ...
204e5476626SJessica Hamilton
205e5476626SJessica Hamilton; That's what esp points to after a "pushad".
206e5476626SJessica Hamiltonstruc	PushadStack
207e5476626SJessica Hamilton	.edi						resd	1
208e5476626SJessica Hamilton	.esi						resd	1
209e5476626SJessica Hamilton	.ebp						resd	1
210e5476626SJessica Hamilton	.tmp						resd	1	; esp
211e5476626SJessica Hamilton	.ebx						resd	1
212e5476626SJessica Hamilton	.edx						resd	1
213e5476626SJessica Hamilton	.ecx						resd	1
214e5476626SJessica Hamilton	.eax						resd	1
215e5476626SJessica Hamiltonendstruc
216e5476626SJessica Hamilton
217e5476626SJessica Hamilton; helper macro for defining static variables
218e5476626SJessica Hamilton%macro	define_static_var	1
219e5476626SJessica Hamilton	%define %1	static_variables + StaticVariables. %+ %1
220e5476626SJessica Hamilton%endmacro
221e5476626SJessica Hamilton
222e5476626SJessica Hamilton; Structure containing the static variables we use (the ones that don't need
223e5476626SJessica Hamilton; pre-initialization at least). By using this structure we can easily place
224e5476626SJessica Hamilton; them onto our "heap".
225e5476626SJessica Hamiltonstruc	StaticVariables
226e5476626SJessica Hamilton	.bios_drive_id				resd	1
227e5476626SJessica Hamilton	.address_packet				nstruc	AddressPacket
228e5476626SJessica Hamilton	.write_int32_buffer			resb	32
229e5476626SJessica Hamilton	.inode						resb	512
230e5476626SJessica Hamilton	.indirect_block				resb	512
231e5476626SJessica Hamilton	.buffer						resb	1024
232e5476626SJessica Hamiltonendstruc
233e5476626SJessica Hamilton
234e5476626SJessica Hamilton; define short names for our static variables
235e5476626SJessica Hamiltondefine_static_var	bios_drive_id
236e5476626SJessica Hamiltondefine_static_var	write_int32_buffer
237e5476626SJessica Hamiltondefine_static_var	address_packet
238e5476626SJessica Hamiltondefine_static_var	inode
239e5476626SJessica Hamiltondefine_static_var	indirect_block
240e5476626SJessica Hamiltondefine_static_var	buffer
241e5476626SJessica Hamilton
242e5476626SJessica Hamilton; Macro for defining a string prefixed by a byte containing its length. Used
243e5476626SJessica Hamilton; for the list of components of the path to the stage 2 boot loader.
244e5476626SJessica Hamilton%macro	pathComponent	1
245e5476626SJessica Hamilton	%strlen	.componentLen	%1
246e5476626SJessica Hamilton	db						.componentLen
247e5476626SJessica Hamilton	db						%1
248e5476626SJessica Hamilton%endmacro
249e5476626SJessica Hamilton
250e5476626SJessica Hamilton; macro to be invoked in case of error -- parameter is the error string
251e5476626SJessica Hamilton%macro	error	1
252e5476626SJessica Hamilton	%if	DEBUG
253e5476626SJessica Hamilton		mov			si, %1
254e5476626SJessica Hamilton	%else
255e5476626SJessica Hamilton		mov			si, kErrorString
256e5476626SJessica Hamilton	%endif
257e5476626SJessica Hamilton	jmp			_error
258e5476626SJessica Hamilton%endmacro
259e5476626SJessica Hamilton
260e5476626SJessica Hamilton
261e5476626SJessica Hamiltonstart:
262e5476626SJessica Hamilton	; set ds, es, ss to the value of cs (which is 0x0000)
263e5476626SJessica Hamilton	push		cs
264e5476626SJessica Hamilton	pop			ds
265e5476626SJessica Hamilton	push		cs
266e5476626SJessica Hamilton	pop			es
267e5476626SJessica Hamilton
268e5476626SJessica Hamilton	push		cs				; setup stack
269e5476626SJessica Hamilton	pop			ss
270e5476626SJessica Hamilton	mov			sp, STACK_ADDRESS
271e5476626SJessica Hamilton
272e5476626SJessica Hamilton	cli							; disable interrupts
273e5476626SJessica Hamilton	cld							; clear direction flag (for string ops)
274e5476626SJessica Hamilton
275e5476626SJessica Hamilton	; save the BIOS drive ID
276e5476626SJessica Hamilton	mov			[bios_drive_id], dl
277e5476626SJessica Hamilton
278e5476626SJessica Hamilton	; check for BIOS int 0x13 (disk services) extensions
279e5476626SJessica Hamilton	mov			ah, CHECK_DISK_EXTENSIONS_PRESENT
280e5476626SJessica Hamilton	mov			bx, 0x55aa
281e5476626SJessica Hamilton	; dl has not changed yet, still contains the drive ID
282e5476626SJessica Hamilton	int			BIOS_DISK_SERVICES
283e5476626SJessica Hamilton
284e5476626SJessica Hamilton	jc			.no_disk_extensions	; error
285e5476626SJessica Hamilton
286e5476626SJessica Hamilton	cmp			bx, 0xaa55
287e5476626SJessica Hamilton	jne			.no_disk_extensions	; call not supported?
288e5476626SJessica Hamilton
289e5476626SJessica Hamilton	test		cl, FIXED_DISK_SUPPORT
290e5476626SJessica Hamilton	jz			.no_disk_extensions
291e5476626SJessica Hamilton
292e5476626SJessica Hamilton	; we have disk extensions
293e5476626SJessica Hamilton	mov	byte	[sHasDiskExtensions], 1
294e5476626SJessica Hamilton
295e5476626SJessica Hamilton.no_disk_extensions:
296e5476626SJessica Hamilton
297e5476626SJessica Hamilton	; read in our second half
298e5476626SJessica Hamilton	xor			eax, eax					; block offset (1) to eax
299e5476626SJessica Hamilton	inc			ax
300e5476626SJessica Hamilton	lea			ebp, [second_boot_block]	; buffer to ebp
301e5476626SJessica Hamilton
302e5476626SJessica Hamilton	call		readOneBlock
303e5476626SJessica Hamilton
304e5476626SJessica Hamilton	; check superblock magic
305e5476626SJessica Hamilton	cmp	dword	[superblock + SuperBlock.magic1], SUPER_BLOCK_MAGIC1
306e5476626SJessica Hamilton	je			.valid_superblock_magic
307e5476626SJessica Hamilton
308e5476626SJessica Hamilton	error		kBadSuperBlockMagicString
309e5476626SJessica Hamilton
310e5476626SJessica Hamilton.valid_superblock_magic:
311e5476626SJessica Hamilton	jmp			continueMain
312e5476626SJessica Hamilton
313e5476626SJessica Hamilton
314e5476626SJessica Hamilton; Jumped to in case of error. si must contain the pointer to the error string.
315e5476626SJessica Hamilton_error:
316e5476626SJessica Hamilton	call		_writeString
317e5476626SJessica Hamilton
318e5476626SJessica Hamilton	; wait for a key and reboot
319e5476626SJessica Hamilton	mov			ah, READ_CHAR
320e5476626SJessica Hamilton	int			BIOS_KEYBOARD_SERVICES
321e5476626SJessica Hamilton	int			BIOS_REBOOT
322e5476626SJessica Hamilton
323e5476626SJessica Hamilton
324e5476626SJessica Hamilton; _writeString
325e5476626SJessica Hamilton; Prints a string to the screen.
326e5476626SJessica Hamilton; [entry]
327e5476626SJessica Hamilton; si:		pointer to null terminated string
328e5476626SJessica Hamilton; [exit]
329e5476626SJessica Hamilton; trashes:	si, ax
330e5476626SJessica Hamilton_writeString:
331e5476626SJessica Hamilton.loop:
332e5476626SJessica Hamilton	lodsb		; al <- [si++]
333e5476626SJessica Hamilton	or			al, al
334e5476626SJessica Hamilton	jz			.loopend
335e5476626SJessica Hamilton
336e5476626SJessica Hamilton	mov			ah, WRITE_CHAR
337e5476626SJessica Hamilton	int			BIOS_VIDEO_SERVICES
338e5476626SJessica Hamilton
339e5476626SJessica Hamilton	jmp			.loop
340e5476626SJessica Hamilton.loopend:
341e5476626SJessica Hamilton
342e5476626SJessica Hamilton	ret
343e5476626SJessica Hamilton
344e5476626SJessica Hamilton
345e5476626SJessica Hamilton; readOneBlock
346e5476626SJessica Hamilton; Reads one disk block from the given offset into the specified buffer.
347e5476626SJessica Hamilton; [entry]
348e5476626SJessica Hamilton; eax:		block offset
349e5476626SJessica Hamilton; ebp:		buffer address
350e5476626SJessica Hamilton; [exit]
351e5476626SJessica Hamilton; trashes:	di
352e5476626SJessica HamiltonreadOneBlock:
353e5476626SJessica Hamilton	mov			di, 1
354e5476626SJessica Hamilton	; fall through ...
355e5476626SJessica Hamilton
356e5476626SJessica Hamilton
357e5476626SJessica Hamilton; readBlocks
358e5476626SJessica Hamilton; Reads one or more disk blocks from the given offset into the specified buffer.
359e5476626SJessica Hamilton; [entry]
360e5476626SJessica Hamilton; eax:	block offset
361e5476626SJessica Hamilton; di:	block count
362e5476626SJessica Hamilton; ebp:	buffer address
363e5476626SJessica HamiltonreadBlocks:
364e5476626SJessica Hamilton	pushad
365e5476626SJessica Hamilton
366e5476626SJessica Hamilton	; add the partition offset
367e5476626SJessica Hamilton	add	dword	eax, [kPartitionOffset]
368e5476626SJessica Hamilton
369e5476626SJessica Hamilton	; drive ID to dl
370e5476626SJessica Hamilton	mov			dl, [bios_drive_id]
371e5476626SJessica Hamilton
372e5476626SJessica Hamilton	cmp	byte	[sHasDiskExtensions], 0
373e5476626SJessica Hamilton	jz			.no_extension_support
374e5476626SJessica Hamilton
375e5476626SJessica Hamilton	; set packet size, block count, and buffer in the address packet
376e5476626SJessica Hamilton	mov	word	[address_packet + AddressPacket.packet_size], \
377e5476626SJessica Hamilton				sizeof(AddressPacket)
378e5476626SJessica Hamilton	mov			[address_packet + AddressPacket.block_count], di
379e5476626SJessica Hamilton	mov			[address_packet + AddressPacket.buffer], ebp
380e5476626SJessica Hamilton
381e5476626SJessica Hamilton	; write the block offset to the address packet
382e5476626SJessica Hamilton	mov	dword	[address_packet + AddressPacket.offset + quadword.lower], eax
383e5476626SJessica Hamilton	xor			eax, eax
384e5476626SJessica Hamilton	mov	dword	[address_packet + AddressPacket.offset + quadword.upper], eax
385e5476626SJessica Hamilton
386e5476626SJessica Hamilton	; do the "extended read" call
387e5476626SJessica Hamilton	; address packet address in si
388e5476626SJessica Hamilton	mov			si, address_packet
389e5476626SJessica Hamilton	mov			ah, EXTENDED_READ
390e5476626SJessica Hamilton	int			BIOS_DISK_SERVICES
391e5476626SJessica Hamilton
392e5476626SJessica Hamilton	jnc			.no_error	; error?
393e5476626SJessica Hamilton
394e5476626SJessica Hamilton.read_error:
395e5476626SJessica Hamilton	error		kReadErrorString
396e5476626SJessica Hamilton
397e5476626SJessica Hamilton.no_extension_support:
398e5476626SJessica Hamilton	; no fixed disk extension support
399e5476626SJessica Hamilton
400e5476626SJessica Hamilton	; save parameters
401e5476626SJessica Hamilton	push		eax
402e5476626SJessica Hamilton
403e5476626SJessica Hamilton	; read drive parameters
404e5476626SJessica Hamilton	mov			ah, READ_DRIVE_PARAMETERS
405e5476626SJessica Hamilton	int			BIOS_DISK_SERVICES
406e5476626SJessica Hamilton	jc			.read_error
407e5476626SJessica Hamilton
408e5476626SJessica Hamilton	; -> cl - max cylinder 9:8
409e5476626SJessica Hamilton	;		- sectors per track
410e5476626SJessica Hamilton	;    ch - max cylinder 7:0
411e5476626SJessica Hamilton	;    dh - max head
412e5476626SJessica Hamilton
413e5476626SJessica Hamilton	; compute sectors
414e5476626SJessica Hamilton	pop			eax			; LBA
415e5476626SJessica Hamilton	xchg		dl, dh		; max head to dx
416e5476626SJessica Hamilton	xor			dh, dh		;
417e5476626SJessica Hamilton	push		dx			; save max head
418e5476626SJessica Hamilton	xor			edx, edx
419e5476626SJessica Hamilton	and			ecx, 0x3f	; filter sectors per track
420e5476626SJessica Hamilton	div			ecx			; divide by sectors per track
421e5476626SJessica Hamilton
422e5476626SJessica Hamilton	inc			dl			; sector numbering starts with 1
423e5476626SJessica Hamilton	pop			cx			; restore max head
424e5476626SJessica Hamilton	push		dx			; save sector
425e5476626SJessica Hamilton
426e5476626SJessica Hamilton	; compute heads and cylinders
427e5476626SJessica Hamilton	xor			dx, dx
428e5476626SJessica Hamilton	xor			ch, ch		; cl only
429e5476626SJessica Hamilton	inc			cx			; max head -> head count
430e5476626SJessica Hamilton	div			cx			; divide by head count
431e5476626SJessica Hamilton	; result: ax: cylinder, dx: head
432e5476626SJessica Hamilton
433e5476626SJessica Hamilton	; we need to shuffle things a bit
434e5476626SJessica Hamilton	or			dh, dl		; head
435e5476626SJessica Hamilton
436e5476626SJessica Hamilton	mov			cx, ax
437e5476626SJessica Hamilton	xchg		cl, ch		; ch: 7:0 cylinder
438e5476626SJessica Hamilton	ror			cl, 2		; cl: 9:8 cylinder in bits 7:6
439e5476626SJessica Hamilton	pop			dx			; restore sector
440e5476626SJessica Hamilton	or			cl, dl		; cl: 9:8 cylinder, 5:0 sector
441e5476626SJessica Hamilton
442e5476626SJessica Hamilton	; buffer address must be in es:bx
443e5476626SJessica Hamilton	mov			eax, ebp	; count
444e5476626SJessica Hamilton	shr			eax, 16
445e5476626SJessica Hamilton	push		es			; save es
446e5476626SJessica Hamilton	push		ax
447e5476626SJessica Hamilton	pop			es
448e5476626SJessica Hamilton	mov			bx, bp
449e5476626SJessica Hamilton
450e5476626SJessica Hamilton	; block count to ax
451e5476626SJessica Hamilton	mov			ax, di		; count
452e5476626SJessica Hamilton
453e5476626SJessica Hamilton	mov			dl, [bios_drive_id]
454e5476626SJessica Hamilton	mov			ah, READ_DISK_SECTORS
455e5476626SJessica Hamilton	int			BIOS_DISK_SERVICES
456e5476626SJessica Hamilton
457e5476626SJessica Hamilton	pop			es			; restore es
458e5476626SJessica Hamilton
459e5476626SJessica Hamilton	cmp			ax, di
460e5476626SJessica Hamilton	jne			.read_error
461e5476626SJessica Hamilton
462e5476626SJessica Hamilton.no_error:
463e5476626SJessica Hamilton	popad
464e5476626SJessica Hamilton
465e5476626SJessica Hamilton	ret
466e5476626SJessica Hamilton
467e5476626SJessica Hamilton
468e5476626SJessica Hamilton; readBuffer
469e5476626SJessica Hamilton; Reads the next 1024 bytes from the data of the current inode (the one read
470e5476626SJessica Hamilton; with the last call to readInode) into a buffer. The function uses an own stack
471e5476626SJessica Hamilton; which it switches to at the beginning (switching back at the end). This
472e5476626SJessica Hamilton; custom stack is initially in an "after pushad" state. The functions does a
473e5476626SJessica Hamilton; popad at the beginning and pushad at the end, thus keeping its register
474e5476626SJessica Hamilton; configuration between calls (see some lines below for the meaning of the
475e5476626SJessica Hamilton; registers). readBufferInit must be called before the first call to readBuffer
476e5476626SJessica Hamilton; for a node. After that manipulating the parameters (registers) of the
477e5476626SJessica Hamilton; function can be done by accessing the respective values on the custom stack.
478e5476626SJessica Hamilton; [exit]
479e5476626SJessica Hamilton; ax:	0x0000 - nothing read (end of file/directory)
480e5476626SJessica Hamilton;		0x0001 - read one buffer
481e5476626SJessica HamiltonreadBuffer:
482e5476626SJessica Hamilton	xor			ax, ax				; the default result (end)
483e5476626SJessica Hamilton	pushad
484e5476626SJessica Hamilton
485e5476626SJessica Hamilton	; set our custom stack and get our registers
486e5476626SJessica Hamilton	xchg		sp, [sReadBufferStack]
487e5476626SJessica Hamilton	popad
488e5476626SJessica Hamilton
489e5476626SJessica Hamilton	; registers:
490e5476626SJessica Hamilton	; eax		- read offset
491e5476626SJessica Hamilton	; ecx		- blocks left of the current block run
492e5476626SJessica Hamilton	; edx		- max remaining block runs
493e5476626SJessica Hamilton	; ebp		- pointer to the read buffer
494e5476626SJessica Hamilton	; si		- pointer to the current block run
495e5476626SJessica Hamilton	; edi		- index of the current indirect block
496e5476626SJessica Hamilton	; bx		- remaining indirect blocks
497e5476626SJessica Hamilton
498e5476626SJessica Hamilton	and			ecx, ecx
499e5476626SJessica Hamilton	jg			.blocks_left_valid
500e5476626SJessica Hamilton
501e5476626SJessica Hamilton	; blocks_left <= 0: decrement remaining block run index
502e5476626SJessica Hamilton	dec			dl
503e5476626SJessica Hamilton	jge			.next_block_run
504e5476626SJessica Hamilton
505e5476626SJessica Hamilton.next_indirect_block:
506e5476626SJessica Hamilton	; no more block runs: decrement remaining indirect block count
507e5476626SJessica Hamilton	dec			bx
508e5476626SJessica Hamilton	jl			.nothing_read
509e5476626SJessica Hamilton
510e5476626SJessica Hamilton	; there are more indirect blocks: read the next one
511e5476626SJessica Hamilton	; get the buffer address to esi first
512e5476626SJessica Hamilton	xor			esi, esi
513e5476626SJessica Hamilton	lea			si, [indirect_block]
514e5476626SJessica Hamilton
515e5476626SJessica Hamilton	; read the block
516e5476626SJessica Hamilton	pushad
517e5476626SJessica Hamilton	xchg		eax, edi		; block index to eax
518e5476626SJessica Hamilton	mov			ebp, esi		; buffer pointer to ebp
519e5476626SJessica Hamilton
520e5476626SJessica Hamilton	call		readOneBlock
521e5476626SJessica Hamilton
522e5476626SJessica Hamilton	popad
523e5476626SJessica Hamilton
524e5476626SJessica Hamilton	; increment the indirect block index
525e5476626SJessica Hamilton	inc			edi
526e5476626SJessica Hamilton
527e5476626SJessica Hamilton	; maximal number of block runs in this block to edx
528e5476626SJessica Hamilton	xor			edx, edx
529e5476626SJessica Hamilton	mov			dl, 512 / sizeof(BlockRun)
530e5476626SJessica Hamilton
531e5476626SJessica Hamilton.next_block_run:
532e5476626SJessica Hamilton	; convert block run to disk block offset
533e5476626SJessica Hamilton	call		blockRunToDiskBlock
534e5476626SJessica Hamilton
535e5476626SJessica Hamilton	and			eax, eax
536e5476626SJessica Hamilton	jz			.next_indirect_block
537e5476626SJessica Hamilton
538e5476626SJessica Hamilton.more_blocks:
539e5476626SJessica Hamilton	; compute blocks_left
540e5476626SJessica Hamilton	xchg		eax, ecx							; save eax
541e5476626SJessica Hamilton	movzx		eax, word [si + BlockRun.length]	; length to eax
542e5476626SJessica Hamilton	call		bfsBlockToDiskBlock					; convert
543e5476626SJessica Hamilton	xchg		eax, ecx							; blocks_left now in ecx
544e5476626SJessica Hamilton
545e5476626SJessica Hamilton	; move to the next block run
546e5476626SJessica Hamilton	add			si, sizeof(BlockRun)
547e5476626SJessica Hamilton
548e5476626SJessica Hamilton.blocks_left_valid:
549e5476626SJessica Hamilton	; we'll read 2 disk blocks: so subtract 2 from blocks_left
550e5476626SJessica Hamilton	sub			ecx, 2
551e5476626SJessica Hamilton
552e5476626SJessica Hamilton	push		edi			; save edi -- we use it for other stuff for the
553e5476626SJessica Hamilton							; moment
554e5476626SJessica Hamilton
555e5476626SJessica Hamilton	mov			di, 2
556e5476626SJessica Hamilton
557e5476626SJessica Hamilton	call		readBlocks
558e5476626SJessica Hamilton
559e5476626SJessica Hamilton	; adjust read_offset
560e5476626SJessica Hamilton	add			eax, 2
561e5476626SJessica Hamilton
562e5476626SJessica Hamilton	; success
563e5476626SJessica Hamilton	mov			di, [sReadBufferStack]
564e5476626SJessica Hamilton	mov	byte	[di + PushadStack.eax], 1
565e5476626SJessica Hamilton
566e5476626SJessica Hamilton	pop			edi			; restore edi
567e5476626SJessica Hamilton
568e5476626SJessica Hamilton.nothing_read:
569e5476626SJessica Hamilton	pushad
570e5476626SJessica Hamilton	xchg		sp, [sReadBufferStack]
571e5476626SJessica Hamilton	popad
572e5476626SJessica Hamilton	ret
573e5476626SJessica Hamilton
574e5476626SJessica Hamilton
575e5476626SJessica Hamilton; readBufferInit
576e5476626SJessica Hamilton; Initializes readBuffer's context for the current inode (the one read with
577e5476626SJessica Hamilton; the last call to readInode). Must be called before the first call to
578e5476626SJessica Hamilton; readBuffer for an inode.
579e5476626SJessica HamiltonreadBufferInit:
580e5476626SJessica Hamilton	; switch to readBuffer context
581e5476626SJessica Hamilton	pushad
582e5476626SJessica Hamilton	xchg		sp, [sReadBufferStack]
583e5476626SJessica Hamilton	popad
584e5476626SJessica Hamilton
585e5476626SJessica Hamilton	; clear the number of indirect blocks, for the case there aren't any
586e5476626SJessica Hamilton	xor			bx, bx
587e5476626SJessica Hamilton
588e5476626SJessica Hamilton	; check whether there are indirect blocks (max_indirect_range != 0)
589e5476626SJessica Hamilton	lea			si, [inode + BFSInode.data + DataStream.max_indirect_range]
590e5476626SJessica Hamilton	cmp	dword	[si], 0
591e5476626SJessica Hamilton	jnz			.has_indirect_blocks
592e5476626SJessica Hamilton	cmp	dword	[si + 4], 0
593e5476626SJessica Hamilton	jz			.no_indirect_blocks
594e5476626SJessica Hamilton
595e5476626SJessica Hamilton.has_indirect_blocks:
596e5476626SJessica Hamilton	; get the first indirect block index
597e5476626SJessica Hamilton	lea			si, [inode + BFSInode.data + DataStream.indirect]
598e5476626SJessica Hamilton	call		blockRunToDiskBlock
599e5476626SJessica Hamilton
600e5476626SJessica Hamilton	and			eax, eax
601e5476626SJessica Hamilton	jz			.no_indirect_blocks
602e5476626SJessica Hamilton
603e5476626SJessica Hamilton	; indirect block index to edi
604e5476626SJessica Hamilton	xchg		edi, eax
605e5476626SJessica Hamilton
606e5476626SJessica Hamilton	; get number of indirect blocks
607e5476626SJessica Hamilton	movzx		eax, word [si + BlockRun.length]
608e5476626SJessica Hamilton	call		bfsBlockToDiskBlock
609e5476626SJessica Hamilton	xchg		bx, ax							; number to bx
610e5476626SJessica Hamilton
611e5476626SJessica Hamilton.no_indirect_blocks:
612e5476626SJessica Hamilton
613e5476626SJessica Hamilton	; blocks_left = 0, max_remaining_direct_block_runs = NUM_DIRECT_BLOCKS
614e5476626SJessica Hamilton	xor			ecx, ecx
615e5476626SJessica Hamilton	mov			dl, NUM_DIRECT_BLOCKS
616e5476626SJessica Hamilton
617e5476626SJessica Hamilton	; position si at the 1st block run
618e5476626SJessica Hamilton	lea			si, [inode + BFSInode.data + DataStream.direct]
619e5476626SJessica Hamilton
620e5476626SJessica Hamilton	; buffer address
621e5476626SJessica Hamilton	xor			ebp, ebp
622e5476626SJessica Hamilton	mov			bp, buffer
623e5476626SJessica Hamilton
624e5476626SJessica Hamilton	; switch context back (use readBuffer's code)
625e5476626SJessica Hamilton	jmp			readBuffer.nothing_read
626e5476626SJessica Hamilton
627e5476626SJessica Hamilton
628e5476626SJessica Hamilton; data
629e5476626SJessica Hamilton
630e5476626SJessica Hamilton; the custom stack for readBuffer
631e5476626SJessica HamiltonsReadBufferStack			dw	READ_BUFFER_STACK - sizeof(PushadStack)
632e5476626SJessica Hamilton								; already start in "after pushad" state
633e5476626SJessica HamiltonsHasDiskExtensions			db	0	; 1 if the drive supports the extended read
634e5476626SJessica Hamilton									; BIOS call.
635e5476626SJessica Hamilton
636e5476626SJessica Hamilton; error strings
637e5476626SJessica Hamilton; If DEBUG is enabled, we use more descriptive ones.
638e5476626SJessica Hamilton%if DEBUG
639e5476626SJessica HamiltonkReadErrorString			db	"read error", 0
640e5476626SJessica HamiltonkBadSuperBlockMagicString	db	"bad superblock", 0
641e5476626SJessica HamiltonkNotADirectoryString		db	"not a directory", 0
642e5476626SJessica HamiltonkBadInodeMagicString		db	"bad inode", 0
643e5476626SJessica HamiltonkNoZbeosString				db	"no loader", 0
644e5476626SJessica Hamilton%else
6454124da50SAlexander von Gluck IVkErrorString				db	"bios_ia32 stage1: Failed to load OS. Press any key to reboot..."
646e5476626SJessica Hamilton							db	0
647e5476626SJessica Hamilton%endif
648e5476626SJessica Hamilton
649e5476626SJessica HamiltonkPathComponents:
650e5476626SJessica HamiltonpathComponent				"system"
651e5476626SJessica HamiltonpathComponent				"packages"
652e5476626SJessica HamiltonkLastPathComponent:
6534124da50SAlexander von Gluck IVpathComponent				"haiku_loader"
654e5476626SJessica Hamilton							db	0
655e5476626SJessica Hamilton
656e5476626SJessica Hamilton
657e5476626SJessica Hamilton
658e5476626SJessica Hamiltonfirst_code_part_end:
659e5476626SJessica Hamilton
660e5476626SJessica Hamilton; The first (max) 512 - 4 -2 bytes of the boot code end here
661e5476626SJessica Hamilton; ---------------------------------------------------------------------------
662e5476626SJessica Hamilton
663e5476626SJessica Hamilton				%if first_code_part_end - start > PARTITION_OFFSET_OFFSET
664e5476626SJessica Hamilton					%error "Code exceeds first boot code block!"
665e5476626SJessica Hamilton				%endif
666e5476626SJessica Hamilton
667e5476626SJessica Hamilton				; pad to the partition offset
668e5476626SJessica Hamilton				%rep start + PARTITION_OFFSET_OFFSET - first_code_part_end
669e5476626SJessica Hamilton					db	0
670e5476626SJessica Hamilton				%endrep
671e5476626SJessica Hamilton
672e5476626SJessica HamiltonkPartitionOffset			dd	0
673e5476626SJessica HamiltonkBootBlockSignature			dw	0xaa55
674e5476626SJessica Hamilton
675e5476626SJessica Hamilton
676e5476626SJessica Hamiltonsecond_boot_block:
677e5476626SJessica Hamilton
678e5476626SJessica Hamilton; first comes the BFS superblock
679e5476626SJessica Hamiltonsuperblock:
680e5476626SJessica Hamilton				%rep sizeof(SuperBlock)
681e5476626SJessica Hamilton					db	0
682e5476626SJessica Hamilton				%endrep
683e5476626SJessica Hamilton
684e5476626SJessica Hamilton
685e5476626SJessica Hamilton; the second part of the boot block code
686e5476626SJessica Hamilton
687e5476626SJessica Hamilton; readBootLoader
688e5476626SJessica Hamilton; Jumped to when all path components to the stage 2 boot loader have been
689e5476626SJessica Hamilton; resolved and the current inode is the one of the boot loader. The boot
690e5476626SJessica Hamilton; loader will be read into memory and jumped into.
691e5476626SJessica HamiltonreadBootLoader:
692e5476626SJessica Hamilton	; prepare for the first call to readBuffer
693e5476626SJessica Hamilton	call		readBufferInit
694e5476626SJessica Hamilton
695e5476626SJessica Hamilton	; the destination address: start at the beginning of segment 0x1000
696e5476626SJessica Hamilton	mov			ecx, 0x10000000
697e5476626SJessica Hamilton	mov			edi, ecx			; 0x1000:0000
698e5476626SJessica Hamilton
699e5476626SJessica Hamilton	xor			ebx, ebx
700e5476626SJessica Hamilton	mov			bx, [sReadBufferStack]
701e5476626SJessica Hamilton
702e5476626SJessica Hamilton.read_loop:
703e5476626SJessica Hamilton	; write destination address
704e5476626SJessica Hamilton	mov			[bx + PushadStack.ebp], edi
705e5476626SJessica Hamilton
706e5476626SJessica Hamilton	; compute next destination address
707e5476626SJessica Hamilton	add			di, 1024
708e5476626SJessica Hamilton	jnc			.no_carry
709e5476626SJessica Hamilton	add			edi, ecx		; the lower 16 bit wrapped around: add 0x1000
710e5476626SJessica Hamilton								; (64 KB) to the segment selector
711e5476626SJessica Hamilton.no_carry:
712e5476626SJessica Hamilton
713e5476626SJessica Hamilton	call		readBuffer
714e5476626SJessica Hamilton
715e5476626SJessica Hamilton	; loop as long as reading succeeds
716e5476626SJessica Hamilton	and			ax, ax
717e5476626SJessica Hamilton	jnz			.read_loop
718e5476626SJessica Hamilton
719e5476626SJessica Hamilton	; We have successfully read the complete boot loader package. The actual
720e5476626SJessica Hamilton	; code is located at the beginning of the package file heap which starts
721e5476626SJessica Hamilton	; directly after the header. Since the boot loader code expects to be
722e5476626SJessica Hamilton	; located at a fixed address, we have to move it there.
723e5476626SJessica Hamilton
724e5476626SJessica Hamilton	; First set up the source and target segment registers. We keep the current
725e5476626SJessica Hamilton	; value also in bx, since it is easier to do arithmetics with it. We keep
726e5476626SJessica Hamilton	; the increment value for the segment registers in dx.
727e5476626SJessica Hamilton	mov			bx, 0x1000		; initial ds and es value
728e5476626SJessica Hamilton	push		bx
729e5476626SJessica Hamilton	pop			ds
730e5476626SJessica Hamilton	push		bx
731e5476626SJessica Hamilton	pop			es
732e5476626SJessica Hamilton	mov			dx, bx			; the increment value for the segment registers
733e5476626SJessica Hamilton
734e5476626SJessica Hamilton	; Determine how much we have to copy and from where to where. si will be
735e5476626SJessica Hamilton	; the source and di the destination pointer (both segment relative) and
736e5476626SJessica Hamilton	; ecx is our byte count. To save instructions we only approximate the count.
737e5476626SJessica Hamilton	; It may be almost a full segment greater than necessary. But that doesn't
738e5476626SJessica Hamilton	; really harm.
739e5476626SJessica Hamilton	mov			ecx, edi
740e5476626SJessica Hamilton	shr			ecx, 12								; byte count
741e5476626SJessica Hamilton	xor			di, di								; target
742e5476626SJessica Hamilton	mov			ax, [di + HPKGHeader.header_size]	; header size (big endian)
743e5476626SJessica Hamilton	xchg		ah, al
744e5476626SJessica Hamilton	mov			si, ax								; source
745e5476626SJessica Hamilton
746e5476626SJessica Hamilton.move_loop:
747e5476626SJessica Hamilton	movsb
748e5476626SJessica Hamilton	test		si, si
749e5476626SJessica Hamilton	jnz			.move_no_source_overflow
750e5476626SJessica Hamilton	add			bx, dx
751e5476626SJessica Hamilton	push		bx
752e5476626SJessica Hamilton	pop			ds
753e5476626SJessica Hamilton.move_no_source_overflow:
754e5476626SJessica Hamilton	test		di, di
755e5476626SJessica Hamilton	jnz			.move_no_destination_overflow
756e5476626SJessica Hamilton	push		bx
757e5476626SJessica Hamilton	pop			es
758e5476626SJessica Hamilton				; Using bx (the value of ds) is fine, since we assume that the
759e5476626SJessica Hamilton				; source is less than a segment ahead of the destination.
760e5476626SJessica Hamilton.move_no_destination_overflow:
761e5476626SJessica Hamilton	dec			ecx
762e5476626SJessica Hamilton	jnz			.move_loop
763e5476626SJessica Hamilton
764e5476626SJessica Hamilton	; We have successfully prepared the boot loader code. Set up the
765e5476626SJessica Hamilton	; environment for it.
766e5476626SJessica Hamilton	; eax - partition offset in sectors
767e5476626SJessica Hamilton	push		cs
768e5476626SJessica Hamilton	pop			ds
769e5476626SJessica Hamilton				; temporarily reset ds, so we can access our variables
770e5476626SJessica Hamilton	mov dword	eax, [kPartitionOffset]
771e5476626SJessica Hamilton
772e5476626SJessica Hamilton	; dl - BIOS drive ID
773e5476626SJessica Hamilton	xor			edx, edx
774e5476626SJessica Hamilton	mov			dl, [bios_drive_id]
775e5476626SJessica Hamilton
776e5476626SJessica Hamilton	; Note: We don't have to set ds and es, since the stage 2 sets them
777e5476626SJessica Hamilton	; anyway before accessing any data.
778e5476626SJessica Hamilton
779e5476626SJessica Hamilton	; enter the boot loader
780e5476626SJessica Hamilton	jmp			0x1000:0x200
781e5476626SJessica Hamilton
782e5476626SJessica Hamilton
783e5476626SJessica Hamilton; continueMain
784e5476626SJessica Hamilton; Continues the "main" function of the boot code. Mainly contains the loop that
785e5476626SJessica Hamilton; resolves the path to the stage 2 boot loader, jumping to readBootLoader when
786e5476626SJessica Hamilton; it was found.
787e5476626SJessica HamiltoncontinueMain:
788e5476626SJessica Hamilton
789e5476626SJessica Hamilton	; load root node
790e5476626SJessica Hamilton	; convert root node block run to block
791e5476626SJessica Hamilton	lea			si, [superblock + SuperBlock.root_dir]
792e5476626SJessica Hamilton	call		blockRunToDiskBlock
793e5476626SJessica Hamilton
794e5476626SJessica Hamilton	call		readInode
795e5476626SJessica Hamilton
796e5476626SJessica Hamilton	; stack:
797e5476626SJessica Hamilton	; word		number of keys					(in .key_loop)
798e5476626SJessica Hamilton	; word		previous key length				(in .key_loop)
799e5476626SJessica Hamilton
800e5476626SJessica Hamilton	; registers:
801e5476626SJessica Hamilton	; di	- path component					(in .search_loop)
802e5476626SJessica Hamilton	; cx	- path component length				(in .search_loop)
803e5476626SJessica Hamilton	; ax	- remaining key count (-1)			(in .key_loop)
804e5476626SJessica Hamilton	; bx	- key lengths array (current pos)	(in .key_loop)
805e5476626SJessica Hamilton	; dx	- previous absolute key length		(in .key_loop)
806e5476626SJessica Hamilton	; si	- current key						(in .key_loop)
807e5476626SJessica Hamilton	; bp	- current key length				(in .key_loop)
808e5476626SJessica Hamilton
809e5476626SJessica Hamilton	lea			di, [kPathComponents]
810e5476626SJessica Hamilton
811e5476626SJessica Hamilton.search_loop:
812e5476626SJessica Hamilton	; the path component we're looking for
813e5476626SJessica Hamilton	xor			cx, cx
814e5476626SJessica Hamilton	mov			cl, [di]	; the path component length
815e5476626SJessica Hamilton	inc			di			; the path component itself
816e5476626SJessica Hamilton	and			cl, cl
817e5476626SJessica Hamilton	jz			readBootLoader ; no more path components: We found the boot
818e5476626SJessica Hamilton								 ; loader! Now read it in.
819e5476626SJessica Hamilton
820e5476626SJessica Hamilton.continue_search:
821e5476626SJessica Hamilton	; is a directory?
822e5476626SJessica Hamilton	mov			eax, [inode + BFSInode.mode]
823e5476626SJessica Hamilton	and			eax, S_IFMT
824e5476626SJessica Hamilton	cmp			eax, S_IFDIR
825e5476626SJessica Hamilton	je			.is_directory
826e5476626SJessica Hamilton
827e5476626SJessica Hamilton	error		kNotADirectoryString
828e5476626SJessica Hamilton
829e5476626SJessica Hamilton.is_directory:
830e5476626SJessica Hamilton	; prepare for the first call to readBuffer
831e5476626SJessica Hamilton	call		readBufferInit
832e5476626SJessica Hamilton
833e5476626SJessica Hamilton	; we skip the first 1024 bytes (that's the b+tree header)
834e5476626SJessica Hamilton	call		readBuffer
835e5476626SJessica Hamilton	and			ax, ax
836e5476626SJessica Hamilton	jnz			.read_loop
837e5476626SJessica Hamilton
838e5476626SJessica Hamilton.not_found:
839e5476626SJessica Hamilton	error		kNoZbeosString
840e5476626SJessica Hamilton
841e5476626SJessica Hamilton.read_loop:
842e5476626SJessica Hamilton
843e5476626SJessica Hamilton	; read the next B+ tree node
844e5476626SJessica Hamilton	call		readBuffer
845e5476626SJessica Hamilton	and			ax, ax
846e5476626SJessica Hamilton	jz			.not_found
847e5476626SJessica Hamilton
848e5476626SJessica Hamilton	; we're only interested in leaf nodes (overflow_link == -1)
849e5476626SJessica Hamilton	xor			eax, eax
850e5476626SJessica Hamilton	dec			eax
851e5476626SJessica Hamilton	cmp			[buffer + BPlusTreeNode.overflow_link + quadword.lower], eax
852e5476626SJessica Hamilton	jne			.read_loop
853e5476626SJessica Hamilton	cmp			[buffer + BPlusTreeNode.overflow_link + quadword.upper], eax
854e5476626SJessica Hamilton	jne			.read_loop
855e5476626SJessica Hamilton
856e5476626SJessica Hamilton	; get the keylengths and keys
857e5476626SJessica Hamilton
858e5476626SJessica Hamilton	; the keys
859e5476626SJessica Hamilton	lea			si, [buffer + sizeof(BPlusTreeNode)]
860e5476626SJessica Hamilton
861e5476626SJessica Hamilton	; the keylengths array
862e5476626SJessica Hamilton	mov			bx, [buffer + BPlusTreeNode.all_key_length]
863e5476626SJessica Hamilton	add			bx, sizeof(BPlusTreeNode) + 7
864e5476626SJessica Hamilton	and			bl, 0xf8
865e5476626SJessica Hamilton	add			bx, buffer
866e5476626SJessica Hamilton
867e5476626SJessica Hamilton	; number of keys
868e5476626SJessica Hamilton	mov			ax, [buffer + BPlusTreeNode.all_key_count]
869e5476626SJessica Hamilton	push		ax
870e5476626SJessica Hamilton
871e5476626SJessica Hamilton	; the "previous" key length
872e5476626SJessica Hamilton	push word	0
873e5476626SJessica Hamilton
874e5476626SJessica Hamilton.key_loop:
875e5476626SJessica Hamilton	; while there are more keys
876e5476626SJessica Hamilton	dec			ax
877e5476626SJessica Hamilton	jl			.key_loop_end
878e5476626SJessica Hamilton
879e5476626SJessica Hamilton	; get current key length
880e5476626SJessica Hamilton	mov			bp, [bx]
881e5476626SJessica Hamilton
882e5476626SJessica Hamilton	; exchange previous key length on the stack and compute the actual
883e5476626SJessica Hamilton	; length (the key lengths array contains summed-up lengths)
884e5476626SJessica Hamilton	pop			dx
885e5476626SJessica Hamilton	push		bp
886e5476626SJessica Hamilton	sub			bp, dx
887e5476626SJessica Hamilton
888e5476626SJessica Hamilton	; Compare the key length. For the last component we only want to check
889e5476626SJessica Hamilton	; whether the prefix matches.
890e5476626SJessica Hamilton	cmp			cx, bp
891e5476626SJessica Hamilton	jg			.skip_key
892e5476626SJessica Hamilton
893e5476626SJessica Hamilton	cmp			di, kLastPathComponent + 1
894e5476626SJessica Hamilton	je			.compare_keys
895e5476626SJessica Hamilton
896e5476626SJessica Hamilton	cmp			cx, bp
897e5476626SJessica Hamilton	jne			.skip_key
898e5476626SJessica Hamilton
899e5476626SJessica Hamilton	; compare path component (di) with key (si), length cx (<= bp)
900e5476626SJessica Hamilton.compare_keys:
901e5476626SJessica Hamilton	pusha
902e5476626SJessica Hamilton	repe cmpsb
903e5476626SJessica Hamilton	popa
904e5476626SJessica Hamilton
905e5476626SJessica Hamilton	jne			.skip_key
906e5476626SJessica Hamilton
907e5476626SJessica Hamilton	; keys are equal
908e5476626SJessica Hamilton
909e5476626SJessica Hamilton	; get the current index
910e5476626SJessica Hamilton	pop			dx			; pop previous key length
911e5476626SJessica Hamilton	pop			dx			; key count
912e5476626SJessica Hamilton	inc			ax			; ax is decremented already at the loop top
913e5476626SJessica Hamilton	sub			dx, ax		; the current index
914e5476626SJessica Hamilton
915e5476626SJessica Hamilton	; get to the end of the key lengths array
916e5476626SJessica Hamilton	shl			ax, 1		; number of bytes remaining in the array
917e5476626SJessica Hamilton	add			bx, ax
918e5476626SJessica Hamilton	shl			dx, 3		; offset in the value (block number) array
919e5476626SJessica Hamilton	add			bx, dx		; bx now points to the block number of the inode
920e5476626SJessica Hamilton
921e5476626SJessica Hamilton	; read the block offset and load the Inode
922e5476626SJessica Hamilton	mov			eax, [bx]
923e5476626SJessica Hamilton	call		bfsBlockToDiskBlock
924e5476626SJessica Hamilton
925e5476626SJessica Hamilton	call		readInode
926e5476626SJessica Hamilton
927e5476626SJessica Hamilton	; next path component
928e5476626SJessica Hamilton	add			di, cx
929e5476626SJessica Hamilton	jmp			.search_loop
930e5476626SJessica Hamilton
931e5476626SJessica Hamilton.skip_key:
932e5476626SJessica Hamilton	inc			bx			; next key length
933e5476626SJessica Hamilton	inc			bx
934e5476626SJessica Hamilton	add			si, bp		; next key
935e5476626SJessica Hamilton	jmp			.key_loop
936e5476626SJessica Hamilton
937e5476626SJessica Hamilton.key_loop_end:
938e5476626SJessica Hamilton	; all keys check, but nothing found: need to read in the next tree node
939e5476626SJessica Hamilton	pop			dx			; pop previous key length
940e5476626SJessica Hamilton	pop			dx			; pop key count
941e5476626SJessica Hamilton	jmp			.read_loop
942e5476626SJessica Hamilton
943e5476626SJessica Hamilton
944e5476626SJessica Hamilton; readInode
945e5476626SJessica Hamilton; Reads the inode at the specified disk block offset into the buffer "inode".
946e5476626SJessica Hamilton; [entry]
947e5476626SJessica Hamilton; eax:	disk block offset
948e5476626SJessica HamiltonreadInode:
949e5476626SJessica Hamilton	pushad
950e5476626SJessica Hamilton
951e5476626SJessica Hamilton	; buffer address to ebp
952e5476626SJessica Hamilton	xor			ebp, ebp
953e5476626SJessica Hamilton	mov			bp, inode
954e5476626SJessica Hamilton
955e5476626SJessica Hamilton	; An inode is actually one BFS block big, but we're interested only in the
956e5476626SJessica Hamilton	; administrative part (not the small data section), which easily fits into
957e5476626SJessica Hamilton	; one disk block.
958e5476626SJessica Hamilton	call		readOneBlock
959e5476626SJessica Hamilton
960e5476626SJessica Hamilton	cmp	dword	[inode + BFSInode.magic1], INODE_MAGIC1
961e5476626SJessica Hamilton	je			.no_error
962e5476626SJessica Hamilton
963e5476626SJessica Hamilton	error		kBadInodeMagicString
964e5476626SJessica Hamilton
965e5476626SJessica Hamilton.no_error:
966e5476626SJessica Hamilton	popad
967e5476626SJessica Hamilton
968e5476626SJessica Hamilton	ret
969e5476626SJessica Hamilton
970e5476626SJessica Hamilton
971e5476626SJessica Hamilton; blockRunToDiskBlock
972e5476626SJessica Hamilton; Computes the start address (in disk blocks) of a given BFS block run.
973e5476626SJessica Hamilton; [entry]
974e5476626SJessica Hamilton; si:	pointer to the BlockRun
975e5476626SJessica Hamilton; [exit]
976e5476626SJessica Hamilton; eax:	disk block number, where the block run begins
977e5476626SJessica HamiltonblockRunToDiskBlock:
978e5476626SJessica Hamilton	push		ecx
979e5476626SJessica Hamilton
980e5476626SJessica Hamilton	; run.allocation_group << superblock.ag_shift
981e5476626SJessica Hamilton	mov			cl, [superblock + SuperBlock.ag_shift]
982e5476626SJessica Hamilton	mov 		eax, [si + BlockRun.allocation_group]
983e5476626SJessica Hamilton	shl			eax, cl
984e5476626SJessica Hamilton
985e5476626SJessica Hamilton	; add run.start
986e5476626SJessica Hamilton	xor			ecx, ecx
987e5476626SJessica Hamilton	mov			cx, [si + BlockRun.start]
988e5476626SJessica Hamilton
989e5476626SJessica Hamilton	add			eax, ecx
990e5476626SJessica Hamilton
991e5476626SJessica Hamilton	pop			ecx
992e5476626SJessica Hamilton
993e5476626SJessica Hamilton	; Fall through to bfsBlockToDiskBlock, which will convert the BFS block
994e5476626SJessica Hamilton	; number to a disk block number and return to our caller.
995e5476626SJessica Hamilton
996e5476626SJessica Hamilton
997e5476626SJessica Hamilton; bfsBlockToDiskBlock
998e5476626SJessica Hamilton; Converts a BFS block number to a disk block number.
999e5476626SJessica Hamilton; [entry]
1000e5476626SJessica Hamilton; eax:	BFS block number
1001e5476626SJessica Hamilton; [exit]
1002e5476626SJessica Hamilton; eax:	disk block number
1003e5476626SJessica HamiltonbfsBlockToDiskBlock:
1004e5476626SJessica Hamilton	push		cx
1005e5476626SJessica Hamilton
1006e5476626SJessica Hamilton	;   1 BFS block == superblock_block_size / 512 disk blocks
1007e5476626SJessica Hamilton	mov byte	cl, [superblock + SuperBlock.block_shift]
1008e5476626SJessica Hamilton	sub			cl, 9
1009e5476626SJessica Hamilton
1010e5476626SJessica Hamilton	shl			eax, cl
1011e5476626SJessica Hamilton
1012e5476626SJessica Hamilton	pop			cx
1013e5476626SJessica Hamilton	ret
1014e5476626SJessica Hamilton
1015e5476626SJessica Hamilton
1016e5476626SJessica Hamilton%if 0
1017e5476626SJessica Hamilton; _writeInt32
1018e5476626SJessica Hamilton; Writes the given number in 8 digit hexadecimal representation to screen.
1019e5476626SJessica Hamilton; Used for debugging only.
1020e5476626SJessica Hamilton; [entry]
1021e5476626SJessica Hamilton; eax:	The number to print.
1022e5476626SJessica Hamilton_writeInt32:
1023e5476626SJessica Hamilton	pushad
1024e5476626SJessica Hamilton
1025e5476626SJessica Hamilton	mov			bx, write_int32_buffer
1026e5476626SJessica Hamilton	mov byte	[bx + 8], 0	; terminating null
1027e5476626SJessica Hamilton	mov			di, 7
1028e5476626SJessica Hamilton
1029e5476626SJessica Hamilton.loop:
1030e5476626SJessica Hamilton	; get the lowest hex digit
1031e5476626SJessica Hamilton	mov			dx, ax
1032e5476626SJessica Hamilton	and			dl, 0xf
1033e5476626SJessica Hamilton
1034e5476626SJessica Hamilton	; convert hex digit to character
1035e5476626SJessica Hamilton	cmp			dl, 10
1036e5476626SJessica Hamilton	jl			.digit
1037e5476626SJessica Hamilton	add			dl, 'a' - '0' - 10
1038e5476626SJessica Hamilton
1039e5476626SJessica Hamilton.digit:
1040e5476626SJessica Hamilton	add			dl, '0'
1041e5476626SJessica Hamilton
1042e5476626SJessica Hamilton	; prepend the digit to the string
1043e5476626SJessica Hamilton	mov			[bx + di], dl
1044e5476626SJessica Hamilton
1045e5476626SJessica Hamilton	; shift out lowest digit and loop, if there are more digits
1046e5476626SJessica Hamilton	shr			eax, 4
1047e5476626SJessica Hamilton	dec			di
1048e5476626SJessica Hamilton	jge			.loop
1049e5476626SJessica Hamilton
1050e5476626SJessica Hamilton	; write the composed string
1051e5476626SJessica Hamilton	xchg		bx, si
1052e5476626SJessica Hamilton	call		_writeString
1053e5476626SJessica Hamilton
1054e5476626SJessica Hamilton	popad
1055e5476626SJessica Hamilton	ret
1056e5476626SJessica Hamilton%endif
1057e5476626SJessica Hamilton
1058e5476626SJessica Hamilton
1059e5476626SJessica Hamilton; check whether we are small enough
1060e5476626SJessica Hamiltonend:
1061e5476626SJessica Hamilton				%if end - start > 1024
1062e5476626SJessica Hamilton					%error "Code exceeds second boot code block!"
1063e5476626SJessica Hamilton				%endif
1064e5476626SJessica Hamilton
1065e5476626SJessica Hamilton; pad to 1024 bytes size
1066e5476626SJessica Hamilton				%rep start + 1024 - end
1067e5476626SJessica Hamilton					db	0
1068e5476626SJessica Hamilton				%endrep
1069e5476626SJessica Hamilton
1070e5476626SJessica Hamilton; Base offset for static variables.
1071e5476626SJessica Hamiltonstatic_variables: