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
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
|
; -*- fundamental -*- (asm-mode sucks)
; $Id$
; -----------------------------------------------------------------------
;
; Copyright 1998 H. Peter Anvin - All Rights Reserved
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
; USA; either version 2 of the License, or (at your option) any later
; version; incorporated herein by reference.
;
; -----------------------------------------------------------------------
;
; syslinux.asm
;
; DOS installer for SYSLINUX
;
absolute 0
pspInt20: resw 1
pspNextParagraph: resw 1
resb 1 ; reserved
pspDispatcher: resb 5
pspTerminateVector: resd 1
pspControlCVector: resd 1
pspCritErrorVector: resd 1
resw 11 ; reserved
pspEnvironment: resw 1
resw 23 ; reserved
pspFCB_1: resb 16
pspFCB_2: resb 16
resd 1 ; reserved
pspCommandLen: resb 1
pspCommandArg: resb 127
section .text
org 0100h
_start:
mov ax,3000h ; Get DOS version
int 21h
xchg al,ah
mov [DOSVersion],ax
cmp ax,0314h ; DOS 3.20 minimum
jae dosver_ok
mov dx,msg_ancient_err
jmp die
section .bss
alignb 2
DOSVersion: resw 1
section .text
;
; Scan command line for a drive letter followed by a colon
;
dosver_ok:
xor cx,cx
mov si,pspCommandArg
mov cl,[pspCommandLen]
cmdscan1: jcxz bad_usage ; End of command line?
lodsb ; Load character
dec cx
cmp al,' ' ; White space
jbe cmdscan1
cmp al,'-'
je scan_option
or al,020h ; -> lower case
cmp al,'a' ; Check for letter
jb bad_usage
cmp al,'z'
ja bad_usage
sub al,'a' ; Convert to zero-based index
mov [DriveNo],al ; Save away drive index
section .bss
DriveNo: resb 1
section .text
;
; Got the leading letter, now the next character must be a colon
;
got_letter: jcxz bad_usage
lodsb
dec cx
cmp al,':'
jne bad_usage
;
; Got the colon; the rest better be whitespace
;
got_colon: jcxz got_cmdline
lodsb
dec cx
cmp al,' '
jbe got_colon
;
; We end up here if the command line doesn't parse
;
bad_usage: mov dx,msg_unfair
jmp die
section .data
msg_unfair: db 'Usage: syslinux [-s] <drive>:', 0Dh, 0Ah, '$'
section .text
;
; Scan for options after a - sign. The only recognized option right now
; is -s.
;
scan_option: jcxz bad_usage
lodsb
dec cx
cmp al,' '
jbe cmdscan1
or al,20h
cmp al,'s'
jne bad_usage
push si ; make_stupid doesn't save these
push cx
call make_stupid ; Enable stupid boot sector
pop cx
pop si
jmp short scan_option
;
; Parsed the command line OK. Check that the drive parameters are acceptable
;
struc DPB
dpbDrive: resb 1
dpbUnit: resb 1
dpbSectorSize: resw 1
dpbClusterMask: resb 1
dpbClusterShift: resb 1
dpbFirstFAT: resw 1
dpbFATCount: resb 1
dpbRootEntries: resw 1
dpbFirstSector: resw 1
dpbMaxCluster: resw 1
dpbFATSize: resw 1
dpbDirSector: resw 1
dpbDriverAddr: resd 1
dpbMedia: resb 1
dpbFirstAccess: resb 1
dpbNextDPB: resd 1
dpbNextFree: resw 1
dpbFreeCnt: resw 1
endstruc
got_cmdline:
mov dl,[DriveNo]
inc dl ; 1-based
mov bx,DPB
mov ah,32h
int 21h ; Get Drive Parameter Block
and al,al
jnz filesystem_error
cmp word [bx+dpbSectorSize],512 ; Sector size = 512 required
jne sectorsize_error
cmp byte [bx+dpbClusterShift],5 ; Max size = 16K = 2^5 sectors
jna read_bootsect
hugeclust_error:
mov dx,msg_hugeclust_err
jmp die
filesystem_error:
mov dx,msg_filesystem_err
jmp die
sectorsize_error:
mov dx,msg_sectorsize_err
jmp die
;
; Good enough. Now read the old boot sector and copy the superblock.
;
section .data
align 4, db 0
DISKIO equ $
diStartSector: dd 0 ; Absolute sector 0
diSectors: dw 1 ; One sector
diBuffer: dw SectorBuffer ; Buffer offset
dw 0 ; Buffer segment
section .text
read_bootsect:
mov ax,cs ; Set DS <- CS
mov ds,ax
cmp word [DOSVersion],0400h ; DOS 4.00 has a new interface
jae .new
.old:
mov bx,SectorBuffer
mov cx,1 ; One sector
jmp short .common
.new:
mov bx,DISKIO
mov [bx+8],ax ; Buffer segment
mov cx,-1
.common:
xor dx,dx ; Absolute sector 0
mov al,[DriveNo]
int 25h ; DOS absolute disk read
pop ax ; Remove flags from stack
jc disk_read_error
mov si,SectorBuffer+11 ; Offset of superblock
mov di,BootSector+11
mov cx,51 ; Superblock = 51 bytes
rep movsb ; Copy the superblock
jmp short write_file
disk_read_error:
mov dx,msg_read_err
jmp die
;
; Writing LDLINUX.SYS
;
write_file:
; 0. Set the correct filename
mov al,[DriveNo]
add [ldlinux_sys_str],al
; 1. If the file exists, strip its attributes and delete
xor cx,cx ; Clear attributes
mov dx,ldlinux_sys_str
mov ax,4301h ; Set file attributes
int 21h
mov dx,ldlinux_sys_str
mov ah,41h ; Delete file
int 21h
section .data
ldlinux_sys_str: db 'A:\LDLINUX.SYS', 0
section .text
; 2. Create LDLINUX.SYS and write data to it
mov dx,ldlinux_sys_str
xor cx,cx ; Normal file
mov ah,3Ch ; Create file
int 21h
jc file_write_error
mov [FileHandle],ax
mov bx,ax
mov cx,ldlinux_size
mov dx,LDLinuxSYS
mov ah,40h ; Write data
int 21h
jc file_write_error
cmp ax,ldlinux_size
jne file_write_error
mov bx,[FileHandle]
mov ah,3Eh ; Close file
int 21h
section .bss
FileHandle: resw 1
section .text
; 3. Set the readonly flag on LDLINUX.SYS
mov dx,ldlinux_sys_str
mov cx,1 ; Read only
mov ax,4301h ; Set attributes
int 21h
;
; Writing boot sector
;
write_bootsect:
cmp word [DOSVersion],0400h ; DOS 4.00 has a new interface
jae .new
.old:
mov bx,BootSector
mov cx,1 ; One sector
jmp short .common
.new:
mov bx,DISKIO
mov word [bx+6],BootSector
mov cx,-1
.common:
xor dx,dx ; Absolute sector 0
mov al,[DriveNo]
int 26h ; DOS absolute disk write
pop ax ; Remove flags from stack
jc disk_write_error
all_done: mov ax,4C00h ; Exit good status
int 21h
;
; Error routine jump
;
disk_write_error:
file_write_error:
mov dx,msg_write_err
die:
push cs
pop ds
push dx
mov dx,msg_error
mov ah,09h
int 21h
pop dx
mov ah,09h ; Write string
int 21h
mov ax,4C01h ; Exit error status
int 21h
;
; This includes a small subroutine make_stupid to patch up the boot sector
; in case we give the -s (stupid) option
;
%include "stupid.inc"
section .data
msg_error: db 'ERROR: $'
msg_ancient_err: db 'DOS version 3.20 or later required', 0Dh, 0Ah, '$'
msg_filesystem_err: db 'Filesystem not found on disk', 0Dh, 0Ah, '$'
msg_sectorsize_err: db 'Sector sizes other than 512 bytes not supported', 0Dh, 0Ah, '$'
msg_hugeclust_err: db 'Clusters larger than 16K not supported', 0Dh, 0Ah, '$'
msg_read_err: db 'Boot sector read failed', 0Dh, 0Ah, '$'
msg_write_err: db 'Disk write failed', 0Dh, 0Ah, '$'
section .data
align 4, db 0
BootSector: incbin "bootsect.bin"
LDLinuxSYS: incbin "ldlinux.sys"
ldlinux_size: equ $-LDLinuxSYS
section .bss
alignb 4
SectorBuffer: resb 512
|