1 ;; -----------------------------------------------------------------------
3 ;; Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
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.
11 ;; -----------------------------------------------------------------------
16 ;; The auxillary data vector and its routines
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
26 ;; Note that unlike BOOTP/DHCP, zero terminates the chain, and FF
27 ;; has no special meaning.
31 ;; List of ADV tags...
38 ADV_MAGIC1 equ 0x5a2d2fa5 ; Head signature
39 ADV_MAGIC2 equ 0xa3041767 ; Total checksum
40 ADV_MAGIC3 equ 0xdd28bf64 ; Tail signature
42 ADV_LEN equ 500 ; Data bytes
44 adv_retries equ 6 ; Disk retries
47 ; Introduce the ADVs to valid but blank
63 ; This is called after config file parsing, so we know
64 ; the intended location of the ADV
67 cmp byte [ADVDrive],-1
70 ;%if IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
71 %if IS_EXTLINUX ; Not yet implemented for the other derivatives
73 ; Update pointers to default ADVs...
78 mov eax,[bx+SectorPtrs-8]
79 mov edx,[bx+SectorPtrs-4]
87 ; ** fall through to adv_verify **
90 ; Initialize the ADV data structure in memory
93 cmp byte [ADVDrive],-1 ; No ADV configured, still?
94 je .reset ; Then unconditionally reset
98 jz .ok ; Primary ADV okay
103 ; Neither ADV is usable; initialize to blank
119 ; The primary ADV is bad, but the backup is OK
127 ; SI points to the putative ADV; unchanged by routine
128 ; ZF=1 on return if good
133 jne .done ; ZF=0, i.e. bad
135 mov cx,ADV_LEN/4+1 ; Remaining dwords
149 ; adv_get: find an ADV string if present
152 ; Output: CX = byte count (zero on not found)
153 ; SI = pointer to data
162 xor ax,ax ; Keep AH=0 at all times
178 add ax,si ; Make sure it fits
188 ; adv_set: insert a string into the ADV in memory
191 ; FS:BX = input buffer
192 ; CX = byte count (max = 255!)
193 ; Output: CF=1 on error
196 ; Assumes CS == DS == ES.
220 .found: ; Found, need to delete old copy
228 rep movsb ; Remove the old one
229 mov [di],ah ; Termination zero
238 ; Now SI points to where we want to put our data
257 rep stosb ; Zero-fill remainder
270 ; adv_cleanup: checksum adv0 and copy to adv1
271 ; Assumes CS == DS == ES.
286 mov [si+4],eax ; Store checksum
287 mov cx,(ADV_LEN+12)/4
293 ; adv_write: write the ADV to disk.
295 ; Location is in memory variables.
296 ; Assumes CS == DS == ES.
298 ; Returns CF=1 if the ADV cannot be written.
301 cmp dword [ADVSec0],0
303 cmp dword [ADVSec1],0
305 cmp byte [ADVDrive],-1
316 .bad: ; No location for ADV set
321 ; adv_read: read the ADV from disk
323 ; Location is in memory variables.
324 ; Assumes CS == DS == ES.
335 ; adv_read_write: disk I/O for the ADV
337 ; On input, AH=2 for read, AH=3 for write.
338 ; Assumes CS == DS == ES.
346 mov ah,41h ; EDD existence query
370 xor edx,edx ; Zero-extend LBA
382 push word 1 ; Sector count
383 push word 16 ; DAPA size
395 lea sp,[si+16] ; Remove DAPA
412 ; Floppies: can't trust INT 13h 08h, we better know
413 ; the geometry a priori, which means it better be our
415 jns .noparm ; Floppy drive... urk
417 mov ah,08h ; Get disk parameters
424 movzx edi,dx ; EDI = heads
426 movzx esi,cx ; ESI = sectors/track
430 ; No CHS info... this better be our boot drive, then
431 %if IS_SYSLINUX || IS_EXTLINUX
433 jne .cb_overflow ; Fatal error!
434 movzx esi,word [bsSecPerTrack]
435 movzx edi,word [bsHeads]
437 ; Not a disk-based derivative... there is no hope
443 ; Dividing by sectors to get (track,sector): we may have
444 ; up to 2^18 tracks, so we need to use 32-bit arithmetric.
448 xchg cx,dx ; CX <- sector index (0-based)
451 div edi ; Convert track to head/cyl
453 ; Watch out for overflow, we might be writing!
458 ; Now we have AX = cyl, DX = head, CX = sector (0-based),
459 ; BP = sectors to transfer, SI = bsSecPerTrack,
460 ; ES:BX = data target
463 shl ah,6 ; Because IBM was STOOPID
464 ; and thought 8 bits were enough
465 ; then thought 10 bits were enough...
466 inc cx ; Sector numbers are 1-based, sigh
471 mov al,01h ; Transfer one sector
472 mov ah,[ADVOp] ; Operation
497 ADVSec0 dd 0 ; Not specified
498 ADVSec1 dd 0 ; Not specified
499 ADVDrive db -1 ; No ADV defined
500 ADVCHSInfo db -1 ; We have CHS info for this drive