Merge commit 'origin/master' into adv syslinux-3.60-pre6
authorH. Peter Anvin <hpa@zytor.com>
Tue, 18 Dec 2007 23:58:13 +0000 (15:58 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 18 Dec 2007 23:58:13 +0000 (15:58 -0800)
34 files changed:
Makefile
NEWS
adv.inc [new file with mode: 0644]
bin2c.pl
com32/include/syslinux/adv.h [new file with mode: 0644]
com32/include/syslinux/advconst.h [new file with mode: 0644]
com32/lib/Makefile
com32/lib/syslinux/adv.c [new file with mode: 0644]
com32/lib/syslinux/advwrite.c [new file with mode: 0644]
com32/lib/syslinux/getadv.c [new file with mode: 0644]
com32/lib/syslinux/setadv.c [new file with mode: 0644]
com32/samples/Makefile
com32/samples/advdump.c [new file with mode: 0644]
comboot.inc
doc/comboot.doc
doc/extlinux.doc
dos/Makefile
extlinux.asm
extlinux/Makefile
extlinux/extlinux.c
isolinux.asm
layout.inc
ldlinux.asm
libinstaller/advconst.h [new symlink]
libinstaller/setadv.c [new file with mode: 0644]
libinstaller/syslinux.h [moved from syslinux.h with 81% similarity]
libinstaller/syslxint.h [new file with mode: 0644]
libinstaller/syslxmod.c [moved from syslxmod.c with 100% similarity]
mtools/Makefile
pxelinux.asm
ui.inc
unix/Makefile
version
win32/Makefile

index 4ae6543..41ca1f8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -182,7 +182,7 @@ extlinux_bss_bin.c: extlinux.bss bin2c.pl
        $(PERL) bin2c.pl extlinux_bootsect < $< > $@
 
 extlinux_sys_bin.c: extlinux.sys bin2c.pl
-       $(PERL) bin2c.pl extlinux_image < $< > $@
+       $(PERL) bin2c.pl extlinux_image 512 < $< > $@
 
 libsyslinux.a: bootsect_bin.o ldlinux_bin.o mbr_bin.o syslxmod.o
        rm -f $@
diff --git a/NEWS b/NEWS
index 3ba83ce..6082620 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,17 @@ Starting with 1.47, changes marked with SYSLINUX/PXELINUX/ISOLINUX
 apply to that specific program only; other changes apply to all of
 them.
 
+Changes in 3.60:
+       * Support for "auxilliary data vector", a small amount of
+         writable storage.  Currently only supported for EXTLINUX,
+         but the infrastructure is there for the other derivatives,
+         assuming a suitable storage location can be found.
+       * EXTLINUX: boot-once support (--once, --clear-once, and
+         --reset-adv).
+       * A command is now required to the EXTLINUX installer, i.e. at
+         least one of --install, --update, --once, --clear-once, or
+         --reset-adv.
+
 Changes in 3.55:
        * PXELINUX: as per RFC 5071, PXELINUX no longer requires the
          use of the magic cookie option (208) for unencapsulated
diff --git a/adv.inc b/adv.inc
new file mode 100644 (file)
index 0000000..7eca4b5
--- /dev/null
+++ b/adv.inc
@@ -0,0 +1,485 @@
+;; -----------------------------------------------------------------------
+;;
+;;   Copyright 2007 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., 53 Temple Place Ste 330,
+;;   Boston MA 02111-1307, USA; either version 2 of the License, or
+;;   (at your option) any later version; incorporated herein by reference.
+;;
+;; -----------------------------------------------------------------------
+
+;;
+;; adv.inc
+;;
+;; The auxillary data vector and its routines
+;;
+;; The auxillary data vector is a 512-byte aligned block that on the
+;; disk-based derivatives can be part of the syslinux file itself.  It
+;; exists in two copies; when written, both copies are written (with a
+;; sync in between, if from the operating system.)  The first two
+;; dwords are magic number and inverse checksum, then follows the data
+;; area as a tagged array similar to BOOTP/DHCP, finally a tail
+;; signature.
+;;
+;; Note that unlike BOOTP/DHCP, zero terminates the chain, and FF
+;; has no special meaning.
+;;
+
+;;
+;; List of ADV tags...
+;;
+ADV_BOOTONCE   equ 1
+
+;;
+;; Other ADV data...
+;;
+ADV_MAGIC1     equ 0x5a2d2fa5                  ; Head signature
+ADV_MAGIC2     equ 0xa3041767                  ; Total checksum
+ADV_MAGIC3     equ 0xdd28bf64                  ; Tail signature
+
+ADV_LEN                equ 500                         ; Data bytes
+
+adv_retries    equ 6                           ; Disk retries
+
+               section .adv
+               ; Introduce the ADVs to valid but blank
+adv0:
+.head          resd 1
+.csum          resd 1
+.data          resb ADV_LEN
+.tail          resd 1
+.end
+adv1:
+.head          resd 1
+.csum          resd 1
+.data          resb ADV_LEN
+.tail          resd 1
+.end
+               section .text
+
+               ;
+               ; This is called after config file parsing, so we know
+               ; the intended location of the ADV
+               ;
+adv_init:
+               cmp byte [ADVDrive],-1
+               jne adv_read
+
+;%if IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
+%if IS_EXTLINUX                ; Not yet implemented for the other derivatives
+               ;
+               ; Update pointers to default ADVs...
+               ;
+               mov bx,[LDLSectors]
+               shl bx,2
+               mov ecx,[bsHidden]
+               mov eax,[bx+SectorPtrs-8]
+               mov edx,[bx+SectorPtrs-4]
+               add eax,ecx
+               add edx,ecx
+               mov [ADVSec0],eax
+               mov [ADVSec1],edx
+               mov al,[DriveNumber]
+               mov [ADVDrive],al
+%endif
+               ; ** fall through to adv_verify **
+
+               ;
+               ; Initialize the ADV data structure in memory
+               ;
+adv_verify:
+               mov si,adv0
+               call .check_adv
+               jz .ok                          ; Primary ADV okay
+               mov si,adv1
+               call .check_adv
+               jz .adv1ok
+
+               ; Neither ADV is usable; initialize to blank
+               mov si,adv0
+               mov eax,ADV_MAGIC1
+               stosd
+               mov eax,ADV_MAGIC2
+               stosd
+               xor eax,eax
+               mov cx,ADV_LEN/4
+               rep stosd
+               mov eax,ADV_MAGIC3
+               stosd
+
+.ok:
+               ret
+
+               ; The primary ADV is bad, but the backup is OK
+.adv1ok:
+               mov di,adv0
+               mov cx,512/4
+               rep movsd
+               ret
+
+
+               ; SI points to the putative ADV; unchanged by routine
+               ; ZF=1 on return if good
+.check_adv:
+               push si
+               lodsd
+               cmp eax,ADV_MAGIC1
+               jne .done                       ; ZF=0, i.e. bad
+               xor edx,edx
+               mov cx,ADV_LEN/4+1              ; Remaining dwords
+.csum:
+               lodsd
+               add edx,eax
+               loop .csum
+               cmp edx,ADV_MAGIC2
+               jne .done
+               lodsd
+               cmp eax,ADV_MAGIC3
+.done:
+               pop si
+               ret
+
+;
+; adv_get: find an ADV string if present
+;
+; Input:       DL      = ADV ID
+; Output:      CX      = byte count (zero on not found)
+;              SI      = pointer to data
+;              DL      = unchanged
+;
+; Assumes CS == DS.
+;
+
+adv_get:
+               push ax
+               mov si,adv0.data
+               xor ax,ax                       ; Keep AH=0 at all times
+.loop:
+               lodsb                           ; Read ID
+               cmp al,dl
+               je .found
+               and al,al
+               jz .end
+               lodsb                           ; Read length
+               add si,ax
+               cmp si,adv0.tail
+               jb .loop
+               jmp .end
+
+.found:
+               lodsb
+               mov cx,ax
+               add ax,si                       ; Make sure it fits
+               cmp ax,adv0.tail
+               jbe .ok
+.end:
+               xor cx,cx
+.ok:
+               pop ax
+               ret
+
+;
+; adv_set: insert a string into the ADV in memory
+;
+; Input:       DL      = ADV ID
+;              FS:BX   = input buffer
+;              CX      = byte count (max = 255!)
+; Output:      CF=1 on error
+;              CX      clobbered
+;
+; Assumes CS == DS == ES.
+;
+adv_set:
+               push ax
+               push si
+               push di
+               and ch,ch
+               jnz .overflow
+
+               push cx
+               mov si,adv0.data
+               xor ax,ax
+.loop:
+               lodsb
+               cmp al,dl
+               je .found
+               and al,al
+               jz .endz
+               lodsb
+               add si,ax
+               cmp si,adv0.tail
+               jb .loop
+               jmp .end
+
+.found:                ; Found, need to delete old copy
+               lodsb
+               lea di,[si-2]
+               push di
+               add si,ax
+               mov cx,adv0.tail
+               sub cx,si
+               jb .nukeit
+               rep movsb                       ; Remove the old one
+               mov [di],ah                     ; Termination zero
+               pop si
+               jmp .loop
+.nukeit:
+               pop si
+               jmp .end
+.endz:
+               dec si
+.end:
+               ; Now SI points to where we want to put our data
+               pop cx
+               mov di,si
+               jcxz .empty
+               add si,cx
+               cmp si,adv0.tail-2
+               jae .overflow                   ; CF=0
+
+               mov si,bx
+               mov al,dl
+               stosb
+               mov al,cl
+               stosb
+               fs rep movsb
+
+.empty:
+               mov cx,adv0.tail
+               sub cx,di
+               xor ax,ax
+               rep stosb                       ; Zero-fill remainder
+
+               clc
+.done:
+               pop di
+               pop si
+               pop ax
+               ret
+.overflow:
+               stc
+               jmp .done
+
+;
+; adv_cleanup: checksum adv0 and copy to adv1
+;              Assumes CS == DS == ES.
+;
+adv_cleanup:
+               pushad
+               mov si,adv0.data
+               mov cx,ADV_LEN/4
+               xor edx,edx
+.loop:
+               lodsd
+               add edx,eax
+               loop .loop
+               mov eax,ADV_MAGIC2
+               sub eax,edx
+               lea di,[si+4]                   ; adv1
+               mov si,adv0
+               mov [si+4],eax                  ; Store checksum
+               mov cx,(ADV_LEN+12)/4
+               rep movsd
+               popad
+               ret
+
+;
+; adv_write:   write the ADV to disk.
+;
+;              Location is in memory variables.
+;              Assumes CS == DS == ES.
+;
+;              Returns CF=1 if the ADV cannot be written.
+;
+adv_write:
+               cmp dword [ADVSec0],0
+               je .bad
+               cmp dword [ADVSec1],0
+               je .bad
+               cmp byte [ADVDrive],-1
+               je .bad
+
+               push ax
+               call adv_cleanup
+               mov ah,3                        ; Write
+               call adv_read_write
+               pop ax
+
+               clc
+               ret
+.bad:                                          ; No location for ADV set
+               stc
+               ret
+
+;
+; adv_read:    read the ADV from disk
+;
+;              Location is in memory variables.
+;              Assumes CS == DS == ES.
+;
+adv_read:
+               push ax
+               mov ah,2                        ; Read
+               call adv_read_write
+               call adv_verify
+               pop ax
+               ret
+
+;
+; adv_read_write: disk I/O for the ADV
+;
+;              On input, AH=2 for read, AH=3 for write.
+;              Assumes CS == DS == ES.
+;
+adv_read_write:
+               mov [ADVOp],ah
+               pushad
+
+               mov dl,[ADVDrive]
+               and dl,dl
+               ; Floppies: can't trust INT 13h 08h, we better know
+               ; the geometry a priori, which means it better be our
+               ; boot device.  Handle that later.
+               ; jns .floppy                   ; Floppy drive... urk
+
+               mov ah,08h                      ; Get disk parameters
+               int 13h
+               jc .noparm
+               and ah,ah
+               jnz .noparm
+               shr dx,8
+               inc dx
+               mov [ADVHeads],dx
+               and cx,3fh
+               mov [ADVSecPerTrack],cx
+
+.noparm:
+               ; Check for EDD
+               mov bx,55AAh
+               mov ah,41h                      ; EDD existence query
+               mov dl,[ADVDrive]
+               int 13h
+               mov si,.cbios
+               jc .noedd
+               mov si,.ebios
+.noedd:
+
+               mov eax,[ADVSec0]
+               mov bx,adv0
+               call .doone
+
+               mov eax,[ADVSec1]
+               mov bx,adv1
+               call .doone
+
+               popad
+               ret
+
+.doone:
+               xor edx,edx                     ; Zero-extend LBA
+               push si
+               jmp si
+
+.ebios:
+               mov cx,adv_retries
+.eb_retry:
+               ; Form DAPA on stack
+               push edx
+               push eax
+               push es
+               push bx
+               push word 1                     ; Sector count
+               push word 16                    ; DAPA size
+               mov si,sp
+               pushad
+               mov dl,[ADVDrive]
+               mov ax,4080h
+               or ah,[ADVOp]
+               push ds
+               push ss
+               pop ds
+               int 13h
+               pop ds
+               popad
+               lea sp,[si+16]                  ; Remove DAPA
+               jc .eb_error
+               pop si
+               ret
+.eb_error:
+               loop .eb_retry
+               stc
+               pop si
+               ret
+
+.cbios:
+               push edx
+               push eax
+               push bp
+
+               movzx esi,word [ADVSecPerTrack]
+               movzx edi,word [ADVHeads]
+                ;
+                ; Dividing by sectors to get (track,sector): we may have
+                ; up to 2^18 tracks, so we need to use 32-bit arithmetric.
+                ;
+                div esi
+                xor cx,cx
+                xchg cx,dx              ; CX <- sector index (0-based)
+                                        ; EDX <- 0
+                ; eax = track #
+                div edi                 ; Convert track to head/cyl
+
+               ; Watch out for overflow, we might be writing!
+               cmp eax,1023
+                ja .cb_overflow
+
+                ;
+                ; Now we have AX = cyl, DX = head, CX = sector (0-based),
+                ; BP = sectors to transfer, SI = bsSecPerTrack,
+                ; ES:BX = data target
+                ;
+
+                shl ah,6                ; Because IBM was STOOPID
+                                        ; and thought 8 bits were enough
+                                        ; then thought 10 bits were enough...
+                inc cx                  ; Sector numbers are 1-based, sigh
+                or cl,ah
+                mov ch,al
+                mov dh,dl
+                mov dl,[ADVDrive]
+                xchg ax,bp              ; Sector to transfer count
+                mov ah,[ADVOp]         ; Operation
+
+               mov bp,adv_retries
+.cb_retry:
+                pushad
+                int 13h
+                popad
+                jc .cb_error
+
+.cb_done:
+                pop bp
+                pop eax
+                pop edx
+                ret
+
+.cb_error:
+                dec bp
+                jnz .cb_retry
+.cb_overflow:
+               stc
+               jmp .cb_done
+
+               section .data
+               align 4, db 0
+ADVSec0                db 0                    ; Undefined
+ADVSec1                db 0                    ; Undefined
+ADVDrive       db -1                   ; No ADV defined
+
+               section .bss
+               alignb 4
+ADVSecPerTrack resw 1
+ADVHeads       resw 1
+ADVOp          resb 1
index 5ef1c03..2bd95d5 100644 (file)
--- a/bin2c.pl
+++ b/bin2c.pl
 eval { use bytes; };
 eval { binmode STDIN; };
 
-if ( $#ARGV != 0 ) {
-    print STDERR "Usage: $0 table_name < input_file > output_file\n";
+($table_name, $pad) = @ARGV;
+
+if ( !defined($table_name) ) {
+    print STDERR "Usage: $0 table_name [pad] < input_file > output_file\n";
     exit 1;
 }
 
-($table_name) = @ARGV;
+$pad = 1 if ($pad < 1);
 
 printf "unsigned char %s[] = {\n", $table_name;
 
@@ -49,6 +51,24 @@ while ( ($n = read(STDIN, $data, 4096)) > 0 ) {
     }
 }
 
+$align = $total_len % $pad;
+if ($align != 0) {
+    $n = $pad - $align;
+    $total_len += $n;
+    for ( $i = 0 ; $i < $n ; $i++ ) {
+       if ( $pos >= $linelen ) {
+           print ",\n\t";
+           $pos = 0;
+       } elsif ( $pos > 0 ) {
+           print ", ";
+       } else {        
+           print "\t";
+       }
+       print '0x00';
+       $pos++;
+    }
+}
+
 printf "\n};\n\nunsigned int %s_len = %u;\n", $table_name, $total_len;
 
 @st = stat STDIN;
diff --git a/com32/include/syslinux/adv.h b/com32/include/syslinux/adv.h
new file mode 100644 (file)
index 0000000..a31712b
--- /dev/null
@@ -0,0 +1,57 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * syslinux/adv.h
+ */
+
+#ifndef _SYSLINUX_ADV_H
+#define _SYSLINUX_ADV_H
+
+#include <klibc/extern.h>
+#include <stddef.h>
+#include <syslinux/advconst.h>
+
+__extern void *__syslinux_adv_ptr;
+__extern size_t __syslinux_adv_size;
+
+static inline void *syslinux_adv_ptr(void)
+{
+  return __syslinux_adv_ptr;
+}
+
+static inline size_t syslinux_adv_size(void)
+{
+  return __syslinux_adv_size;
+}
+
+__extern int syslinux_adv_write(void);
+
+__extern int syslinux_setadv(int, size_t, const void *);
+__extern const void *syslinux_getadv(int, size_t *);
+
+#endif /* _SYSLINUX_ADV_H */
diff --git a/com32/include/syslinux/advconst.h b/com32/include/syslinux/advconst.h
new file mode 100644 (file)
index 0000000..f9d55aa
--- /dev/null
@@ -0,0 +1,43 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *   
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *   
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * syslinux/advconst.h
+ *
+ * ADV defined constants
+ *
+ * Defined in a separate file so it can be used by non-COM32 code.
+ * Some of these constants are also defined in adv.inc, they better match...
+ */
+
+#ifndef _SYSLINUX_ADVCONST_H
+#define _SYSLINUX_ADVCONST_H
+
+#define ADV_END                0
+#define ADV_BOOTONCE   1
+
+#endif /* _SYSLINUX_ADVCONST_H */
index 1cde067..6540f9f 100644 (file)
@@ -81,7 +81,10 @@ LIBOBJS = \
        syslinux/initramfs_file.o syslinux/initramfs_loadfile.o         \
        syslinux/initramfs_archive.o                                    \
        \
-       syslinux/pxe_get_cached.o
+       syslinux/pxe_get_cached.o                                       \
+       \
+       syslinux/adv.o syslinux/advwrite.o syslinux/getadv.o            \
+       syslinux/setadv.o
 
 BINDIR   = /usr/bin
 LIBDIR   = /usr/lib
diff --git a/com32/lib/syslinux/adv.c b/com32/lib/syslinux/adv.c
new file mode 100644 (file)
index 0000000..a4e74ab
--- /dev/null
@@ -0,0 +1,49 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * syslinux/adv.c
+ *
+ * Access the syslinux auxilliary data vector
+ */
+
+#include <syslinux/adv.h>
+#include <klibc/compiler.h>
+#include <com32.h>
+
+void *__syslinux_adv_ptr;
+size_t __syslinux_adv_size;
+
+void __constructor __syslinux_get_adv(void)
+{
+  static com32sys_t reg;
+
+  reg.eax.w[0] = 0x001c;
+  __intcall(0x22, &reg, &reg);
+  __syslinux_adv_ptr = MK_PTR(reg.es, reg.ebx.w[0]);
+  __syslinux_adv_size = reg.ecx.w[0];
+}
diff --git a/com32/lib/syslinux/advwrite.c b/com32/lib/syslinux/advwrite.c
new file mode 100644 (file)
index 0000000..1fe26b4
--- /dev/null
@@ -0,0 +1,45 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * syslinux/advwrite.c
+ *
+ * Write back the ADV
+ */
+
+#include <syslinux/adv.h>
+#include <klibc/compiler.h>
+#include <com32.h>
+
+int syslinux_adv_write(void)
+{
+  static com32sys_t reg;
+
+  reg.eax.w[0] = 0x001d;
+  __intcall(0x22, &reg, &reg);
+  return (reg.eflags.l & EFLAGS_CF) ? -1 : 0;
+}
diff --git a/com32/lib/syslinux/getadv.c b/com32/lib/syslinux/getadv.c
new file mode 100644 (file)
index 0000000..416f5f9
--- /dev/null
@@ -0,0 +1,68 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *   
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *   
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * syslinux/getadv.c
+ *
+ * Get a data item from the auxilliary data vector.  Returns a pointer
+ * and sets *size on success; NULL on failure.
+ */
+
+#include <syslinux/adv.h>
+#include <klibc/compiler.h>
+#include <inttypes.h>
+
+const void *syslinux_getadv(int tag, size_t *size)
+{
+  const uint8_t *p;
+  size_t left, len;
+
+  p = syslinux_adv_ptr();
+  left = syslinux_adv_size();
+
+  while (left >= 2) {
+    uint8_t ptag = *p++;
+    size_t  plen = *p++;
+    left -= 2;
+
+    if (ptag == ADV_END)
+      return NULL;             /* Not found */
+
+    if (left < plen)
+      return NULL;             /* Item overrun */
+
+    if (ptag == tag) {
+      *size = plen;
+      return p;
+    }
+
+    p    += plen;
+    left -= plen;
+  }
+
+  return NULL;
+}
diff --git a/com32/lib/syslinux/setadv.c b/com32/lib/syslinux/setadv.c
new file mode 100644 (file)
index 0000000..f6488b3
--- /dev/null
@@ -0,0 +1,112 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * syslinux/setadv.c
+ *
+ * (Over)write a data item in the auxilliary data vector.  To
+ * delete an item, set its length to zero.
+ *
+ * Return 0 on success, -1 on error, and set errno.
+ *
+ * NOTE: Data is not written to disk unless
+ * syslinux_adv_write() is called.
+ */
+
+#include <syslinux/adv.h>
+#include <klibc/compiler.h>
+#include <inttypes.h>
+#include <string.h>
+#include <errno.h>
+#include <alloca.h>
+
+int syslinux_setadv(int tag, size_t size, const void *data)
+{
+  uint8_t *p, *advtmp;
+  size_t left;
+
+  if ((unsigned)tag-1 > 254) {
+    errno = EINVAL;
+    return -1;                 /* Impossible tag value */
+  }
+
+  if (size > 255) {
+    errno = ENOSPC;            /* Max 255 bytes for a data item */
+    return -1;
+  }
+
+  left = syslinux_adv_size();
+  p = advtmp = alloca(left);
+  memcpy(p, syslinux_adv_ptr(), left); /* Make working copy */
+
+  while (left >= 2) {
+    uint8_t ptag = p[0];
+    size_t  plen = p[1]+2;
+
+    if (ptag == ADV_END)
+      break;
+
+    if (ptag == tag) {
+      /* Found our tag.  Delete it. */
+
+      if (plen >= left) {
+       /* Entire remainder is our tag */
+       break;
+      }
+      memmove(p, p+plen, left-plen);
+    } else {
+      /* Not our tag */
+      if (plen > left)
+       break;                  /* Corrupt tag (overrun) - overwrite it */
+
+      left -= plen;
+      p += plen;
+    }
+  }
+
+  /* Now (p, left) reflects the position to write in and how much space
+     we have for our data. */
+
+  if (size) {
+    if (left < size+2) {
+      errno = ENOSPC;          /* Not enough space for data */
+      return -1;
+    }
+
+    *p++ = tag;
+    *p++ = size;
+    memcpy(p, data, size);
+    left -= size+2;
+  }
+
+  memset(p, 0, left);
+
+  /* If we got here, everything went OK, commit the write to low memory */
+  memcpy(syslinux_adv_ptr(), advtmp, syslinux_adv_size());
+
+  return 0;
+}
index e14e08f..197e911 100644 (file)
@@ -45,6 +45,7 @@ all:  hello.c32 cat.c32 resolv.c32 vesainfo.c32 serialinfo.c32 \
        localboot.c32 \
        fancyhello.c32 fancyhello.lnx \
        keytest.c32 keytest.lnx \
+       advdump.c32
 
 .PRECIOUS: %.o
 %.o: %.S
diff --git a/com32/samples/advdump.c b/com32/samples/advdump.c
new file mode 100644 (file)
index 0000000..f50401b
--- /dev/null
@@ -0,0 +1,53 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2007 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., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * advdump.c
+ *
+ * Dump the contents of the syslinux ADV
+ */
+
+#include <stdio.h>
+#include <console.h>
+#include <syslinux/adv.h>
+#include <string.h>
+
+int main(void)
+{
+  uint8_t *p, *ep;
+  size_t s = syslinux_adv_size();
+  char buf[256];
+
+  openconsole(&dev_stdcon_r, &dev_stdcon_w);
+
+  p = syslinux_adv_ptr();
+
+  printf("ADV size: %zd bytes at %p\n", s, p);
+
+  ep = p+s;                    /* Need at least opcode+len */
+  while (p < ep-1 && *p) {
+    int t = *p++;
+    int l = *p++;
+
+    if (p+l > ep)
+      break;
+
+    memcpy(buf, p, l);
+    buf[l] = '\0';
+
+    printf("ADV %3d: \"%s\"\n", t, buf);
+
+    p += l;
+  }
+
+  return 0;
+}
index 2c1c882..7deac33 100644 (file)
@@ -592,6 +592,7 @@ comapi_dnsresolv:
                mov si,P_BX
                call dns_resolv
                mov P_EAX,eax
+               clc
                ret
 %else
 comapi_dnsresolv equ comapi_err
@@ -898,6 +899,20 @@ comapi_shufflerm:
                stc
                ret
 
+;
+; INT 22h AX=001Ch     Get pointer to auxillary data vector
+;
+comapi_getadv:
+               mov P_ES,ds
+               mov P_BX,adv0.data
+               mov P_CX,ADV_LEN
+               ret
+
+;
+; INT 22h AX=001Dh     Write auxillary data vector
+;
+comapi_writeadv        equ adv_write
+
                section .data
 
 %macro         int21 2
@@ -948,6 +963,8 @@ int22_table:
                dw comapi_readdisk      ; 0019 read disk
                dw comapi_shufflepm     ; 001A cleanup, shuffle and boot to pm
                dw comapi_shufflerm     ; 001B cleanup, shuffle and boot to rm
+               dw comapi_getadv        ; 001C get pointer to ADV
+               dw comapi_writeadv      ; 001D write ADV to disk
 int22_count    equ ($-int22_table)/2
 
 APIKeyWait     db 0
index c520704..a69bfc4 100644 (file)
@@ -828,7 +828,7 @@ AX=001Ah [3.50] Cleanup, shuffle and boot to flat protected mode
 
 
 AX=001Bh [3.50] Cleanup, shuffle and boot to real mode
-       Input:  AX      001Ah
+       Input:  AX      001Bh
                DX      derivative-specific flags (see function 000Ch)
                ES:DI   shuffle descriptor list (must be in low memory)
                CX      number of shuffle descriptors
@@ -869,3 +869,26 @@ AX=001Bh [3.50] Cleanup, shuffle and boot to real mode
        };
 
        Interrupts are off and DF=0 on entry.
+
+
+AX=001Ch [3.60] Get pointer to auxilliary data vector
+       Input:  AX      001Ch
+       Output: ES:BX   Auxilliary data vector
+               CX      Size of the ADV (currently 500 bytes)
+
+       The auxillary data vector is a tagged data structure used
+       to carry a small amount of information (up to 500 bytes) from
+       one boot to another.
+
+
+AX=001Dh [3.60]        Write auxilliary data vector
+       Input:  AX      001Dh
+       Output: None
+
+       Write the auxilliary data vector back to disk.  Returns
+       failure for non-disk-based derivatives unless the "auxdata"
+       configuration command is used to specify a disk location
+       (not yet implemented.)
+
+       In a future version, PXELINUX may end up attempting to save
+       the ADV on the server via TFTP write.
index 78f0910..2508fa1 100644 (file)
@@ -6,7 +6,7 @@ It works the same way as SYSLINUX, with a few slight modifications.
 1. The installer is run on a *mounted* filesystem.  Run the extlinux
    installer on the directory in which you want extlinux installed:
 
-       extlinux -i /boot
+       extlinux --install /boot
 
    Specify --install (-i) to install for the first time, or
    --update (-U) to upgrade a previous installation.
@@ -15,9 +15,10 @@ It works the same way as SYSLINUX, with a few slight modifications.
    If /boot is a filesystem, you can do:
 
        mkdir -p /boot/extlinux
-       extlinux -i /boot/extlinux
+       extlinux --install /boot/extlinux
 
    ... to create a subdirectory and install extlinux in it.
+   /boot/extlinux is the recommended location for extlinux.
 
 
 2. The configuration file is called "extlinux.conf", and is expected
@@ -42,6 +43,39 @@ It works the same way as SYSLINUX, with a few slight modifications.
    possible.
 
 
+5. EXTLINUX now has "boot-once" support.  The boot-once information is
+   stored in an on-disk datastructure, part of extlinux.sys, called
+   the "Auxillary Data Vector".  The Auxilliary Data Vector is also
+   available to COMBOOT/COM32 modules that want to store small amounts
+   of information.
+
+   To set the boot-once information, do:
+
+       extlinux --once 'command' /boot/extlinux
+
+   where 'command' is any command you could enter at the SYSLINUX
+   command line.  It will be executed on the next boot and then
+   erased.
+
+   To clear the boot-once information, do:
+
+       extlinux --clear-once /boot/extlinux
+
+   If EXTLINUX is used on a RAID-1, this is recommended, since under
+   certain circumstances a RAID-1 rebuild can "resurrect" the
+   boot-once information otherwise.
+
+   To clear the entire Auxillary Data Vector, do:
+
+       extlinux --reset-adv /boot/extlinux
+
+   This will erase all data stored in the ADV, including boot-once.
+
+   The --once, --clear-once, and --reset-adv commands can be combined
+   with --install or --update, if desired.  The ADV is preserved
+   across updates, unless --reset-adv is specified.
+   
+
 Note that EXTLINUX installs in the filesystem partition like a
 well-behaved bootloader :)  Thus, it needs a master boot record in the
 partition table; the mbr.bin shipped with SYSLINUX should work well.
index 53406b1..1bfc513 100644 (file)
@@ -3,13 +3,15 @@ TMPFILE = $(shell mktemp /tmp/gcc_ok.XXXXXX)
 gcc_ok   = $(shell tmpf=$(TMPFILE); if gcc $(1) -c -x c /dev/null -o $$tmpf 2>/dev/null; \
                   then echo $(1); else echo $(2); fi; rm -f $$tmpf)
 
-M32       := $(call gcc_ok,-m32,) $(call gcc_ok,-ffreestanding,) $(call gcc_ok,-fno-stack-protector,)
+M32       := $(call gcc_ok,-m32,) $(call gcc_ok,-ffreestanding,) \
+       $(call gcc_ok,-fno-stack-protector,) \
+       $(call gcc_ok,-fno-top-level-reorder,$(call gcc_ok,-fno-unit-at-a-time))
 
 CC      = gcc
 LD       = ld -m elf_i386
 OBJCOPY  = objcopy
 OPTFLAGS = -g -Os -march=i386 -falign-functions=0 -falign-jumps=0 -falign-loops=0 -fomit-frame-pointer
-INCLUDES = -include code16.h -I. -I.. -I../libfat
+INCLUDES = -include code16.h -I. -I.. -I../libfat -I ../libinstaller
 CFLAGS  = $(M32) -mregparm=3 -DREGPARM=3 -W -Wall -msoft-float $(OPTFLAGS) $(INCLUDES)
 LDFLAGS         = -T com16.ld
 AR       = ar
@@ -25,7 +27,7 @@ LIBOBJS        = conio.o memcpy.o memset.o  skipatou.o atou.o malloc.o free.o \
 
 .SUFFIXES: .c .o .i .s .S .elf .com
 
-VPATH = .:..:../libfat
+VPATH = .:..:../libfat:../libinstaller
 
 TARGETS = syslinux.com
 
index 6666f79..27eaed3 100644 (file)
@@ -112,7 +112,7 @@ trackbuf    resb trackbufsize       ; Track buffer goes here
 getcbuf                resb trackbufsize
                ; ends at 4800h
 
-               section .bss
+               section .bss1
 SuperBlock     resb 1024               ; ext2 superblock
 SuperInfo      resq 16                 ; DOS superblock expanded
 ClustSize      resd 1                  ; Bytes/cluster ("block")
@@ -591,8 +591,10 @@ ldlinux_magic      dd LDLINUX_MAGIC
 ; LDLINUX_MAGIC, plus 8 bytes.
 ;
 patch_area:
-LDLDwords      dw 0            ; Total dwords starting at ldlinux_sys
-LDLSectors     dw 0            ; Number of sectors - (bootsec+this sec)
+LDLDwords      dw 0            ; Total dwords starting at ldlinux_sys,
+                               ; not including ADVs
+LDLSectors     dw 0            ; Number of sectors, not including
+                               ; bootsec & this sec, but including the two ADVs
 CheckSum       dd 0            ; Checksum starting at ldlinux_sys
                                ; value = LDLINUX_MAGIC - [sum of dwords]
 CurrentDir     dd 2            ; "Current" directory inode number
@@ -1528,7 +1530,8 @@ getfssec:
 %include "highmem.inc"         ; High memory sizing
 %include "strcpy.inc"           ; strcpy()
 %include "strecpy.inc"          ; strcpy with end pointer check
-%include "cache.inc"
+%include "cache.inc"           ; Metadata disk cache
+%include "adv.inc"             ; Auxillary Data Vector
 
 ; -----------------------------------------------------------------------------
 ;  Begin data section
index d2ea6f9..908d1ce 100644 (file)
@@ -8,16 +8,16 @@ LDHASH  := $(call gcc_ok,-Wl$(comma)--hash-style=both,)
 
 CC      = gcc
 OPTFLAGS = -g -Os
-INCLUDES = -I. -I.. -I../libfat
+INCLUDES = -I. -I.. -I../libinstaller
 CFLAGS  = -W -Wall -Wno-sign-compare -D_FILE_OFFSET_BITS=64 $(OPTFLAGS) $(INCLUDES)
-LDFLAGS         = $(LDHASH) -s
+LDFLAGS         = $(LDHASH) -s
 
-SRCS     = extlinux.c ../extlinux_bss_bin.c ../extlinux_sys_bin.c
+SRCS     = extlinux.c setadv.c extlinux_bss_bin.c extlinux_sys_bin.c
 OBJS    = $(patsubst %.c,%.o,$(notdir $(SRCS)))
 
 .SUFFIXES: .c .o .i .s .S
 
-VPATH = .:..
+VPATH = .:..:../libinstaller
 
 all: installer
 
index a3d57bd..ac24497 100644 (file)
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 1998-2005 H. Peter Anvin - All Rights Reserved
+ *   Copyright 1998-2007 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
@@ -43,6 +43,7 @@ typedef uint64_t u64;
 
 #include "ext2_fs.h"
 #include "../version.h"
+#include "syslxint.h"
 
 #ifdef DEBUG
 # define dprintf printf
@@ -59,10 +60,14 @@ struct my_options {
   unsigned int sectors;
   unsigned int heads;
   int raid_mode;
+  int reset_adv;
+  const char *set_once;
 } opt = {
   .sectors = 0,
   .heads = 0,
   .raid_mode = 0,
+  .reset_adv = 0,
+  .set_once = NULL,
 };
 
 static void __attribute__((noreturn)) usage(int rv)
@@ -75,6 +80,9 @@ static void __attribute__((noreturn)) usage(int rv)
          "  --sectors=#  -S  Force the number of sectors per track\n"
          "  --heads=#    -H  Force number of heads\n"
          "  --raid       -r  Fall back to the next device on boot failure\n"
+         "  --once=...   -o  Execute a command once upon boot\n"
+         "  --clear-once -O  Clear the boot-once command\n"
+         "  --reset-adv      Reset auxilliary data\n"
          "\n"
          "  Note: geometry is determined at boot time for devices which\n"
          "  are considered hard disks by the BIOS.  Unfortunately, this is\n"
@@ -88,19 +96,27 @@ static void __attribute__((noreturn)) usage(int rv)
   exit(rv);
 }
 
+enum long_only_opt {
+  OPT_NONE,
+  OPT_RESET_ADV,
+};
+
 static const struct option long_options[] = {
-  { "install",   0, NULL, 'i' },
-  { "update",    0, NULL, 'U' },
-  { "zipdrive",  0, NULL, 'z' },
-  { "sectors",   1, NULL, 'S' },
-  { "heads",     1, NULL, 'H' },
-  { "raid-mode", 0, NULL, 'r' },
-  { "version",   0, NULL, 'v' },
-  { "help",      0, NULL, 'h' },
+  { "install",    0, NULL, 'i' },
+  { "update",     0, NULL, 'U' },
+  { "zipdrive",   0, NULL, 'z' },
+  { "sectors",    1, NULL, 'S' },
+  { "heads",      1, NULL, 'H' },
+  { "raid-mode",  0, NULL, 'r' },
+  { "version",    0, NULL, 'v' },
+  { "help",       0, NULL, 'h' },
+  { "once",       1, NULL, 'o' },
+  { "clear-once", 0, NULL, 'O' },
+  { "reset-adv",  0, NULL, OPT_RESET_ADV },
   { 0, 0, 0, 0 }
 };
 
-static const char short_options[] = "iUuzS:H:rvh";
+static const char short_options[] = "iUuzS:H:rvho:O";
 
 #if defined(__linux__) && !defined(BLKGETSIZE64)
 /* This takes a u64, but the size field says size_t.  Someone screwed big. */
@@ -158,66 +174,10 @@ enum bs_offsets {
 #define bsCode     bs32Code    /* The common safe choice */
 #define bsCodeLen   (bsSignature-bs32Code)
 
-/*
- * Access functions for littleendian numbers, possibly misaligned.
- */
-static inline uint8_t get_8(const unsigned char *p)
-{
-  return *(const uint8_t *)p;
-}
-
-static inline uint16_t get_16(const unsigned char *p)
-{
-#if defined(__i386__) || defined(__x86_64__)
-  /* Littleendian and unaligned-capable */
-  return *(const uint16_t *)p;
-#else
-  return (uint16_t)p[0] + ((uint16_t)p[1] << 8);
-#endif
-}
-
-static inline uint32_t get_32(const unsigned char *p)
-{
-#if defined(__i386__) || defined(__x86_64__)
-  /* Littleendian and unaligned-capable */
-  return *(const uint32_t *)p;
-#else
-  return (uint32_t)p[0] + ((uint32_t)p[1] << 8) +
-    ((uint32_t)p[2] << 16) + ((uint32_t)p[3] << 24);
-#endif
-}
-
-static inline void set_16(unsigned char *p, uint16_t v)
-{
-#if defined(__i386__) || defined(__x86_64__)
-  /* Littleendian and unaligned-capable */
-  *(uint16_t *)p = v;
-#else
-  p[0] = (v & 0xff);
-  p[1] = ((v >> 8) & 0xff);
-#endif
-}
-
-static inline void set_32(unsigned char *p, uint32_t v)
-{
-#if defined(__i386__) || defined(__x86_64__)
-  /* Littleendian and unaligned-capable */
-  *(uint32_t *)p = v;
-#else
-  p[0] = (v & 0xff);
-  p[1] = ((v >> 8) & 0xff);
-  p[2] = ((v >> 16) & 0xff);
-  p[3] = ((v >> 24) & 0xff);
-#endif
-}
-
 #ifndef EXT2_SUPER_OFFSET
 #define EXT2_SUPER_OFFSET 1024
 #endif
 
-#define SECTOR_SHIFT   9       /* 512-byte sectors */
-#define SECTOR_SIZE    (1 << SECTOR_SHIFT)
-
 const char *program;
 
 /*
@@ -490,6 +450,7 @@ patch_file_and_bootblock(int fd, int dirfd, int devfd)
 
   dprintf("directory inode = %lu\n", (unsigned long) dirst.st_ino);
   nsect = (boot_image_len+SECTOR_SIZE-1) >> SECTOR_SHIFT;
+  nsect += 2;                  /* Two sectors for the ADV */
   sectp = alloca(sizeof(uint32_t)*nsect);
   if ( sectmap(fd, sectp, nsect) ) {
     perror("bmap");
@@ -505,9 +466,10 @@ patch_file_and_bootblock(int fd, int dirfd, int devfd)
   patcharea = p+8;
 
   /* Set up the totals */
-  dw = boot_image_len >> 2; /* COMPLETE dwords! */
+  dw = boot_image_len >> 2;    /* COMPLETE dwords, excluding ADV */
   set_16(patcharea, dw);
-  set_16(patcharea+2, nsect);  /* Does not include the first sector! */
+  set_16(patcharea+2, nsect);  /* Not including the first sector, but
+                                  including the ADV */
   set_32(patcharea+8, dirst.st_ino); /* "Current" directory */
 
   /* Set the sector pointers */
@@ -529,6 +491,163 @@ patch_file_and_bootblock(int fd, int dirfd, int devfd)
   set_32(patcharea+4, csum);
 }
 
+/*
+ * Read the ADV from an existing instance, or initialize if invalid.
+ * Returns -1 on fatal errors, 0 if ADV is okay, and 1 if no valid
+ * ADV was found.
+ */
+int
+read_adv(const char *path)
+{
+  char *file;
+  int fd = -1;
+  struct stat st;
+  int err = 0;
+
+  asprintf(&file, "%s%sextlinux.sys",
+          path,
+          path[0] && path[strlen(path)-1] == '/' ? "" : "/");
+
+  if ( !file ) {
+    perror(program);
+    return -1;
+  }
+
+  fd = open(file, O_RDONLY);
+  if ( fd < 0 ) {
+    if ( errno != ENOENT ) {
+      err = -1;
+    } else {
+      syslinux_reset_adv(syslinux_adv);
+    }
+  } else if (fstat(fd, &st)) {
+    err = -1;
+  } else if (st.st_size < 2*ADV_SIZE) {
+    /* Too small to be useful */
+    syslinux_reset_adv(syslinux_adv);
+    err = 0;                   /* Nothing to read... */
+  } else if (xpread(fd, syslinux_adv, 2*ADV_SIZE,
+                   st.st_size-2*ADV_SIZE) != 2*ADV_SIZE) {
+    err = -1;
+  } else {
+    /* We got it... maybe? */
+    err = syslinux_validate_adv(syslinux_adv) ? 1 : 0;
+  }
+
+  if (err < 0)
+    perror(file);
+
+  if (fd >= 0)
+    close(fd);
+  if (file)
+    free(file);
+
+  return err;
+}
+
+/*
+ * Update the ADV in an existing installation.
+ */
+int
+write_adv(const char *path)
+{
+  unsigned char advtmp[2*ADV_SIZE];
+  char *file;
+  int fd = -1;
+  struct stat st, xst;
+  int err = 0;
+  int flags, nflags;
+
+  asprintf(&file, "%s%sextlinux.sys",
+          path,
+          path[0] && path[strlen(path)-1] == '/' ? "" : "/");
+
+  if ( !file ) {
+    perror(program);
+    return -1;
+  }
+
+  fd = open(file, O_RDONLY);
+  if ( fd < 0 ) {
+    err = -1;
+  } else if (fstat(fd, &st)) {
+    err = -1;
+  } else if (st.st_size < 2*ADV_SIZE) {
+    /* Too small to be useful */
+    err = -2;
+  } else if (xpread(fd, advtmp, 2*ADV_SIZE,
+                   st.st_size-2*ADV_SIZE) != 2*ADV_SIZE) {
+    err = -1;
+  } else {
+    /* We got it... maybe? */
+    err = syslinux_validate_adv(advtmp) ? -2 : 0;
+    if (!err) {
+      /* Got a good one, write our own ADV here */
+      if (!ioctl(fd, EXT2_IOC_GETFLAGS, &flags)) {
+       nflags = flags & ~EXT2_IMMUTABLE_FL;
+       if (nflags != flags)
+         ioctl(fd, EXT2_IOC_SETFLAGS, &nflags);
+      }
+      if (!(st.st_mode & S_IWUSR))
+       fchmod(fd, st.st_mode | S_IWUSR);
+
+      /* Need to re-open read-write */
+      close(fd);
+      fd = open(file, O_RDWR|O_SYNC);
+      if (fd < 0) {
+       err = -1;
+      } else if (fstat(fd, &xst) || xst.st_ino != st.st_ino ||
+                xst.st_dev != st.st_dev || xst.st_size != st.st_size) {
+       fprintf(stderr, "%s: race condition on write\n", file);
+       err = -2;
+      }
+      /* Write our own version ... */
+      if (xpwrite(fd, syslinux_adv, 2*ADV_SIZE,
+                 st.st_size-2*ADV_SIZE) != 2*ADV_SIZE) {
+       err = -1;
+      }
+
+      sync();
+
+      if (!(st.st_mode & S_IWUSR))
+       fchmod(fd, st.st_mode);
+
+      if (nflags != flags)
+       ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
+    }
+  }
+
+  if (err == -2)
+    fprintf(stderr, "%s: cannot write auxilliary data (need --update)?\n",
+           file);
+  else if (err == -1)
+    perror(file);
+
+  if (fd >= 0)
+    close(fd);
+  if (file)
+    free(file);
+
+  return err;
+}
+
+/*
+ * Make any user-specified ADV modifications
+ */
+int modify_adv(void)
+{
+  int rv = 0;
+
+  if (opt.set_once) {
+    if (syslinux_setadv(ADV_BOOTONCE, strlen(opt.set_once), opt.set_once)) {
+      fprintf(stderr, "%s: not enough space for boot-once command\n", program);
+      rv = -1;
+    }
+  }
+
+  return rv;
+}
+
 /*
  * Install the boot block on the specified device.
  * Must be run AFTER install_file()!
@@ -595,14 +714,15 @@ install_file(const char *path, int devfd, struct stat *rst)
   }
   close(fd);
 
-  fd = open(file, O_WRONLY|O_TRUNC|O_CREAT, S_IRUSR|S_IRGRP|S_IROTH);
+  fd = open(file, O_WRONLY|O_TRUNC|O_CREAT|O_SYNC, S_IRUSR|S_IRGRP|S_IROTH);
   if ( fd < 0 ) {
     perror(file);
     goto bail;
   }
 
   /* Write it the first time */
-  if ( xpwrite(fd, boot_image, boot_image_len, 0) != boot_image_len ) {
+  if ( xpwrite(fd, boot_image, boot_image_len, 0) != boot_image_len ||
+       xpwrite(fd, syslinux_adv, 2*ADV_SIZE, boot_image_len) != 2*ADV_SIZE ) {
     fprintf(stderr, "%s: write failure on %s\n", program, file);
     goto bail;
   }
@@ -610,8 +730,9 @@ install_file(const char *path, int devfd, struct stat *rst)
   /* Map the file, and patch the initial sector accordingly */
   patch_file_and_bootblock(fd, dirfd, devfd);
 
-  /* Write it again - this relies on the file being overwritten in place! */
-  if ( xpwrite(fd, boot_image, boot_image_len, 0) != boot_image_len ) {
+  /* Write the first sector again - this relies on the file being
+     overwritten in place! */
+  if ( xpwrite(fd, boot_image, SECTOR_SIZE, 0) != SECTOR_SIZE ) {
     fprintf(stderr, "%s: write failure on %s\n", program, file);
     goto bail;
   }
@@ -665,6 +786,17 @@ static void device_cleanup(void)
 }
 #endif
 
+/* Verify that a device fd and a pathname agree.
+   Return 0 on valid, -1 on error. */
+static int validate_device(const char *path, int devfd)
+{
+  struct stat pst, dst;
+
+  if (stat(path, &pst) || fstat(devfd, &dst))
+    return -1;
+
+  return (pst.st_dev == dst.st_rdev) ? 0 : -1;
+}
 
 int
 install_loader(const char *path, int update_only)
@@ -738,12 +870,30 @@ install_loader(const char *path, int update_only)
     return 1;
   }
 
+  /* Verify that the device we opened is the device intended */
+  if (validate_device(path, devfd)) {
+    fprintf(stderr, "%s: path %s doesn't match device %s\n",
+           program, path, devname);
+    return 1;
+  }
+
   if ( update_only && !already_installed(devfd) ) {
     fprintf(stderr, "%s: no previous extlinux boot sector found\n", program);
     return 1;
   }
 
-  install_file(path, devfd, &fst);
+  /* Read a pre-existing ADV, if already installed */
+  if (opt.reset_adv)
+    syslinux_reset_adv(syslinux_adv);
+  else if (read_adv(path) < 0)
+    return 1;
+
+  if (modify_adv() < 0)
+    return 1;
+
+  /* Install extlinux.sys */
+  if (install_file(path, devfd, &fst))
+    return 1;
 
   if ( fst.st_dev != st.st_dev ) {
     fprintf(stderr, "%s: file system changed under us - aborting!\n",
@@ -759,6 +909,26 @@ install_loader(const char *path, int update_only)
   return rv;
 }
 
+/*
+ * Modify the ADV of an existing installation
+ */
+int
+modify_existing_adv(const char *path)
+{
+  if (opt.reset_adv)
+    syslinux_reset_adv(syslinux_adv);
+  else if (read_adv(path) < 0)
+    return 1;
+    
+  if (modify_adv() < 0)
+    return 1;
+
+  if (write_adv(path) < 0)
+    return 1;
+
+  return 0;
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -804,6 +974,15 @@ main(int argc, char *argv[])
     case 'h':
       usage(0);
       break;
+    case 'o':
+      opt.set_once = optarg;
+      break;
+    case 'O':
+      opt.set_once = "";
+      break;
+    case OPT_RESET_ADV:
+      opt.reset_adv = 1;
+      break;
     case 'v':
       fputs("extlinux " VERSION "\n", stderr);
       exit(0);
@@ -818,9 +997,11 @@ main(int argc, char *argv[])
     usage(EX_USAGE);
 
   if ( update_only == -1 ) {
-    fprintf(stderr, "%s: warning: a future version will require "
-           "--install or --update\n", program);
-    update_only = 0;
+    if (opt.reset_adv || opt.set_once) {
+      return modify_existing_adv(directory);
+    } else {
+      usage(EX_USAGE);
+    }
   }
 
   return install_loader(directory, update_only);
index ba7a6a6..0be751f 100644 (file)
@@ -1493,6 +1493,7 @@ getfssec:
 %include "highmem.inc"         ; High memory sizing
 %include "strcpy.inc"          ; strcpy()
 %include "rawcon.inc"          ; Console I/O w/o using the console functions
+%include "adv.inc"             ; Auxillary Data Vector
 
 ; -----------------------------------------------------------------------------
 ;  Begin data section
index 3070373..200ef9e 100644 (file)
@@ -56,7 +56,12 @@ STACK_START  equ TEXT_START-STACK_SIZE
                ; NASM BUG: .data always follows .text; can't override
                section .data           align=16 ; follows=.text
 
-               section .adv            progbits align=1 follows=.config
+               ; This empty section works around a NASM bug with regards
+               ; to follows= and nobits sections following a section which
+               ; has VMA != LMA.
+               section .advpad         progbits align=512 follows=.config
+
+               section .adv            nobits align=512 follows=.advpad
 
                ; .uibss contains bss data which is guaranteed to be
                ; safe to clobber during the loading of the image.  This
index ff90043..538ce68 100644 (file)
@@ -827,13 +827,13 @@ genfatinfo:
                bsr cx,ax
                mov [ClustShift],cl
                push cx
-               add cl,9
+               add cl,SECTOR_SHIFT
                mov [ClustByteShift],cl
                pop cx
                dec ax
                mov [ClustMask],eax
                inc ax
-               shl eax,9
+               shl eax,SECTOR_SHIFT
                mov [ClustSize],eax
 
 ;
@@ -868,14 +868,6 @@ getfattype:
 %include "cpuinit.inc"
 %include "init.inc"
 
-;
-; Clear Files structures
-;
-               mov di,Files
-               mov cx,(MAX_OPEN*open_file_t_size)/4
-               xor eax,eax
-               rep stosd
-
 ;
 ; Initialize the metadata cache
 ;
@@ -1550,6 +1542,7 @@ getfatsector:
 %include "highmem.inc"         ; High memory sizing
 %include "strcpy.inc"           ; strcpy()
 %include "cache.inc"           ; Metadata disk cache
+%include "adv.inc"             ; Auxillary Data Vector
 
 ; -----------------------------------------------------------------------------
 ;  Begin data section
diff --git a/libinstaller/advconst.h b/libinstaller/advconst.h
new file mode 120000 (symlink)
index 0000000..044572b
--- /dev/null
@@ -0,0 +1 @@
+../com32/include/syslinux/advconst.h
\ No newline at end of file
diff --git a/libinstaller/setadv.c b/libinstaller/setadv.c
new file mode 100644 (file)
index 0000000..e786e40
--- /dev/null
@@ -0,0 +1,160 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2007 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., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * setadv.c
+ *
+ * (Over)write a data item in the auxilliary data vector.  To
+ * delete an item, set its length to zero.
+ *
+ * Return 0 on success, -1 on error, and set errno.
+ *
+ */
+
+#include <string.h>
+#include <errno.h>
+#include "syslxint.h"
+
+unsigned char syslinux_adv[2*ADV_SIZE];
+
+#define ADV_MAGIC1     0x5a2d2fa5      /* Head signature */
+#define ADV_MAGIC2     0xa3041767      /* Total checksum */
+#define ADV_MAGIC3     0xdd28bf64      /* Tail signature */
+
+static void cleanup_adv(unsigned char *advbuf)
+{
+  int i;
+  uint32_t csum;
+
+  /* Make sure both copies agree, and update the checksum */
+  set_32(advbuf, ADV_MAGIC1);
+  
+  csum = ADV_MAGIC2;
+  for (i = 8; i < ADV_SIZE-4; i += 4)
+    csum -= get_32(advbuf+i);
+  
+  set_32(advbuf+4, csum);
+  set_32(advbuf+ADV_SIZE-4, ADV_MAGIC3);
+
+  memcpy(advbuf+ADV_SIZE, advbuf, ADV_SIZE);
+}
+
+int syslinux_setadv(int tag, size_t size, const void *data)
+{
+  uint8_t *p;
+  size_t left;
+  uint8_t advtmp[ADV_SIZE];
+
+  if ((unsigned)tag-1 > 254) {
+    errno = EINVAL;
+    return -1;                 /* Impossible tag value */
+  }
+
+  if (size > 255) {
+    errno = ENOSPC;            /* Max 255 bytes for a data item */
+    return -1;
+  }
+
+  left = ADV_LEN;
+  p = advtmp;
+  memcpy(p, syslinux_adv+2*4, left); /* Make working copy */
+
+  while (left >= 2) {
+    uint8_t ptag = p[0];
+    size_t  plen = p[1]+2;
+
+    if (ptag == ADV_END)
+      break;
+
+    if (ptag == tag) {
+      /* Found our tag.  Delete it. */
+
+      if (plen >= left) {
+       /* Entire remainder is our tag */
+       break;
+      }
+      memmove(p, p+plen, left-plen);
+    } else {
+      /* Not our tag */
+      if (plen > left)
+       break;                  /* Corrupt tag (overrun) - overwrite it */
+
+      left -= plen;
+      p += plen;
+    }
+  }
+
+  /* Now (p, left) reflects the position to write in and how much space
+     we have for our data. */
+
+  if (size) {
+    if (left < size+2) {
+      errno = ENOSPC;          /* Not enough space for data */
+      return -1;
+    }
+
+    *p++ = tag;
+    *p++ = size;
+    memcpy(p, data, size);
+    p += size;
+    left -= size+2;
+  }
+
+  memset(p, 0, left);
+
+  /* If we got here, everything went OK, commit the write */
+  memcpy(syslinux_adv+2*4, advtmp, ADV_LEN);
+  cleanup_adv(syslinux_adv);
+
+  return 0;
+}
+
+void syslinux_reset_adv(unsigned char *advbuf)
+{
+  /* Create an all-zero ADV */
+  memset(advbuf+2*4, 0, ADV_LEN);
+  cleanup_adv(advbuf);
+}
+
+static int adv_consistent(const unsigned char *p)
+{
+  int i;
+  uint32_t csum;
+
+  if (get_32(p) != ADV_MAGIC1 || get_32(p+ADV_SIZE-4) != ADV_MAGIC3)
+    return 0;
+
+  csum = 0;
+  for (i = 4; i < ADV_SIZE-4; i += 4)
+    csum += get_32(p+i);
+
+  return csum == ADV_MAGIC2;
+}
+
+/*
+ * Verify that an in-memory ADV is consistent, making the copies consistent.
+ * If neither copy is OK, return -1 and call syslinux_reset_adv().
+ */
+int syslinux_validate_adv(unsigned char *advbuf)
+{
+  if (adv_consistent(advbuf+0*ADV_SIZE)) {
+    memcpy(advbuf+ADV_SIZE, advbuf, ADV_SIZE);
+    return 0;
+  } else if (adv_consistent(advbuf+1*ADV_SIZE)) {
+    memcpy(advbuf, advbuf+ADV_SIZE, ADV_SIZE);
+    return 0;
+  } else {
+    syslinux_reset_adv(advbuf);
+    return -1;
+  }
+}
+
similarity index 81%
rename from syslinux.h
rename to libinstaller/syslinux.h
index 60b36ce..dd04aad 100644 (file)
@@ -14,6 +14,7 @@
 #define SYSLINUX_H
 
 #include <inttypes.h>
+#include "advconst.h"
 
 /* The standard boot sector and ldlinux image */
 extern unsigned char syslinux_bootsect[];
@@ -38,4 +39,13 @@ const char *syslinux_check_bootsect(const void *bs);
 int syslinux_patch(const uint32_t *sectors, int nsectors,
                   int stupid, int raid_mode);
 
+/* ADV information */
+#define ADV_SIZE       512             /* Total size */
+#define ADV_LEN                (ADV_SIZE-3*4)  /* Usable data size */
+extern unsigned char syslinux_adv[2*ADV_SIZE];
+
+int syslinux_setadv(int tag, size_t size, const void *data);
+void syslinux_reset_adv(unsigned char *advbuf);
+int syslinux_validate_adv(unsigned char *advbuf);
+
 #endif
diff --git a/libinstaller/syslxint.h b/libinstaller/syslxint.h
new file mode 100644 (file)
index 0000000..e296df1
--- /dev/null
@@ -0,0 +1,74 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2007 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., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef SYSLXINT_H
+#define SYSLXINT_H
+
+#include "syslinux.h"
+
+/*
+ * Access functions for littleendian numbers, possibly misaligned.
+ */
+static inline uint8_t get_8(const unsigned char *p)
+{
+  return *(const uint8_t *)p;
+}
+
+static inline uint16_t get_16(const unsigned char *p)
+{
+#if defined(__i386__) || defined(__x86_64__)
+  /* Littleendian and unaligned-capable */
+  return *(const uint16_t *)p;
+#else
+  return (uint16_t)p[0] + ((uint16_t)p[1] << 8);
+#endif
+}
+
+static inline uint32_t get_32(const unsigned char *p)
+{
+#if defined(__i386__) || defined(__x86_64__)
+  /* Littleendian and unaligned-capable */
+  return *(const uint32_t *)p;
+#else
+  return (uint32_t)p[0] + ((uint32_t)p[1] << 8) +
+    ((uint32_t)p[2] << 16) + ((uint32_t)p[3] << 24);
+#endif
+}
+
+static inline void set_16(unsigned char *p, uint16_t v)
+{
+#if defined(__i386__) || defined(__x86_64__)
+  /* Littleendian and unaligned-capable */
+  *(uint16_t *)p = v;
+#else
+  p[0] = (v & 0xff);
+  p[1] = ((v >> 8) & 0xff);
+#endif
+}
+
+static inline void set_32(unsigned char *p, uint32_t v)
+{
+#if defined(__i386__) || defined(__x86_64__)
+  /* Littleendian and unaligned-capable */
+  *(uint32_t *)p = v;
+#else
+  p[0] = (v & 0xff);
+  p[1] = ((v >> 8) & 0xff);
+  p[2] = ((v >> 16) & 0xff);
+  p[3] = ((v >> 24) & 0xff);
+#endif
+}
+
+#define SECTOR_SHIFT   9       /* 512-byte sectors */
+#define SECTOR_SIZE    (1 << SECTOR_SHIFT)
+
+#endif /* SYSLXINT_H */
similarity index 100%
rename from syslxmod.c
rename to libinstaller/syslxmod.c
index 16d63a6..4b52cb6 100644 (file)
@@ -8,7 +8,7 @@ LDHASH  := $(call gcc_ok,-Wl$(comma)--hash-style=both,)
 
 CC      = gcc
 OPTFLAGS = -g -Os
-INCLUDES = -I. -I.. -I../libfat
+INCLUDES = -I. -I.. -I../libfat -I../libinstaller
 CFLAGS  = -W -Wall -D_FILE_OFFSET_BITS=64 $(OPTFLAGS) $(INCLUDES)
 LDFLAGS         = $(LDHASH) -s
 
@@ -17,7 +17,7 @@ OBJS   = $(patsubst %.c,%.o,$(notdir $(SRCS)))
 
 .SUFFIXES: .c .o .i .s .S
 
-VPATH = .:..:../libfat
+VPATH = .:..:../libfat:../libinstaller
 
 all: installer
 
index 431ee90..fa7eb43 100644 (file)
@@ -2433,6 +2433,7 @@ writestr  equ cwritestr
 %include "strcpy.inc"          ; strcpy()
 %include "rawcon.inc"          ; Console I/O w/o using the console functions
 %include "dnsresolv.inc"       ; DNS resolver
+%include "adv.inc"             ; Auxillary Data Vector
 
 ; -----------------------------------------------------------------------------
 ;  Begin data section
diff --git a/ui.inc b/ui.inc
index dbf6352..8df0633 100644 (file)
--- a/ui.inc
+++ b/ui.inc
@@ -17,6 +17,33 @@ load_config_file:
                call parse_config               ; Parse configuration file
 no_config_file:
 
+               call adv_init
+;
+; Check for an ADV boot-once entry
+;
+               mov dl,ADV_BOOTONCE
+               call adv_get
+               jcxz .no_bootonce
+
+.have_bootone:
+               ; We apparently have a boot-once set; clear it and
+               ; then execute the boot-once...
+
+               ; Save the boot-once data; SI = data, CX = length
+               mov di,command_line
+               rep movsb
+               xor ax,ax
+               stosb
+
+               ; Clear the boot-once data from the ADV
+               xor cx,cx                       ; Set to zero = delete
+               call adv_set
+               jc .err
+               call adv_write
+.err:          jmp load_kernel
+
+.no_bootonce:
+
 ;
 ; Check whether or not we are supposed to display the boot prompt.
 ;
index b046529..75f7cba 100644 (file)
@@ -8,7 +8,7 @@ LDHASH  := $(call gcc_ok,-Wl$(comma)--hash-style=both,)
 
 CC      = gcc
 OPTFLAGS = -g -Os
-INCLUDES = -I. -I..
+INCLUDES = -I. -I.. -I../libinstaller
 CFLAGS  = -W -Wall -D_FILE_OFFSET_BITS=64 $(OPTFLAGS) $(INCLUDES)
 LDFLAGS         = $(LDHASH) -s
 
@@ -17,7 +17,7 @@ OBJS   = $(patsubst %.c,%.o,$(notdir $(SRCS)))
 
 .SUFFIXES: .c .o .i .s .S
 
-VPATH = .:..:../libfat
+VPATH = .:..:../libinstaller
 
 all: installer
 
diff --git a/version b/version
index 376cd27..1057d90 100644 (file)
--- a/version
+++ b/version
@@ -1 +1 @@
-3.55
+3.60
index 6130e29..9bd483a 100644 (file)
@@ -36,11 +36,12 @@ WINAR           = i386-mingw32-ar
 WINRANLIB   = i386-mingw32-ranlib
 endif
 
-WINCFLAGS   = -W -Wall -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64
+WINCFLAGS   = -W -Wall -Wno-sign-compare -Os -fomit-frame-pointer \
+       -D_FILE_OFFSET_BITS=64
 WINPIC      =
 WINLDFLAGS  = -Os -s
 endif
-WINCFLAGS += -I. -I.. -I../libfat
+WINCFLAGS += -I. -I.. -I../libfat -I../libinstaller
 
 WINCC_IS_GOOD := $(shell $(WINCC) $(WINCFLAGS) $(WINLDFLAGS) -o hello.exe hello.c >/dev/null 2>&1 ; echo $$?)
 
@@ -50,7 +51,7 @@ SRCS     = syslinux.c ../syslxmod.c ../bootsect_bin.c ../ldlinux_bin.c \
           ../mbr_bin.c $(wildcard ../libfat/*.c)
 OBJS     = $(patsubst %.c,%.o,$(notdir $(SRCS)))
 
-VPATH = .:..:../libfat
+VPATH = .:..:../libfat:../libinstaller
 
 TARGETS = syslinux.exe