"Fossies" - the Fresh Open Source Software Archive

Member "syslinux-6.03/core/adv.inc" (6 Oct 2014, 9483 Bytes) of package /linux/misc/syslinux-6.03.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) fasm source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "adv.inc": 6.02_vs_6.03.

    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 ;;
   33 ADV_BOOTONCE    equ 1
   34 
   35 ;;
   36 ;; Other ADV data...
   37 ;;
   38 ADV_MAGIC1  equ 0x5a2d2fa5          ; Head signature
   39 ADV_MAGIC2  equ 0xa3041767          ; Total checksum
   40 ADV_MAGIC3  equ 0xdd28bf64          ; Tail signature
   41 
   42 ADV_LEN     equ 500             ; Data bytes
   43 
   44 adv_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
   55 adv0:
   56 .head       resd 1
   57 .csum       resd 1
   58 .data       resb ADV_LEN
   59 .tail       resd 1
   60 .end        equ $
   61 adv1:
   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
   74 adv_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         ;
   96 adv_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 
  163 adv_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 ;
  202 adv_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 ;
  277 adv_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
  305 adv_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 ;
  334 adv_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 ;
  348 adv_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
  510 ADVSec0     dq 0            ; Not specified
  511 ADVSec1     dq 0            ; Not specified
  512 ADVDrive    db -1           ; No ADV defined
  513 ADVCHSInfo  db -1           ; We have CHS info for this drive
  514 
  515         section .bss16
  516 ADVOp       resb 1
  517 
  518         section .text16