summaryrefslogtreecommitdiff
path: root/bootblocks/bootlist.s
blob: a9c603c7ee8712e2d6a95af6069a1d389e2b3f4d (plain)
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
! This bootsector is modified by the installer to have a list of sectors at
! offset 256.

! Table format is a list of dwords. Each dword has a partition offest in
! the low 24 bits and a count in the high.
!
! Prob better to make it:    HH DD MM LL rather than DD HH MM LL
! as this matches the BIOS better
!
! Note:
!	Stack top is at abs location 64k.
!

! PS: This hasn't been tested much ... make that at all!

BOOTSEG = 0x07c0
LOADSEG = 0x07e0	! Just after boot sector.

public linear
linear = 1		! Is linear processing done ? (0 doesn't work)
public floppy
floppy = 0 *linear	! Allow for floppy drive ? (don't work)
public reloc
reloc  = 1 *linear	! Auto configure of bootpart.

macro locn
  if *-start>?1
   fail! ?1
  endif
  .blkb	?1 + start-*
mend

use16
entry start

org $7b00

! temporary space

n_cyl:		.blkw	1
n_secs:		.blkw	1
t_drive:	.blkb	1
t_sector:	.blkb	1
t_secs:		.blkw	1

org $7c00
start:
  j	code

runit:
  jmpi	0,0		! This instruction is altered by the installer

public execaddr		! Via this label.
execaddr = *-4

public bootpart
bootpart:
  .data4	0x80000011
code:

  if	reloc
  mov	cx,[si+8]	! Fetch the linear address of part from DS:SI
  mov	dh,[si+10]	! DL is drive number
  xchg	dl,dh		! Into normal form.
  endif

  xor	ax,ax
  mov	ds,ax
  mov	ss,ax
  mov	sp,ax

  if	reloc
  mov	[bootpart],cx
  mov	[bootpart+2],dx
  endif

! ASSUME ds=ss= 0  (cs should also be zero)

  mov	ax,#LOADSEG
  mov	es,ax

  mov	si,#table
load_addrs:
  cld

 if	linear
  lodsw
  mov	cx,ax
  add	cx,[bootpart]
  lodsw
  mov	dx,[bootpart+2]
  adc	dl,al
  mov	al,ah
 else
  lodsw				; XXX Broken, doesn't set AL correctly.
  mov	cx,ax
  lodsw
  mov	dx,ax
  lodsb
 endif

  test	al,al
  jz	runit

loadem:
  xor	bx,bx
  push	ax
  call	cread
  jc	failed
  pop	ax
  mov	cl,#5
  sal	ax,cl
  mov	bx,es
  add	ax,bx
  mov	es,ax
  j	load_addrs

! Humm, something goes wrong, not much we can do ...
! Let`s squeak then try again
failed:
  mov	ax,#$0E45
  mov	bx,#7
  int	$10
  pop	ax

  j	loadem

cread:
	! This function is like BIOS 1302 but it`s linear.
	! It's taken, almost, intact from LILO.

	! DH is drive, DL:CX is linear address, AL is count.
	! ES:BX is load address, beware of DMA limitations

	! All registers except AX and flags are preserved.

	mov	t_secs,al	! save number of sectors
lnread:	push	cx		! keep linear address
	push	dx
	xchg	dl,dh

	if	linear
	if	floppy
	test	dl,#0x80	! Floppy is physical only.
	jz	lrd
	endif

	push	bx		! BX is used as scratch
	push	cx		! LSW
	push	dx		! MSW with drive
	mov	ah,#8		! get drive geometry (do not clobber ES:DI)
	push	es
	push	di
	int	0x13
	pop	di
	pop	es
	mov	bl,dh		! BL <- #heads
	pop	dx		! get MSW

	jnc	int_ok		! error -> quit

	pop	cx		! discard stack contents
	pop	bx
	pop	dx
	pop	cx
	ret			! (carry is already set)
int_ok:
	mov	t_drive,dl	! save drive
	mov	dl,dh		! linear address into DX:AX
	xor	dh,dh
	mov	bh,dh		! (clear BH too)
	pop	ax
	push	cx		! compute #cyls-1
	xchg	ch,cl
	rol	ch,1
	rol	ch,1
	and	ch,#3
	mov	n_cyl,cx	! save #cyls-1
	pop	cx
	and	cx,#0x3f	! CX <- #secs
	mov	n_secs,cx
	div	cx		! AX <- track, DX <- sector
	inc	dl
	mov	t_sector,dl
	xor	dx,dx		! divide by #heads
	inc	bx
	div	bx		! AX <- cylinder, DX <- head
	mov	dh,dl		! set up DX (head:drive)
	mov	dl,t_drive
	cmp	ax,n_cyl	! valid cylinder number ?
	ja	linerr3		! no -> error
	xchg	ah,al		! build cylinder number
	ror	al,1
	ror	al,1
	or	al,t_sector
	mov	cx,ax
	pop	bx		! restore BX
	and	ax,#0x3f	! read beyond end of track ?
	add	ax,t_secs
	cmp	ax,n_secs
	jna	intrk		! no -> go on
	mov	al,n_secs	! read to end of track
	sub	al,t_sector
	inc	al
	jmp	lrd		! read it
intrk:	mov	al,t_secs	! read all sectors

	endif

lrd:	push	ax		! save AX and BX
	push	bx

	mov	ah,#2		!
	int	0x13		! read sectors

	pop	bx		! restore AX and BX and the linear address
	pop	ax
	pop	dx
	pop	cx

	if	linear

	jc	linerr		! error -> quit
	sub	t_secs,al	! adjust sector count
	jz	lindone		! zero -> done
	xor	ah,ah		! increase linear address
	add	cx,ax
	adc	dh,#0
	xchg	ah,al		! move BX
	add	ah,ah
	add	bx,ax
	jc	interr		! crossing segment boundaries -> error
	br	lnread		! process remaining sectors

linerr3:pop	bx		! pop BX and linear address
	pop	dx
	pop	cx
interr:	xor	ax,ax		! zero indicates internal error

	else
	jnc	lindone
	endif

linerr:	stc			! error
	ret
lindone:clc			! no error
	ret			! done


!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

public table
table:
! .long	0x80000012
! .byte 1
! .long 0x07e00000
! .byte 0