source: bootcd/isolinux/syslinux-6.03/core/adv.inc

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 9.3 KB
RevLine 
[e16e8f2]1;; -----------------------------------------------------------------------
2;;
3;;   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
4;;
5;;   This program is free software; you can redistribute it and/or modify
6;;   it under the terms of the GNU General Public License as published by
7;;   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
8;;   Boston MA 02110-1301, USA; either version 2 of the License, or
9;;   (at your option) any later version; incorporated herein by reference.
10;;
11;; -----------------------------------------------------------------------
12
13;;
14;; adv.inc
15;;
16;; The auxillary data vector and its routines
17;;
18;; The auxillary data vector is a 512-byte aligned block that on the
19;; disk-based derivatives can be part of the syslinux file itself.  It
20;; exists in two copies; when written, both copies are written (with a
21;; sync in between, if from the operating system.)  The first two
22;; dwords are magic number and inverse checksum, then follows the data
23;; area as a tagged array similar to BOOTP/DHCP, finally a tail
24;; signature.
25;;
26;; Note that unlike BOOTP/DHCP, zero terminates the chain, and FF
27;; has no special meaning.
28;;
29
30;;
31;; List of ADV tags...
32;;
33ADV_BOOTONCE    equ 1
34
35;;
36;; Other ADV data...
37;;
38ADV_MAGIC1      equ 0x5a2d2fa5                  ; Head signature
39ADV_MAGIC2      equ 0xa3041767                  ; Total checksum
40ADV_MAGIC3      equ 0xdd28bf64                  ; Tail signature
41
42ADV_LEN         equ 500                         ; Data bytes
43
44adv_retries     equ 6                           ; Disk retries
45
46                section .data
47                global __syslinux_adv_ptr, __syslinux_adv_size
48__syslinux_adv_ptr:
49                dd adv0.data
50__syslinux_adv_size:
51                dd ADV_LEN
52
53                section .adv
54                ; Introduce the ADVs to valid but blank
55adv0:
56.head           resd 1
57.csum           resd 1
58.data           resb ADV_LEN
59.tail           resd 1
60.end            equ $
61adv1:
62.head           resd 1
63.csum           resd 1
64.data           resb ADV_LEN
65.tail           resd 1
66.end            equ $
67                section .text16
68
69                ;
70                ; This is called after config file parsing, so we know
71                ; the intended location of the ADV
72                ;
73                global adv_init
74adv_init:
75                cmp byte [ADVDrive],-1
76                jne adv_read
77
78%if IS_SYSLINUX || IS_EXTLINUX
79                cmp word [ADVSectors],2         ; Not present?
80                jb adv_verify
81
82                mov eax,[Hidden]
83                mov edx,[Hidden+4]
84                add [ADVSec0],eax
85                adc [ADVSec0+4],edx
86                add [ADVSec1],eax
87                adc [ADVSec1+4],edx
88                mov al,[DriveNumber]
89                mov [ADVDrive],al
90                jmp adv_read
91%endif
92
93                ;
94                ; Initialize the ADV data structure in memory
95                ;
96adv_verify:
97                cmp byte [ADVDrive],-1          ; No ADV configured, still?
98                je .reset                       ; Then unconditionally reset
99
100                mov si,adv0
101                call .check_adv
102                jz .ok                          ; Primary ADV okay
103                mov si,adv1
104                call .check_adv
105                jz .adv1ok
106
107                ; Neither ADV is usable; initialize to blank
108.reset:
109                mov di,adv0
110                mov eax,ADV_MAGIC1
111                stosd
112                mov eax,ADV_MAGIC2
113                stosd
114                xor eax,eax
115                mov cx,ADV_LEN/4
116                rep stosd
117                mov eax,ADV_MAGIC3
118                stosd
119
120.ok:
121                ret
122
123                ; The primary ADV is bad, but the backup is OK
124.adv1ok:
125                mov di,adv0
126                mov cx,512/4
127                rep movsd
128                ret
129
130
131                ; SI points to the putative ADV; unchanged by routine
132                ; ZF=1 on return if good
133.check_adv:
134                push si
135                lodsd
136                cmp eax,ADV_MAGIC1
137                jne .done                       ; ZF=0, i.e. bad
138                xor edx,edx
139                mov cx,ADV_LEN/4+1              ; Remaining dwords
140.csum:
141                lodsd
142                add edx,eax
143                loop .csum
144                cmp edx,ADV_MAGIC2
145                jne .done
146                lodsd
147                cmp eax,ADV_MAGIC3
148.done:
149                pop si
150                ret
151
152;
153; adv_get: find an ADV string if present
154;
155; Input:        DL      = ADV ID
156; Output:       CX      = byte count (zero on not found)
157;               SI      = pointer to data
158;               DL      = unchanged
159;
160; Assumes CS == DS.
161;
162
163adv_get:
164                push ax
165                mov si,adv0.data
166                xor ax,ax                       ; Keep AH=0 at all times
167.loop:
168                lodsb                           ; Read ID
169                cmp al,dl
170                je .found
171                and al,al
172                jz .end
173                lodsb                           ; Read length
174                add si,ax
175                cmp si,adv0.tail
176                jb .loop
177                jmp .end
178
179.found:
180                lodsb
181                mov cx,ax
182                add ax,si                       ; Make sure it fits
183                cmp ax,adv0.tail
184                jbe .ok
185.end:
186                xor cx,cx
187.ok:
188                pop ax
189                ret
190
191;
192; adv_set: insert a string into the ADV in memory
193;
194; Input:        DL      = ADV ID
195;               FS:BX   = input buffer
196;               CX      = byte count (max = 255!)
197; Output:       CF=1 on error
198;               CX      clobbered
199;
200; Assumes CS == DS == ES.
201;
202adv_set:
203                push ax
204                push si
205                push di
206                and ch,ch
207                jnz .overflow
208
209                push cx
210                mov si,adv0.data
211                xor ax,ax
212.loop:
213                lodsb
214                cmp al,dl
215                je .found
216                and al,al
217                jz .endz
218                lodsb
219                add si,ax
220                cmp si,adv0.tail
221                jb .loop
222                jmp .end
223
224.found:         ; Found, need to delete old copy
225                lodsb
226                lea di,[si-2]
227                push di
228                add si,ax
229                mov cx,adv0.tail
230                sub cx,si
231                jb .nukeit
232                rep movsb                       ; Remove the old one
233                mov [di],ah                     ; Termination zero
234                pop si
235                jmp .loop
236.nukeit:
237                pop si
238                jmp .end
239.endz:
240                dec si
241.end:
242                ; Now SI points to where we want to put our data
243                pop cx
244                mov di,si
245                jcxz .empty
246                add si,cx
247                cmp si,adv0.tail-2
248                jae .overflow                   ; CF=0
249
250                mov si,bx
251                mov al,dl
252                stosb
253                mov al,cl
254                stosb
255                fs rep movsb
256
257.empty:
258                mov cx,adv0.tail
259                sub cx,di
260                xor ax,ax
261                rep stosb                       ; Zero-fill remainder
262
263                clc
264.done:
265                pop di
266                pop si
267                pop ax
268                ret
269.overflow:
270                stc
271                jmp .done
272
273;
274; adv_cleanup:  checksum adv0 and copy to adv1
275;               Assumes CS == DS == ES.
276;
277adv_cleanup:
278                pushad
279                mov si,adv0.data
280                mov cx,ADV_LEN/4
281                xor edx,edx
282.loop:
283                lodsd
284                add edx,eax
285                loop .loop
286                mov eax,ADV_MAGIC2
287                sub eax,edx
288                lea di,[si+4]                   ; adv1
289                mov si,adv0
290                mov [si+4],eax                  ; Store checksum
291                mov cx,(ADV_LEN+12)/4
292                rep movsd
293                popad
294                ret
295
296;
297; adv_write:    write the ADV to disk.
298;
299;               Location is in memory variables.
300;               Assumes CS == DS == ES.
301;
302;               Returns CF=1 if the ADV cannot be written.
303;
304                global adv_write
305adv_write:
306                push eax
307                mov eax,[ADVSec0]
308                or eax,[ADVSec0+4]
309                je .bad
310                mov eax,[ADVSec1]
311                or eax,[ADVSec1+4]
312                je .bad
313                cmp byte [ADVDrive],-1
314                je .bad
315
316                call adv_cleanup
317                mov ah,3                        ; Write
318                call adv_read_write
319
320                clc
321                pop eax
322                ret
323.bad:                                           ; No location for ADV set
324                stc
325                pop eax
326                ret
327
328;
329; adv_read:     read the ADV from disk
330;
331;               Location is in memory variables.
332;               Assumes CS == DS == ES.
333;
334adv_read:
335                push ax
336                mov ah,2                        ; Read
337                call adv_read_write
338                call adv_verify
339                pop ax
340                ret
341
342;
343; adv_read_write: disk I/O for the ADV
344;
345;               On input, AH=2 for read, AH=3 for write.
346;               Assumes CS == DS == ES.
347;
348adv_read_write:
349                mov [ADVOp],ah
350                pushad
351
352                ; Check for EDD
353                mov bx,55AAh
354                mov ah,41h                      ; EDD existence query
355                mov dl,[ADVDrive]
356                int 13h
357                mov si,.cbios
358                jc .noedd
359                cmp bx,0AA55h
360                jne .noedd
361                test cl,1
362                jz .noedd
363                mov si,.ebios
364.noedd:
365
366                mov eax,[ADVSec0]
367                mov edx,[ADVSec0+4]
368                mov bx,adv0
369                call .doone
370
371                mov eax,[ADVSec1]
372                mov edx,[ADVSec1+4]
373                mov bx,adv1
374                call .doone
375
376                popad
377                ret
378
379.doone:
380                push si
381                jmp si
382
383.ebios:
384                mov cx,adv_retries
385.eb_retry:
386                ; Form DAPA on stack
387                push edx
388                push eax
389                push es
390                push bx
391                push word 1                     ; Sector count
392                push word 16                    ; DAPA size
393                mov si,sp
394                pushad
395                mov dl,[ADVDrive]
396                mov ax,4000h
397                or ah,[ADVOp]
398                push ds
399                push ss
400                pop ds
401                int 13h
402                pop ds
403                popad
404                lea sp,[si+16]                  ; Remove DAPA
405                jc .eb_error
406                pop si
407                ret
408.eb_error:
409                loop .eb_retry
410                stc
411                pop si
412                ret
413
414.cbios:
415                push edx
416                push eax
417                push bp
418
419                and edx,edx                     ; > 2 TiB not possible
420                jnz .cb_overflow
421
422                mov dl,[ADVDrive]
423                and dl,dl
424                ; Floppies: can't trust INT 13h 08h, we better know
425                ; the geometry a priori, which means it better be our
426                ; boot device...
427                jns .noparm                     ; Floppy drive... urk
428
429                mov ah,08h                      ; Get disk parameters
430                int 13h
431                jc .noparm
432                and ah,ah
433                jnz .noparm
434                shr dx,8
435                inc dx
436                movzx edi,dx                    ; EDI = heads
437                and cx,3fh
438                movzx esi,cx                    ; ESI = sectors/track
439                jmp .parmok
440
441.noparm:
442                ; No CHS info... this better be our boot drive, then
443%if IS_SYSLINUX || IS_EXTLINUX
444                cmp dl,[DriveNumber]
445                jne .cb_overflow                ; Fatal error!
446                movzx esi,word [bsSecPerTrack]
447                movzx edi,word [bsHeads]
448%else
449                ; Not a disk-based derivative... there is no hope
450                jmp .cb_overflow
451%endif
452
453.parmok:
454                ;
455                ; Dividing by sectors to get (track,sector): we may have
456                ; up to 2^18 tracks, so we need to use 32-bit arithmetric.
457                ;
458                xor edx,edx
459                div esi
460                xor cx,cx
461                xchg cx,dx              ; CX <- sector index (0-based)
462                                        ; EDX <- 0
463                ; eax = track #
464                div edi                 ; Convert track to head/cyl
465
466                ; Watch out for overflow, we might be writing!
467                cmp eax,1023
468                ja .cb_overflow
469
470                ;
471                ; Now we have AX = cyl, DX = head, CX = sector (0-based),
472                ; BP = sectors to transfer, SI = bsSecPerTrack,
473                ; ES:BX = data target
474                ;
475
476                shl ah,6                ; Because IBM was STOOPID
477                                        ; and thought 8 bits were enough
478                                        ; then thought 10 bits were enough...
479                inc cx                  ; Sector numbers are 1-based, sigh
480                or cl,ah
481                mov ch,al
482                mov dh,dl
483                mov dl,[ADVDrive]
484                mov al,01h              ; Transfer one sector
485                mov ah,[ADVOp]          ; Operation
486
487                mov bp,adv_retries
488.cb_retry:
489                pushad
490                int 13h
491                popad
492                jc .cb_error
493
494.cb_done:
495                pop bp
496                pop eax
497                pop edx
498                pop si
499                ret
500
501.cb_error:
502                dec bp
503                jnz .cb_retry
504.cb_overflow:
505                stc
506                jmp .cb_done
507
508                section .data16
509                alignz 8
510ADVSec0         dq 0                    ; Not specified
511ADVSec1         dq 0                    ; Not specified
512ADVDrive        db -1                   ; No ADV defined
513ADVCHSInfo      db -1                   ; We have CHS info for this drive
514
515                section .bss16
516ADVOp           resb 1
517
518                section .text16
Note: See TracBrowser for help on using the repository browser.