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_EXTLINUX
71 cmp word [ADVSectors],2 ; Not present?
86 ; Initialize the ADV data structure in memory
89 cmp byte [ADVDrive],-1 ; No ADV configured, still?
90 je .reset ; Then unconditionally reset
94 jz .ok ; Primary ADV okay
99 ; Neither ADV is usable; initialize to blank
115 ; The primary ADV is bad, but the backup is OK
123 ; SI points to the putative ADV; unchanged by routine
124 ; ZF=1 on return if good
129 jne .done ; ZF=0, i.e. bad
131 mov cx,ADV_LEN/4+1 ; Remaining dwords
145 ; adv_get: find an ADV string if present
148 ; Output: CX = byte count (zero on not found)
149 ; SI = pointer to data
158 xor ax,ax ; Keep AH=0 at all times
174 add ax,si ; Make sure it fits
184 ; adv_set: insert a string into the ADV in memory
187 ; FS:BX = input buffer
188 ; CX = byte count (max = 255!)
189 ; Output: CF=1 on error
192 ; Assumes CS == DS == ES.
216 .found: ; Found, need to delete old copy
224 rep movsb ; Remove the old one
225 mov [di],ah ; Termination zero
234 ; Now SI points to where we want to put our data
253 rep stosb ; Zero-fill remainder
266 ; adv_cleanup: checksum adv0 and copy to adv1
267 ; Assumes CS == DS == ES.
282 mov [si+4],eax ; Store checksum
283 mov cx,(ADV_LEN+12)/4
289 ; adv_write: write the ADV to disk.
291 ; Location is in memory variables.
292 ; Assumes CS == DS == ES.
294 ; Returns CF=1 if the ADV cannot be written.
304 cmp byte [ADVDrive],-1
314 .bad: ; No location for ADV set
320 ; adv_read: read the ADV from disk
322 ; Location is in memory variables.
323 ; Assumes CS == DS == ES.
334 ; adv_read_write: disk I/O for the ADV
336 ; On input, AH=2 for read, AH=3 for write.
337 ; Assumes CS == DS == ES.
345 mov ah,41h ; EDD existence query
382 push word 1 ; Sector count
383 push word 16 ; DAPA size
395 lea sp,[si+16] ; Remove DAPA
410 and edx,edx ; > 2 TiB not possible
415 ; Floppies: can't trust INT 13h 08h, we better know
416 ; the geometry a priori, which means it better be our
418 jns .noparm ; Floppy drive... urk
420 mov ah,08h ; Get disk parameters
427 movzx edi,dx ; EDI = heads
429 movzx esi,cx ; ESI = sectors/track
433 ; No CHS info... this better be our boot drive, then
434 %if IS_SYSLINUX || IS_EXTLINUX
436 jne .cb_overflow ; Fatal error!
437 movzx esi,word [bsSecPerTrack]
438 movzx edi,word [bsHeads]
440 ; Not a disk-based derivative... there is no hope
446 ; Dividing by sectors to get (track,sector): we may have
447 ; up to 2^18 tracks, so we need to use 32-bit arithmetric.
452 xchg cx,dx ; CX <- sector index (0-based)
455 div edi ; Convert track to head/cyl
457 ; Watch out for overflow, we might be writing!
462 ; Now we have AX = cyl, DX = head, CX = sector (0-based),
463 ; BP = sectors to transfer, SI = bsSecPerTrack,
464 ; ES:BX = data target
467 shl ah,6 ; Because IBM was STOOPID
468 ; and thought 8 bits were enough
469 ; then thought 10 bits were enough...
470 inc cx ; Sector numbers are 1-based, sigh
475 mov al,01h ; Transfer one sector
476 mov ah,[ADVOp] ; Operation
501 ADVSec0 dq 0 ; Not specified
502 ADVSec1 dq 0 ; Not specified
503 ADVDrive db -1 ; No ADV defined
504 ADVCHSInfo db -1 ; We have CHS info for this drive