From 5dd1d77145d8ea423af32fcf4f2bda924495f17c Mon Sep 17 00:00:00 2001 From: hpa Date: Thu, 5 Apr 2001 06:20:43 +0000 Subject: [PATCH] The great graphics merge! We're now officially working on version 1.60. --- Makefile | 10 +- Makefile.private | 4 +- NEWS | 3 + ldlinux.asm | 510 ++++++++++++++++++++++++++++++++++++++++++++++++----- ppmtolss16 | 286 ++++++++++++++++++++++++++++++ pxelinux.asm | 508 +++++++++++++++++++++++++++++++++++++++++++++++----- sample/Makefile | 29 +++ sample/sample.msg | 8 + sample/syslogo.png | Bin 0 -> 19847 bytes syslinux.doc | 19 ++ version | 2 +- 11 files changed, 1290 insertions(+), 89 deletions(-) create mode 100755 ppmtolss16 create mode 100644 sample/Makefile create mode 100644 sample/sample.msg create mode 100644 sample/syslogo.png diff --git a/Makefile b/Makefile index acf1371..37a0c25 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ SOURCES = ldlinux.asm syslinux.asm syslinux.c copybs.asm \ pxelinux.asm pxe.inc mbr.asm gethostip.c BTARGET = bootsect.bin ldlinux.sys ldlinux.bin ldlinux.lst pxelinux.0 mbr.bin ITARGET = syslinux.com syslinux copybs.com gethostip -DOCS = COPYING NEWS README TODO *.doc +DOCS = COPYING NEWS README TODO *.doc sample OTHER = Makefile bin2c.pl now.pl genstupid.pl keytab-lilo.pl version \ sys2ansi.pl OBSOLETE = pxelinux.bin @@ -44,12 +44,15 @@ OBSOLETE = pxelinux.bin # Things to install in /usr/bin INSTALL_BIN = syslinux gethostip -all: $(BTARGET) $(ITARGET) +all: $(BTARGET) $(ITARGET) samples ls -l $(BTARGET) $(ITARGET) -installer: $(ITARGET) +installer: $(ITARGET) samples ls -l $(BTARGET) $(ITARGET) +samples: + $(MAKE) -C sample all + # The DATE is set on the make command line when building binaries for # official release. Otherwise, substitute a hex string that is pretty much # guaranteed to be unique to be unique from build to build. @@ -116,6 +119,7 @@ tidy: clean: tidy rm -f $(ITARGET) + $(MAKE) -C sample clean dist: tidy rm -f *~ \#* core diff --git a/Makefile.private b/Makefile.private index 97c7418..56412c2 100644 --- a/Makefile.private +++ b/Makefile.private @@ -30,7 +30,7 @@ release: -rm -rf release/syslinux-$(VERSION) -rm -f release/syslinux-$(VERSION).* mkdir -p release/syslinux-$(VERSION) - cp $(SOURCES) $(DOCS) $(OTHER) release/syslinux-$(VERSION) + cp -r $(SOURCES) $(DOCS) $(OTHER) release/syslinux-$(VERSION) ln $(PRIVATE) release/syslinux-$(VERSION) cd release/syslinux-$(VERSION) && $(MAKE) official cd release/syslinux-$(VERSION) && rm -f $(PRIVATE) @@ -50,7 +50,7 @@ prerel: -rm -rf $(PRERELDIR)/$(PREREL) -rm -f $(PRERELDIR)/$(PREREL).* mkdir -p $(PRERELDIR)/$(PREREL) - cp $(SOURCES) $(DOCS) $(OTHER) $(PRERELDIR)/$(PREREL) + cp -r $(SOURCES) $(DOCS) $(OTHER) $(PRERELDIR)/$(PREREL) make -C $(PRERELDIR)/$(PREREL) spotless make -C $(PRERELDIR)/$(PREREL) all DATE=`printf '%s-pre%d ' $(VERSION) $(PRERELNO) | dd bs=10 count=1 2>/dev/null` make -C $(PRERELDIR)/$(PREREL) dist diff --git a/NEWS b/NEWS index 9c0e90d..cce8d88 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ Starting with 1.47, changes marked with SYSLINUX/PXELINUX apply to that specific program only; other changes apply to both. +Changes in 1.60: + * Add support for graphical splash screens. + Changes in 1.54: * PXELINUX: Fix code for finding !PXE from PXENV+. This was due to a spec bug; match the most recent spec since that diff --git a/ldlinux.asm b/ldlinux.asm index e701b38..12ab164 100644 --- a/ldlinux.asm +++ b/ldlinux.asm @@ -152,7 +152,7 @@ vk_end: equ $ ; Should be <= vk_size ; 7000h - real_mode_seg ; fat_seg equ 5000h ; 128K area for FAT (2x64K) -vk_seg equ 4000h ; This is where we stick'em +vk_seg equ 4000h ; Virtual kernels xfer_buf_seg equ 3000h ; Bounce buffer for I/O to high mem comboot_seg equ 2000h ; COMBOOT image loading zone @@ -245,7 +245,20 @@ trackbuf equ $ ; Track buffer goes here trackbufsize equ 16384 ; Safe size of track buffer ; trackbuf ends at 5000h - absolute 6000h ; Here we keep our BSS stuff + +; +; Constants for the xfer_buf_seg +; +; The xfer_buf_seg is also used to store message file buffers. We +; need two trackbuffers (text and graphics), plus a work buffer +; for the graphics decompressor. +; +xbs_textbuf equ 0 ; Also hard-coded, do not change +xbs_vgabuf equ trackbufsize +xbs_vgatmpbuf equ 2*trackbufsize + + + absolute 5000h ; Here we keep our BSS stuff StackBuf equ $ ; Start the stack here (grow down - 4K) VKernelBuf: resb vk_size ; "Current" vkernel alignb 4 @@ -298,6 +311,10 @@ SetupSecs resw 1 ; Number of setup sectors SavedSP resw 1 ; Our SP while running a COMBOOT image A20Test resw 1 ; Counter for testing status of A20 CmdLineLen resw 1 ; Length of command line including null +GraphXSize resw 1 ; Width of splash screen file +VGAPos resw 1 ; Pointer into VGA memory +VGACluster resw 1 ; Cluster pointer for VGA image file +VGAFilePtr resw 1 ; Pointer into VGAFileBuf TextAttrBX equ $ TextAttribute resb 1 ; Text attribute for message file TextPage resb 1 ; Active display page @@ -316,6 +333,10 @@ MNameBuf resb 11 ; Generic mangled file name buffer InitRD resb 11 ; initrd= mangled name KernelCName resb 13 ; Unmangled kernel name InitRDCName resb 13 ; Unmangled initrd name +TextColorReg resb 17 ; VGA color registers for text mode +VGAFileBuf resb 13 ; Unmangled VGA image name +VGAFileBufEnd equ $ +VGAFileMBuf resb 11 ; Mangled VGA image name section .text org 7C00h @@ -1117,6 +1138,25 @@ is_486: ; Initialization that does not need to go into the any of the pre-load ; areas ; + + ; Get ROM 8x16 font in case we switch to graphics mode + xor cx,cx + mov ax,1130h + mov bh,6 ; Get ROM 8x16 font + int 10h + push es + pop fs + push ds + pop es + cmp cx,16 + jne not_vga ; If not VGA we don't care + mov si,bp + mov di,vgafontbuf + mov cx,(16*256) >> 2 + fs rep movsd +not_vga: + + ; Now set up screen parameters call adjust_screen ; ; Now, everything is "up and running"... patch kaboom for more @@ -1406,7 +1446,9 @@ clear_buffer: mov ah,1 ; Check for pending char xor ax,ax ; Get char int 16h jmp short clear_buffer -get_char_time: mov cx,[KbdTimeOut] +get_char_time: + call vgashowcursor + mov cx,[KbdTimeOut] and cx,cx jz get_char ; Timeout == 0 -> no timeout inc cx ; The first loop will happen @@ -1423,10 +1465,14 @@ tick_loop: push dx je tick_loop pop cx loop time_loop ; If so, decrement counter + call vgahidecursor jmp command_done ; Timeout! get_char_pop: pop eax ; Clear stack -get_char: call getchar +get_char: + call vgashowcursor + call getchar + call vgahidecursor and al,al jz func_key @@ -2070,6 +2116,8 @@ high_load_done: mov si,ready_msg call cwritestr + + call vgaclearmode ; We can't trust ourselves after this ; ; Now, if we were supposed to load "low", copy the kernel down to 10000h ; and the real mode stuff to 90000h. We assume that all bzImage kernels are @@ -2294,6 +2342,8 @@ comboot_end_cmd: mov al,0Dh ; CR after last character sub al,cl mov [es:80h], al ; Store command line length + call vgaclearmode ; Reset video + mov ax,es mov ds,ax mov ss,ax @@ -2370,6 +2420,8 @@ load_bootsec: ; ; Okay, here we go... copy over our own boot sector and run the new one ; + call vgaclearmode ; Reset video + cli ; Point of no return mov dl,[bsDriveNumber] ; May not be in new bootsector! @@ -2912,7 +2964,7 @@ loadfont: jne bf_ret mov al,[trackbuf+2] ; File mode - cmp al,3 ; Font modes 0-3 supported + cmp al,5 ; Font modes 0-5 supported ja bf_ret mov bh,byte [trackbuf+3] ; Height of font @@ -2921,8 +2973,18 @@ loadfont: cmp bh,32 ; VGA maximum ja bf_ret - mov bp,trackbuf+4 ; Address of font data - xor bl,bl + ; Copy to font buffer + mov si,trackbuf+4 ; Start of font data + mov [VGAFontSize],bh + mov di,vgafontbuf + mov bp,di ; Address of font data for INT 10h + mov cx,(32*256) >> 2 ; Maximum size + rep movsd + + xor bl,bl ; Needed by both INT 10h calls + cmp [UsingVGA], byte 1 ; Are we in graphics mode? + je .graphics + mov cx,256 xor dx,dx mov ax,1110h @@ -2934,6 +2996,18 @@ loadfont: jmp short adjust_screen +.graphics: + ; CX = 0 on entry + mov cl,bh ; CX = bytes/character + mov ax,640 + div cl ; Compute char rows per screen + mov dl,al + mov [VidRows],al + mov ax,1121h ; Set user character table + int 10h + ; VidCols = 80, TextPage = 0 set by graphics mode select + ret ; No need to call adjust_screen + ; ; loadkeys: Load a LILO-style keymap; SI and DX:AX set by searchdir ; @@ -2960,46 +3034,43 @@ loadkeys_ret: ret ; set by routine searchdir ; get_msg_file: - mov word [NextCharJump],msg_putchar ; State machine for color - mov byte [TextAttribute],07h ; Default grey on white - pusha - mov bh,[TextPage] - mov ah,03h ; Read cursor position - int 10h - mov [CursorDX],dx - popa -get_msg_chunk: push ax ; DX:AX = length of file - push dx - mov bx,trackbuf + push es + shl edx,16 ; EDX <- DX:AX (length of file) + mov dx,ax + mov ax,xfer_buf_seg ; Use for temporary storage + mov es,ax + + call msg_initvars + +get_msg_chunk: push edx ; EDX = length of file + xor bx,bx ; == xbs_textbuf mov cx,[BufSafe] call getfssec - pop dx - pop ax + pop edx push si ; Save current cluster - mov si,trackbuf - mov cx,[BufSafeBytes] ; No more than many bytes -print_msg_file: push cx - push ax - push dx - lodsb - cmp al,1Ah ; ASCII EOF? + xor si,si ; == xbs_textbuf + mov cx,[BufSafeBytes] ; Number of bytes left in chunk +print_msg_file: + push cx + push edx + es lodsb + cmp al,1Ah ; DOS EOF? je msg_done_pop + push si call [NextCharJump] ; Do what shall be done - pop dx - pop ax + pop si + pop edx pop cx - sub ax,byte 1 - sbb dx,byte 0 - mov bx,ax - or bx,dx + dec edx jz msg_done loop print_msg_file pop si jmp short get_msg_chunk msg_done_pop: - add sp,byte 6 ; Lose 3 words on the stack + add sp,byte 6 ; Drop pushed EDX, CX msg_done: pop si + pop es ret msg_putchar: ; Normal character cmp al,0Fh ; ^O = color code follows @@ -3010,6 +3081,8 @@ msg_putchar: ; Normal character je msg_newline cmp al,0Ch ; = clear screen je msg_formfeed + cmp al,18h ; = VGA filename follows + je near msg_vga msg_normal: call write_serial ; Write to serial port mov bx,[TextAttrBX] @@ -3031,10 +3104,8 @@ msg_ctrl_o: ; ^O = color code follows mov word [NextCharJump],msg_setbg ret msg_newline: ; Newline char or end of line - push si mov si,crlf_msg call write_serial_str - pop si msg_line_wrap: ; Screen wraparound mov byte [CursorCol],0 mov al,[CursorRow] @@ -3051,10 +3122,8 @@ msg_scroll: xor cx,cx ; Upper left hand corner int 10h jmp short msg_gotoxy msg_formfeed: ; Form feed character - push si mov si,crff_msg call write_serial_str - pop si xor cx,cx mov [CursorDX],cx ; Upper lefthand corner mov dx,[ScreenSize] @@ -3073,12 +3142,58 @@ msg_setfg: ; Color foreground character call unhexchar jc msg_color_bad or [TextAttribute],al ; setbg set foreground to 0 - mov word [NextCharJump],msg_putchar - ret + jmp short msg_putcharnext +msg_vga: + mov word [NextCharJump],msg_filename + mov di, VGAFileBuf + jmp short msg_setvgafileptr + msg_color_bad: mov byte [TextAttribute],07h ; Default attribute +msg_putcharnext: mov word [NextCharJump],msg_putchar - ret + ret + +msg_filename: ; Getting VGA filename + cmp al,0Ah ; = end of filename + je msg_viewimage + cmp al,' ' + jbe msg_ret ; Ignore space/control char + mov di,[VGAFilePtr] + cmp di,VGAFileBufEnd + jnb msg_ret + mov [di],al ; Can't use stosb (DS:) + inc di +msg_setvgafileptr: + mov [VGAFilePtr],di +msg_ret: ret + +msg_viewimage: + push es + push ds + pop es ; ES <- DS + mov si,VGAFileBuf + mov di,VGAFileMBuf + push di + call mangle_name + pop di + call searchdir + pop es + jz msg_putcharnext ; Not there + call vgadisplayfile + ; Fall through + + ; Subroutine to initialize variables, also needed + ; after loading a graphics file +msg_initvars: + mov byte [TextAttribute],07h ; Default grey on white + pusha + mov bh,[TextPage] + mov ah,03h ; Read cursor position + int 10h + mov [CursorDX],dx + popa + jmp short msg_putcharnext ; Initialize state machine ; ; write_serial: If serial output is enabled, write character on serial port @@ -3678,6 +3793,308 @@ lc_1: cmp al,lcase_low lc_ret: ret ; ---------------------------------------------------------------------------------- +; VGA splash screen code +; ---------------------------------------------------------------------------------- + +; +; vgadisplayfile: +; Display a graphical splash screen. +; +; Input: +; +; SI = cluster/socket pointer +; +vgadisplayfile: + mov [VGACluster],si + push es + + ; This is a cheap and easy way to make sure the screen is + ; cleared in case we were in graphics mode already + call vgaclearmode + call vgasetmode + jnz .error_nz + +.graphalready: + mov ax,xfer_buf_seg ; Use as temporary storage + mov es,ax + mov fs,ax + + call vgagetchunk ; Get the first chunk + + ; The header WILL be in the first chunk. + cmp dword [es:xbs_vgabuf],0x1413f33d ; Magic number +.error_nz: jne near .error + mov ax,[es:xbs_vgabuf+4] + mov [GraphXSize],ax + + mov dx,xbs_vgabuf+8 ; Color map offset + mov ax,1012h ; Set RGB registers + xor bx,bx ; First register number + mov cx,16 ; 16 registers + int 10h + +.movecursor: + mov ax,[es:xbs_vgabuf+6] ; Number of pixel rows + mov dx,[VGAFontSize] + add ax,dx + dec ax + div dl + xor dx,dx ; Set column to 0 + cmp al,[VidRows] + jb .rowsok + mov al,[VidRows] + dec al +.rowsok: + mov dh,al + mov ah,2 + xor bx,bx + int 10h ; Set cursor below image + + mov cx,[es:xbs_vgabuf+6] ; Number of graphics rows + + mov si,xbs_vgabuf+8+3*16 ; Beginning of pixel data + mov word [VGAPos],0 + +.drawpixelrow: + push cx + mov cx,[GraphXSize] + mov di,xbs_vgatmpbuf ; Row buffer + call rledecode ; Decode one row + push si + mov si,xbs_vgatmpbuf + mov di,si + add di,[GraphXSize] + mov cx,640/4 + xor eax,eax + rep stosd ; Clear rest of row + mov di,0A000h ; VGA segment + mov es,di + mov di,[VGAPos] + mov bp,640 + call packedpixel2vga + add word [VGAPos],byte 80 ; Advance to next pixel row + push fs + pop es + pop si + pop cx + loop .drawpixelrow + +.error: + pop es + ret + +; +; rledecode: +; Decode a pixel row in RLE16 format. +; +; FS:SI -> input +; CX -> pixel count +; ES:DI -> output (packed pixel) +; +rledecode: + shl esi,1 ; Nybble pointer + xor dl,dl ; Last pixel +.loop: + call .getnybble + cmp al,dl + je .run ; Start of run sequence + stosb + mov dl,al + dec cx + jnz .loop +.done: + shr esi,1 + adc si,byte 0 + ret +.run: + xor bx,bx + call .getnybble + and al,al + jz .longrun + mov bl,al +.dorun: + push cx + mov cx,bx + mov al,dl + rep stosb + pop cx + sub cx,bx + ja .loop + jmp short .done +.longrun: + call .getnybble + mov ah,al + call .getnybble + shl al,4 + or al,ah + mov bl,al + add bx,16 + jmp short .dorun +.getnybble: + shr esi,1 + fs lodsb + jc .high + dec si + and al,0Fh + stc + rcl esi,1 + ret +.high: + shr al,4 + cmp si,xbs_vgabuf+trackbufsize ; Chunk overrun + jb .nonewchunk + call vgagetchunk + mov si,xbs_vgabuf ; Start at beginning of buffer +.nonewchunk: + shl esi,1 + ret + +; +; vgagetchunk: +; Get a new trackbufsize chunk of VGA image data +; +; On input, ES is assumed to point to the buffer segment. +; +vgagetchunk: + pushad + mov si,[VGACluster] + and si,si + jz .eof ; EOF overrun, not much to do... + + mov cx,[BufSafe] ; One trackbuf worth of data + mov bx,xbs_vgabuf + call getfssec + + jnc .noteof + xor si,si +.noteof: mov [VGACluster],si + +.eof: popad + ret + +; +; packedpixel2vga: +; Convert packed-pixel to VGA bitplanes +; +; FS:SI -> packed pixel string +; BP -> pixel count (multiple of 8) +; ES:DI -> output +; +packedpixel2vga: + mov dx,3C4h ; VGA Sequencer Register select port + mov al,2 ; Sequencer mask + out dx,al ; Select the sequencer mask + inc dx ; VGA Sequencer Register data port + mov al,1 + mov bl,al +.planeloop: + pusha + out dx,al +.loop1: + mov cx,8 +.loop2: + xchg cx,bx + fs lodsb + shr al,cl + rcl ch,1 ; VGA is bigendian. Sigh. + xchg cx,bx + loop .loop2 + mov al,bh + stosb + sub bp,byte 8 + ja .loop1 + popa + inc bl + shl al,1 + cmp bl,4 + jbe .planeloop + ret + +; +; vgasetmode: +; Enable VGA graphics, if possible; return ZF=1 on success +; DS must be set to the base segment. +; +vgasetmode: + push ds + pop es + mov ax,1A00h ; Get video card and monitor + xor bx,bx + int 10h + cmp bl, 8 ; If not VGA card/VGA monitor, give up + jne .error ; ZF=0 +; mov bx,TextColorReg +; mov dx,1009h ; Read color registers +; int 10h + mov ax,0012h ; Set mode = 640x480 VGA 16 colors + int 10h + mov dx,linear_color + mov ax,1002h ; Write color registers + int 10h + mov [UsingVGA], byte 1 + + mov [VidCols], byte 80 ; Always 80 chars/screen + mov [TextPage], byte 0 ; Always page 0 + + mov cx,[VGAFontSize] + mov ax,640 + div cl + mov [VidRows],al + mov dl,al + mov bp,vgafontbuf + xor bx,bx + mov ax,1121h ; Set graphics font + int 10h + + xor ax,ax ; Set ZF +.error: + ret + +; +; vgaclearmode: +; Disable VGA graphics. It is not safe to assume any value for DS. +; +vgaclearmode: + pushad + cmp [cs:UsingVGA], byte 1 + jne .done + mov ax,0003h ; Return to normal video mode + int 10h +; mov dx,TextColorReg ; Restore color registers +; mov ax,1002h +; int 10h +.done: + popad + ret + +; +; vgashowcursor/vgahidecursor: +; If VGA graphics is enabled, draw a cursor/clear a cursor +; +vgashowcursor: + pushad + mov al,'_' + jmp short vgacursorcommon +vgahidecursor: + pushad + mov al,' ' +vgacursorcommon: + cmp [UsingVGA], byte 1 + jne .done + mov ah,09h + mov bx,0007h + mov cx,1 + int 10h +.done: + popad + ret + + + ; Map colors to consecutive DAC registers +linear_color db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 +UsingVGA db 0 + +; ---------------------------------------------------------------------------------- ; Begin data section ; ---------------------------------------------------------------------------------- @@ -3804,6 +4221,7 @@ SerialPort dw 0 ; Serial port base (or 0 for no serial port) A20List dw a20_dunno, a20_none, a20_bios, a20_kbc, a20_fast A20DList dw a20d_dunno, a20d_none, a20d_bios, a20d_kbc, a20d_fast A20Type dw A20_DUNNO ; A20 type unknown +VGAFontSize dw 16 ; Defaults to 16 byte font ; ; Stuff for the command line; we do some trickery here with equ to avoid ; tons of zeros appended to our file and wasting space @@ -3823,3 +4241,13 @@ ldlinux_len equ ldlinux_end-ldlinux_magic ; end_of_code equ (ldlinux_end-bootsec)+7C00h getcbuf equ (end_of_code + 511) & 0FE00h + +; VGA font buffer at the end of memory (so loading a font works even +; in graphics mode.) +vgafontbuf equ 0E000h + +; This is a compile-time assert that we didn't run out of space +%if (getcbuf+trackbufsize) > vgafontbuf +%error "Out of memory, better reorganize something..." +%endif + diff --git a/ppmtolss16 b/ppmtolss16 new file mode 100755 index 0000000..efbd765 --- /dev/null +++ b/ppmtolss16 @@ -0,0 +1,286 @@ +#!/usr/bin/perl +#ident "$Id$" +## ----------------------------------------------------------------------- +## +## Copyright 2001 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., 675 Mass Ave, Cambridge MA 02139, +## USA; either version 2 of the License, or (at your option) any later +## version; incorporated herein by reference. +## +## ----------------------------------------------------------------------- + +## +## ppmtolss16 +## +## Convert a "raw" PPM file with max 16 colors to a simple RLE-based format: +## +## uint32 0x1413f33d ; magic (littleendian) +## uint16 xsize ; littleendian +## uint16 ysize ; littleendian +## 16 x uint8 r,g,b ; color map, in 6-bit format (each byte is 0..63) +## +## Then, a sequence of nybbles: +## +## N ... if N is != previous pixel, one pixel of color N +## ... otherwise run sequence follows ... +## M ... if M > 0 then run length is M+1 +## ... otherwise run sequence is encoded in two nybbles, +## littleendian, +17 +## +## The nybble sequences are on a per-row basis; runs may not extend +## across rows and odd-nybble rows are zero-padded. +## +## At the start of row, the "previous pixel" is assumed to be zero. +## +## BUG: This program does not handle comments in the header, nor +## "plain" ppm format. +## +## Usage: +## +## ppmtorle16 [#rrggbb=i ...] < input.ppm > output.rle +## +## Command line options of the form #rrggbb=i indicate that +## the color #rrggbb (hex) should be assigned index i (decimal) +## + +$magic = 0x1413f33d; + +foreach $arg ( @ARGV ) { + if ( $arg =~ /^\#([0-9a-f])([0-9a-f])([0-9a-f])=([0-9]+)$/i ) { + $r = hex($1) << 2; + $g = hex($2) << 2; + $b = hex($3) << 2; + $i = $4 + 0; + } elsif ( $arg =~ /^\#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})=([0-9]+)$/i ) { + $r = hex($1) >> 2; + $g = hex($2) >> 2; + $b = hex($3) >> 2; + $i = $4 + 0; + } elsif ( $arg =~ /^\#([0-9a-f]{3})([0-9a-f]{3})([0-9a-f]{3})=([0-9]+)$/i ) { + $r = hex($1) >> 6; + $g = hex($2) >> 6; + $b = hex($3) >> 6; + $i = $4 + 0; + } elsif ( $arg =~ /^\#([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})=([0-9]+)$/i ) { + $r = hex($1) >> 10; + $g = hex($2) >> 10; + $b = hex($3) >> 10; + $i = $4 + 0; + } else { + # print STDERR "$0: Unknown argument: $arg\n"; + next; + } + + if ( $i > 15 ) { + # print STDERR "$0: Color index out of range: $arg\n"; + next; + } + + $rgb = pack("CCC", $r, $g, $b); + + if ( defined($index_forced{$i}) ) { + # print STDERR "$0: More than one color index $i\n"; + exit(1); + } + $index_forced{$i} = $rgb; + $force_index{$rgb} = $i; +} + +$form = ; +die "$0: stdin is not a raw PPM file" if ( $form ne "P6\n" ); +$sizes = ; +chomp $sizes; +if ( $sizes !~ /^([0-9]+)\s+([0-9]+)\s*$/ ) { + die "$0: Input format error 1\n"; +} +$xsize = $1 + 0; +$ysize = $2 + 0; +$maxcol = ; +chomp $maxcol; +if ( $maxcol !~ /^([0-9]+)\s*$/ ) { + die "$0: Input format error 2\n"; +} +$maxcol = $1 + 0; +$maxmult = 64/($maxcol+1); # Equal buckets conversion + +@data = (); + +for ( $y = 0 ; $y < $ysize ; $y++ ) { + for ( $x = 0 ; $x < $xsize ; $x++ ) { + die "$0: Premature EOF at ($x,$y) of ($xsize,$ysize)\n" + if ( read(STDIN, $rgb, 3) != 3 ); + # Convert to 6-bit representation + ($r, $g, $b) = unpack("CCC", $rgb); + $r = int($r*$maxmult+0.5); + $g = int($g*$maxmult+0.5); + $b = int($b*$maxmult+0.5); + $rgb = pack("CCC", $r, $g, $b); + $color_count{$rgb}++; + push(@data, $rgb); + } +} + +# Sort list of colors according to freqency +@colors = sort { $color_count{$b} <=> $color_count{$a} } keys(%color_count); + +if ( scalar(@colors) > 16 ) { + # print STDERR "$0: Warning: input > 16 colors\n"; + @colors = @colors[0..15]; +} + +# Now we have our pick of colors. Sort according to intensity; +# this is more or less an ugly hack to cover for the fact that +# using PPM as input doesn't let the user set the color map, +# which the user really needs to be able to do. + +sub by_intensity() { + my($ra,$ga,$ba) = unpack("CCC", $a); + my($rb,$gb,$bb) = unpack("CCC", $b); + + my($ia) = $ra*0.299 + $ga*0.587 + $ba*0.114; + my($ib) = $rb*0.299 + $gb*0.587 + $bb*0.114; + + return ( $ia <=> $ib ) if ( $ia != $ib ); + + # If same, sort based on RGB components, + # with highest priority given to G, then R, then B. + + return ( $ga <=> $gb ) if ( $ga != $gb ); + return ( $ra <=> $rb ) if ( $ra != $rb ); + return ( $ba <=> $bb ); +} + +@icolors = sort by_intensity @colors; + +# Insert forced colors into "final" array +@colors = (undef) x 16; +foreach $rgb ( @icolors ) { + if ( defined($force_index{$rgb}) ) { + $colors[$force_index{$rgb}] = $rgb; + } +} + +# Insert remaining colors in the remaining slots, +# in luminosity-sorted order +$nix = 0; +foreach $rgb ( @icolors ) { + if ( ! defined($force_index{$rgb}) ) { + # Advance to the next free slot + $nix++ while ( defined($colors[$nix]) ); + $colors[$nix] = $rgb; + } +} + +undef @icolors; + +# Generate color index hash +for ( $i = 0 ; $i < scalar @colors ; $i++ ) { + $color_index{$colors[$i]} = $i; +} + +# Output header +print pack("Vvv", $magic, $xsize, $ysize); + +# Output color map +for ( $i = 0 ; $i < 16 ; $i++ ) { + if ( defined($colors[$i]) ) { + print $colors[$i]; + } else { + # Padding for unused color entries + print pack("CCC", 63*$i/15, 63*$i/15, 63*$i/15); + } +} + +sub output_nybble($) { + my($ny) = @_; + + if ( !defined($ny) ) { + if ( defined($nybble_tmp) ) { + $ny = 0; # Force the last byte out + } else { + return; + } + } + + $ny = $ny & 0x0F; + + # printf STDERR "%x", $ny; + + if ( defined($nybble_tmp) ) { + $ny = ($ny << 4) | $nybble_tmp; + print chr($ny); + $bytes++; + undef $nybble_tmp; + } else { + $nybble_tmp = $ny; + } +} + +sub output_run($$$) { + my($last,$this,$run) = @_; + + # printf STDERR "Color %2d Run %3d = ", $this, $run; + + if ( $this != $last ) { + output_nybble($this); + $run--; + } + while ( $run ) { + if ( $run >= 16 ) { + output_nybble($this); + output_nybble(0); + if ( $run > 271 ) { + $erun = 255; + $run -= 271; + } else { + $erun = $run-16; + $run = 0; + } + output_nybble($erun); + output_nybble($erun >> 4); + } else { + output_nybble($this); + output_nybble($run); + $run = 0; + } + } + # print STDERR "\n"; +} + +$bytes = 0; +undef $nybble_tmp; + +for ( $y = 0 ; $y < $ysize ; $y++ ) { + $last = $prev = 0; + $run = 0; + # printf STDERR "*** Row %3d ***\n", $y; + for ( $x = 0 ; $x < $xsize ; $x++ ) { + $rgb = shift(@data); + $i = $color_index{$rgb} + 0; + if ( $i == $last ) { + $run++; + } else { + output_run($prev, $last, $run); + $prev = $last; + $last = $i; + $run = 1; + } + } + # Output final datum for row; we're always at least one pixel behind + output_run($prev, $last, $run); + # printf STDERR "Row termination = "; + output_nybble(undef); # Flush row + # print STDERR "\n"; +} + +$pixels = $xsize * $ysize; +$size = ($pixels+1)/2; +printf STDERR "%d pixels, %d bytes, (%2.2f%% compression)\n", + $pixels, $bytes, 100*($size-$bytes)/$size; + + + + diff --git a/pxelinux.asm b/pxelinux.asm index 70014e1..cbd7584 100644 --- a/pxelinux.asm +++ b/pxelinux.asm @@ -174,7 +174,7 @@ vk_end: equ $ ; Should be <= vk_size ; 0000h - main code/data segment (and BIOS segment) ; 5000h - real_mode_seg ; -vk_seg equ 4000h ; This is where we stick'em +vk_seg equ 4000h ; Virtual kernels xfer_buf_seg equ 3000h ; Bounce buffer for I/O to high mem comboot_seg equ 2000h ; COMBOOT image loading zone @@ -305,10 +305,21 @@ BIOS_vidrows resb 1 ; Number of screen rows ; Memory below this point is reserved for the BIOS and the MBR ; absolute 1000h -trackbuf resb 16384 ; Track buffer goes here +trackbuf resb 8192 ; Track buffer goes here trackbufsize equ $-trackbuf +; trackbuf ends at 3000h -; trackbuf ends at 5000h + +; +; Constants for the xfer_buf_seg +; +; The xfer_buf_seg is also used to store message file buffers. We +; need two trackbuffers (text and graphics), plus a work buffer +; for the graphics decompressor. +; +xbs_textbuf equ 0 ; Also hard-coded, do not change +xbs_vgabuf equ trackbufsize +xbs_vgatmpbuf equ 2*trackbufsize absolute 5000h ; Here we keep our BSS stuff VKernelBuf: resb vk_size ; "Current" vkernel @@ -352,6 +363,10 @@ NextCharJump resw 1 ; Routine to interpret next print char SetupSecs resw 1 ; Number of setup sectors A20Test resw 1 ; Counter for testing status of A20 CmdLineLen resw 1 ; Length of command line including null +GraphXSize resw 1 ; Width of splash screen file +VGAPos resw 1 ; Pointer into VGA memory +VGACluster resw 1 ; Cluster pointer for VGA image file +VGAFilePtr resw 1 ; Pointer into VGAFileBuf ConfigFile resw 1 ; Socket for config file PktTimeout resw 1 ; Timeout for current packet KernelExtPtr resw 1 ; During search, final null pointer @@ -372,6 +387,10 @@ LoadFlags resb 1 ; Loadflags from kernel A20Tries resb 1 ; Times until giving up on A20 FuncFlag resb 1 ; == 1 if pressed OverLoad resb 1 ; Set if DHCP packet uses "overloading" +TextColorReg resb 17 ; VGA color registers for text mode +VGAFileBuf resb FILENAME_MAX ; Unmangled VGA image name +VGAFileBufEnd equ $ +VGAFileMBuf resb FILENAME_MAX ; Mangled VGA image name alignb tftp_port_t_size Sockets resb MAX_SOCKETS*tftp_port_t_size @@ -414,6 +433,25 @@ _start1: ; ; Initialize screen (if we're using one) ; + + ; Get ROM 8x16 font in case we switch to graphics mode + xor cx,cx + mov ax,1130h + mov bh,6 ; Get ROM 8x16 font + int 10h + push es + pop fs + push ds + pop es + cmp cx,16 + jne not_vga ; If not VGA we don't care + mov si,bp + mov di,vgafontbuf + mov cx,(16*256) >> 2 + fs rep movsd +not_vga: + + ; Now set up screen parameters call adjust_screen ; ; Tell the user we got this far @@ -1114,7 +1152,9 @@ clear_buffer: mov ah,1 ; Check for pending char xor ax,ax ; Get char int 16h jmp short clear_buffer -get_char_time: mov cx,[KbdTimeOut] +get_char_time: + call vgashowcursor + mov cx,[KbdTimeOut] and cx,cx jz get_char ; Timeout == 0 -> no timeout inc cx ; The first loop will happen @@ -1130,10 +1170,14 @@ tick_loop: push dx je tick_loop pop cx loop time_loop ; If so, decrement counter + call vgahidecursor jmp command_done ; Timeout! get_char_pop: pop eax ; Clear stack -get_char: call getchar +get_char: + call vgashowcursor + call getchar + call vgahidecursor and al,al jz func_key @@ -1804,6 +1848,8 @@ nk_noinitrd: mov si,ready_msg call cwritestr + + call vgaclearmode ; We can't trust ourselves after this ; ; Unload PXE stack ; @@ -2041,6 +2087,8 @@ comboot_end_cmd: mov al,0Dh ; CR after last character mov ax,ss ; Save away SS:SP mov [SavedSSSP+2],ax + call vgaclearmode ; Reset video + mov ax,es mov ds,ax mov ss,ax @@ -2949,7 +2997,7 @@ loadfont: jne bf_ret mov al,[trackbuf+2] ; File mode - cmp al,3 ; Font modes 0-3 supported + cmp al,5 ; Font modes 0-5 supported ja bf_ret mov bh,byte [trackbuf+3] ; Height of font @@ -2958,8 +3006,18 @@ loadfont: cmp bh,32 ; VGA maximum ja bf_ret - mov bp,trackbuf+4 ; Address of font data - xor bl,bl + ; Copy to font buffer + mov si,trackbuf+4 ; Start of font data + mov [VGAFontSize],bh + mov di,vgafontbuf + mov bp,di ; Address of font data for INT 10h + mov cx,(32*256) >> 2 ; Maximum size + rep movsd + + xor bl,bl ; Needed by both INT 10h calls + cmp [UsingVGA], byte 1 ; Are we in graphics mode? + je .graphics + mov cx,256 xor dx,dx mov ax,1110h @@ -2971,6 +3029,18 @@ loadfont: jmp short adjust_screen +.graphics: + ; CX = 0 on entry + mov cl,bh ; CX = bytes/character + mov ax,640 + div cl ; Compute char rows per screen + mov dl,al + mov [VidRows],al + mov ax,1121h ; Set user character table + int 10h + ; VidCols = 80, TextPage = 0 set by graphics mode select + ret ; No need to call adjust_screen + ; ; loadkeys: Load a LILO-style keymap; SI and DX:AX set by searchdir ; @@ -2997,46 +3067,43 @@ loadkeys_ret: ret ; set by routine searchdir ; get_msg_file: - mov word [NextCharJump],msg_putchar ; State machine for color - mov byte [TextAttribute],07h ; Default grey on white - pusha - mov bh,[TextPage] - mov ah,03h ; Read cursor position - int 10h - mov [CursorDX],dx - popa -get_msg_chunk: push ax ; DX:AX = length of file - push dx - mov bx,trackbuf + push es + shl edx,16 ; EDX <- DX:AX (length of file) + mov dx,ax + mov ax,xfer_buf_seg ; Use for temporary storage + mov es,ax + + call msg_initvars + +get_msg_chunk: push edx ; EDX = length of file + xor bx,bx ; == xbs_textbuf mov cx,[BufSafe] call getfssec - pop dx - pop ax + pop edx push si ; Save current cluster - mov si,trackbuf - mov cx,[BufSafeBytes] ; No more than many bytes -print_msg_file: push cx - push ax - push dx - lodsb - cmp al,1Ah ; ASCII EOF? + xor si,si ; == xbs_textbuf + mov cx,[BufSafeBytes] ; Number of bytes left in chunk +print_msg_file: + push cx + push edx + es lodsb + cmp al,1Ah ; DOS EOF? je msg_done_pop + push si call [NextCharJump] ; Do what shall be done - pop dx - pop ax + pop si + pop edx pop cx - sub ax,byte 1 - sbb dx,byte 0 - mov bx,ax - or bx,dx + dec edx jz msg_done loop print_msg_file pop si jmp short get_msg_chunk msg_done_pop: - add sp,byte 6 ; Lose 3 words on the stack + add sp,byte 6 ; Drop pushed EDX, CX msg_done: pop si + pop es ret msg_putchar: ; Normal character cmp al,0Fh ; ^O = color code follows @@ -3047,6 +3114,8 @@ msg_putchar: ; Normal character je msg_newline cmp al,0Ch ; = clear screen je msg_formfeed + cmp al,18h ; = VGA filename follows + je near msg_vga msg_normal: call write_serial ; Write to serial port mov bx,[TextAttrBX] @@ -3068,10 +3137,8 @@ msg_ctrl_o: ; ^O = color code follows mov word [NextCharJump],msg_setbg ret msg_newline: ; Newline char or end of line - push si mov si,crlf_msg call write_serial_str - pop si msg_line_wrap: ; Screen wraparound mov byte [CursorCol],0 mov al,[CursorRow] @@ -3088,10 +3155,8 @@ msg_scroll: xor cx,cx ; Upper left hand corner int 10h jmp short msg_gotoxy msg_formfeed: ; Form feed character - push si mov si,crff_msg call write_serial_str - pop si xor cx,cx mov [CursorDX],cx ; Upper lefthand corner mov dx,[ScreenSize] @@ -3110,12 +3175,58 @@ msg_setfg: ; Color foreground character call unhexchar jc msg_color_bad or [TextAttribute],al ; setbg set foreground to 0 - mov word [NextCharJump],msg_putchar - ret + jmp short msg_putcharnext +msg_vga: + mov word [NextCharJump],msg_filename + mov di, VGAFileBuf + jmp short msg_setvgafileptr + msg_color_bad: mov byte [TextAttribute],07h ; Default attribute +msg_putcharnext: mov word [NextCharJump],msg_putchar - ret + ret + +msg_filename: ; Getting VGA filename + cmp al,0Ah ; = end of filename + je msg_viewimage + cmp al,' ' + jbe msg_ret ; Ignore space/control char + mov di,[VGAFilePtr] + cmp di,VGAFileBufEnd + jnb msg_ret + mov [di],al ; Can't use stosb (DS:) + inc di +msg_setvgafileptr: + mov [VGAFilePtr],di +msg_ret: ret + +msg_viewimage: + push es + push ds + pop es ; ES <- DS + mov si,VGAFileBuf + mov di,VGAFileMBuf + push di + call mangle_name + pop di + call searchdir + pop es + jz msg_putcharnext ; Not there + call vgadisplayfile + ; Fall through + + ; Subroutine to initialize variables, also needed + ; after loading a graphics file +msg_initvars: + mov byte [TextAttribute],07h ; Default grey on white + pusha + mov bh,[TextPage] + mov ah,03h ; Read cursor position + int 10h + mov [CursorDX],dx + popa + jmp short msg_putcharnext ; Initialize state machine ; ; write_serial: If serial output is enabled, write character on serial port @@ -4107,6 +4218,308 @@ genipopt: ret ; ---------------------------------------------------------------------------------- +; VGA splash screen code +; ---------------------------------------------------------------------------------- + +; +; vgadisplayfile: +; Display a graphical splash screen. +; +; Input: +; +; SI = cluster/socket pointer +; +vgadisplayfile: + mov [VGACluster],si + push es + + ; This is a cheap and easy way to make sure the screen is + ; cleared in case we were in graphics mode already + call vgaclearmode + call vgasetmode + jnz .error_nz + +.graphalready: + mov ax,xfer_buf_seg ; Use as temporary storage + mov es,ax + mov fs,ax + + call vgagetchunk ; Get the first chunk + + ; The header WILL be in the first chunk. + cmp dword [es:xbs_vgabuf],0x1413f33d ; Magic number +.error_nz: jne near .error + mov ax,[es:xbs_vgabuf+4] + mov [GraphXSize],ax + + mov dx,xbs_vgabuf+8 ; Color map offset + mov ax,1012h ; Set RGB registers + xor bx,bx ; First register number + mov cx,16 ; 16 registers + int 10h + +.movecursor: + mov ax,[es:xbs_vgabuf+6] ; Number of pixel rows + mov dx,[VGAFontSize] + add ax,dx + dec ax + div dl + xor dx,dx ; Set column to 0 + cmp al,[VidRows] + jb .rowsok + mov al,[VidRows] + dec al +.rowsok: + mov dh,al + mov ah,2 + xor bx,bx + int 10h ; Set cursor below image + + mov cx,[es:xbs_vgabuf+6] ; Number of graphics rows + + mov si,xbs_vgabuf+8+3*16 ; Beginning of pixel data + mov word [VGAPos],0 + +.drawpixelrow: + push cx + mov cx,[GraphXSize] + mov di,xbs_vgatmpbuf ; Row buffer + call rledecode ; Decode one row + push si + mov si,xbs_vgatmpbuf + mov di,si + add di,[GraphXSize] + mov cx,640/4 + xor eax,eax + rep stosd ; Clear rest of row + mov di,0A000h ; VGA segment + mov es,di + mov di,[VGAPos] + mov bp,640 + call packedpixel2vga + add word [VGAPos],byte 80 ; Advance to next pixel row + push fs + pop es + pop si + pop cx + loop .drawpixelrow + +.error: + pop es + ret + +; +; rledecode: +; Decode a pixel row in RLE16 format. +; +; FS:SI -> input +; CX -> pixel count +; ES:DI -> output (packed pixel) +; +rledecode: + shl esi,1 ; Nybble pointer + xor dl,dl ; Last pixel +.loop: + call .getnybble + cmp al,dl + je .run ; Start of run sequence + stosb + mov dl,al + dec cx + jnz .loop +.done: + shr esi,1 + adc si,byte 0 + ret +.run: + xor bx,bx + call .getnybble + and al,al + jz .longrun + mov bl,al +.dorun: + push cx + mov cx,bx + mov al,dl + rep stosb + pop cx + sub cx,bx + ja .loop + jmp short .done +.longrun: + call .getnybble + mov ah,al + call .getnybble + shl al,4 + or al,ah + mov bl,al + add bx,16 + jmp short .dorun +.getnybble: + shr esi,1 + fs lodsb + jc .high + dec si + and al,0Fh + stc + rcl esi,1 + ret +.high: + shr al,4 + cmp si,xbs_vgabuf+trackbufsize ; Chunk overrun + jb .nonewchunk + call vgagetchunk + mov si,xbs_vgabuf ; Start at beginning of buffer +.nonewchunk: + shl esi,1 + ret + +; +; vgagetchunk: +; Get a new trackbufsize chunk of VGA image data +; +; On input, ES is assumed to point to the buffer segment. +; +vgagetchunk: + pushad + mov si,[VGACluster] + and si,si + jz .eof ; EOF overrun, not much to do... + + mov cx,[BufSafe] ; One trackbuf worth of data + mov bx,xbs_vgabuf + call getfssec + + jnc .noteof + xor si,si +.noteof: mov [VGACluster],si + +.eof: popad + ret + +; +; packedpixel2vga: +; Convert packed-pixel to VGA bitplanes +; +; FS:SI -> packed pixel string +; BP -> pixel count (multiple of 8) +; ES:DI -> output +; +packedpixel2vga: + mov dx,3C4h ; VGA Sequencer Register select port + mov al,2 ; Sequencer mask + out dx,al ; Select the sequencer mask + inc dx ; VGA Sequencer Register data port + mov al,1 + mov bl,al +.planeloop: + pusha + out dx,al +.loop1: + mov cx,8 +.loop2: + xchg cx,bx + fs lodsb + shr al,cl + rcl ch,1 ; VGA is bigendian. Sigh. + xchg cx,bx + loop .loop2 + mov al,bh + stosb + sub bp,byte 8 + ja .loop1 + popa + inc bl + shl al,1 + cmp bl,4 + jbe .planeloop + ret + +; +; vgasetmode: +; Enable VGA graphics, if possible; return ZF=1 on success +; DS must be set to the base segment. +; +vgasetmode: + push ds + pop es + mov ax,1A00h ; Get video card and monitor + xor bx,bx + int 10h + cmp bl, 8 ; If not VGA card/VGA monitor, give up + jne .error ; ZF=0 +; mov bx,TextColorReg +; mov dx,1009h ; Read color registers +; int 10h + mov ax,0012h ; Set mode = 640x480 VGA 16 colors + int 10h + mov dx,linear_color + mov ax,1002h ; Write color registers + int 10h + mov [UsingVGA], byte 1 + + mov [VidCols], byte 80 ; Always 80 chars/screen + mov [TextPage], byte 0 ; Always page 0 + + mov cx,[VGAFontSize] + mov ax,640 + div cl + mov [VidRows],al + mov dl,al + mov bp,vgafontbuf + xor bx,bx + mov ax,1121h ; Set graphics font + int 10h + + xor ax,ax ; Set ZF +.error: + ret + +; +; vgaclearmode: +; Disable VGA graphics. It is not safe to assume any value for DS. +; +vgaclearmode: + pushad + cmp [cs:UsingVGA], byte 1 + jne .done + mov ax,0003h ; Return to normal video mode + int 10h +; mov dx,TextColorReg ; Restore color registers +; mov ax,1002h +; int 10h +.done: + popad + ret + +; +; vgashowcursor/vgahidecursor: +; If VGA graphics is enabled, draw a cursor/clear a cursor +; +vgashowcursor: + pushad + mov al,'_' + jmp short vgacursorcommon +vgahidecursor: + pushad + mov al,' ' +vgacursorcommon: + cmp [UsingVGA], byte 1 + jne .done + mov ah,09h + mov bx,0007h + mov cx,1 + int 10h +.done: + popad + ret + + + ; Map colors to consecutive DAC registers +linear_color db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 +UsingVGA db 0 + +; ---------------------------------------------------------------------------------- ; Begin data section ; ---------------------------------------------------------------------------------- @@ -4308,6 +4721,7 @@ NextSocket dw 49152 ; Counter for allocating socket numbers A20List dw a20_dunno, a20_none, a20_bios, a20_kbc, a20_fast A20DList dw a20d_dunno, a20d_none, a20d_bios, a20d_kbc, a20d_fast A20Type dw A20_DUNNO ; A20 type unknown +VGAFontSize dw 16 ; Defaults to 16 byte font ; ; TFTP commands ; @@ -4364,3 +4778,13 @@ kern_cmd_len equ ldlinux_end-command_line ; end_of_code equ (ldlinux_end-bootsec)+7C00h getcbuf equ (end_of_code + 511) & 0FE00h + +; VGA font buffer at the end of memory (so loading a font works even +; in graphics mode.) +vgafontbuf equ 0E000h + +; This is a compile-time assert that we didn't run out of space +%if (getcbuf+trackbufsize) > vgafontbuf +%error "Out of memory, better reorganize something..." +%endif + diff --git a/sample/Makefile b/sample/Makefile new file mode 100644 index 0000000..d38d5a3 --- /dev/null +++ b/sample/Makefile @@ -0,0 +1,29 @@ +#ident "$Id$" +## ----------------------------------------------------------------------- +## +## Copyright 2001 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., 675 Mass Ave, Cambridge MA 02139, +## USA; either version 2 of the License, or (at your option) any later +## version; incorporated herein by reference. +## +## ----------------------------------------------------------------------- + +## +## samples for syslinux users +## + +PPMTOLSS16 = ../ppmtolss16 + +all: syslogo.lss + +syslogo.lss: syslogo.png $(PPMTOLSS16) + pngtopnm syslogo.png | \ + $(PPMTOLSS16) \#000000=0 \#d0d0d0=7 \#f6f6f6=15 \ + > syslogo.lss + + +clean: + rm -f *.lss diff --git a/sample/sample.msg b/sample/sample.msg new file mode 100644 index 0000000..5a8602a --- /dev/null +++ b/sample/sample.msg @@ -0,0 +1,8 @@ +$Id$ +This message is displayed before the image. +syslogo.lss +This message is displayed after the image. +04 RED 07 02 GREEN 07 01 BLUE 07 +47 RED 07 27 GREEN 07 17 BLUE 07 + + diff --git a/sample/syslogo.png b/sample/syslogo.png new file mode 100644 index 0000000000000000000000000000000000000000..45b4b5ec89b22e9d0ac066b75b31b98a1119cf69 GIT binary patch literal 19847 zcmV)YK&-!sP)C&;S5q>&zp7fPnD34FCYv006FbO#-WQ3jhFy%OS?`001BW zNklYdGE-Pc2HWGZyaW4SayfN` zLp7A^?Ne@EY#^d66gK1>kqr=Z1f((UInSm8c#yli(FzzrgiPoK2~dJe@I_Uo+T-mV z_yBb_n*iG8-%p<>8=7K0 z3sVsUb)8oz9N^0YkTZ(KPmTgGnBS`oaCUYRn{BR5E3w{5QXq=e2`pA>SMvCR)@rR> zLJd_#jc$nzMc~nWQ1Ctonof6RigfTx)V)O-hXBV0kh%tdQ|H)3GvAu-HdED;Mzd9m z=hl`dia=RuAuTdw9Z5$Lds;bhsS6Od3k?Nm^7GMi8t^Cr96!MG%`u<@&wbRyvR%Bl zPA^g2LY2&Omlv}Y`CwiwLc`1*D#~TUd~!+bHWc244;0&e1MoTcjU>Ra0mKb}TWj(} z5-VYeE24`5bko_1sTiTg8u`4Yl?Z<8XhE7Tr~-}CyfmFEz~`@V<(6bWS4HEEzaau= zlxX}$65#j&0(aQWp6};3g(iO76Q=f~f!mB@i57i%l22zZY6sO+O;o5D8K-Lv>EI#_ zZd6^Op;OH+lh(uAvf#}-AUQ4)KSu>PngGWRkjvta9jW>6W~4;w-C}5X+O)T*>vrAy?GQWzJz>m*`(GKD$|g83i1p`ihP0SF*~sC{P((0XFm&4<>1!2qQp0rnB#_yLOb{WwQ3WsxeK6Z6B+LuKxw zI#nSXur35uAZ)0(09qBG;=FmvCqS$HJdj@$3+}_uVFjZU$^xhYfE=EdtGUa|qpLLu zCla-Ds?eiJ4iPk52!~AA0_gnfQ{Lu_-Tw^|U}IQ-{RDUo0QcjhT#y%*@uMr@)60sI zQ`btdOac<*;TPyWxM4oB6Cm!h;65EVj{u_p?8k3R0C5YTRBICz^5iI!>BlERX;hfR zLc2J>ENOZt14*!9)>{1mT2~p!FG3aAm*3a{)@yXL-RtE?#D~iCN~_naWq=(+M@%Au zE`a*YQ$B$9B?cLA1b}@FcuW8(8=$~X;oYTi;DhC8Ho3(wPgSQuMMxndHYMl>h(`k` z4GXY8zp(?P<>mdgaq)vi!%FE?F(Iomjhh5zQy0Mi9ks_m0S*K>K!D=`h}!@U;wzPL z@&kTgy1aDIRK=4O*u1s~+IQ~*=s0!B{a4Y~R2S8%{_)v*Y$SGx^q^a~)LGO;(w~u=y=s3;WjPdas z1aKg~aRXdBxh8@W32d3qQ-Unx$Qe6~I66ST00#gZEWmL9#2o;~>OkBjflUe1y{T9i z)`WFE&VcUUYs29H{rp}zfY)2%=SA)~p$SlIsF$ZdfJcJPGe!hBnBN!xQZEkRR8uY1 zlhyg8QocwgB`-m80KfnX?hi160LK6je{ldoRoFfe4$D*P6S)Rem&~ZNyCvg1J~0x& z2>iy-5PYEkF)W8+l6*m=i=sZRsrU#wyWxoe7TgzL6akJ7kb1!YVL5I!j+9=Js~c@< zw-JXXBMb{L3cv3pKwij83YCxriZl>f1pC@>5Wqg+tVjYJ9U%S^6o_r%RJ)=IxOM;s z*|~MW6;=(i;cEdnvKM(N05Pmk?&gVJJEu-C>0&{)2$FsL@Q?tb@f#H&^^yQ$O9#ty z>x-p)jNZrV4Rh#3Cm1ZjASc`hU_=3q3J`x;0I?+unE%^746p%Q!*0a7m)V4;yJ0$Nj40cNP0BJ>dK4=~JzqgwEY zZulhw#A?laD$~$-vH-Lsm?8{`C=3NKD!&l{;x8HCY+03sL_?OP9$9Z12$3Uk9P|nU zq+T{afH0Y#r{#shf=I2PluKFQDK|k=f`M*0q!Ns5!QXj+*ut`~d{WD*v6E>~6^i?r za-;1bcwGRM3v~IZt3$+J0f1O9xioRGIJI)j)pN&Owp}`&R@?*=!`pBq@ma1ae??zR zy%GSiS@=(8PMxS{8*{wCPpm1Pdhj{`^0ea?;@@e2dMReJ44zGM4Uy<+Jne4H3~R#? zEZF<~R}mrpDgneUXfm-sQ8?y`vunK3n(^cbjt`*XOFfJ8-(`T)*zEBkmr69G>Gk3T z-B8RHwL4WhvJDT^U%;d0hvw(C;FqdEqPSSPJO?l;vPQ~Ah|m$-8qS6X@e54HtG4RthB1-d=-Guya43Kk|6|6! z{=5Z)|anOi@dcJa^HMG_iZQRBs#XIZfdV7@;UEFNS^(>_bXLkV z#QjPo#br}OQdWw1s3VCEFsK_Bf8%5PiQeOhS_!_=0OR2Q;y#{Df)0tM9pyC&XO526 z;XH{soB)+R00WwV?h?g@gDv<~0*GOk=j}PTiiJMUSf99!_X!Tl5djXIhaUxCFuzv| zAXdZsy4^x5x!*p^afP*Ka zMgSOM!LJxVP&mH4qI8qS3O?pI6Z$BCU?eXR1Tc;{)9E4r4B_{x0i2k~RM)$;>PbOg z!iP6jkkX&lPf(5m(CEpzQxM}{ef^dFwZAg}vGsMjMlE7(yihk1FmXgs|1{xCSBR{@ zILCeU#PwA--uTRXIT&D=1;26tv37Mal>x135>AnY8l(_G_qtF)OELDT1mT$(ES~$? z@w8kfKJ&Tx`|lD!Y`R&wtm{J~M?Eyw*^gipfKY+3uO0u`l3@JpN8db&fBaMPSN^IN z{0ah$XAhQ1Zmv07*3?D;GU8D^XngF=U5#MFx)Zr`gN%P_5R8BP2$Y}3ty*vpz)%6c zf&j6p#iW$a9;X_cJXItYv!$lK2#xWvhoBsx5`?GSc=YBY>|+=|1!8>d&4&+fK715^ z!*nZy0EY4d08=l8QlAoIrW55dpDkdA1zBB~YAnmBJ>y*;&nv-D8%8Gl&BL3Io*0sg zKYDcY=FMAgKEcKT@EWK5U$Mlvlck9XEVi&*%xo5x)_DA2P0r;h(-*rnC`SS~@dyBW zlz~@>W3M588+Sj)?igP=0ARQU1AtTMm&7T&l#L(di337jBQ_5&<@v=G9{02d>mCXA zGvRL@-rBhN=1=43{6`M~zKxBWkLKcr1P1^N=ZEURQCA%sdy$Nvg~d%?Ru_x>VVhnr zozPZ;(3QkLP=Y{#@jtwI>+Z&zpQE$mk8W+Og8yzlGQIGiG`9f&U*$4YD;!nY{CTR- zfXj@MuGoyB!GSgmnccj_vaA0sI`_4Q_gGL??>@4cHT^@XeJuEu2Z&wt^7+GRlPBSd zaJZd-=^!W%uwkIUJ36x;pi6!XUvJ!FS8x6k^IQ4@?8DChIF7Z0LFgK-hB9db`?nu!o2$__;+<|0B2tkpTXt0x~$?`!o?BaP}PRU zqr@mEfQreo{j z$%VPZeooq_Dd|{Kt^7e8CrB&pqrU_zps8{1d)POBc#r*;8E|Ewz0W{XX6c?`(%1li z{rDLGCk|c)q<&?hq5qtwkGlz3s+Mpnt?*rQr2v9a1eGC?A=?X8huQEZ_S(J2@kf90 zSM0xh5`TgL=>hlq@Ux$@tLDhkC;*dKGeO`ljZ|34;>(F6Zhcujsw~Mu?_gTf)Kd0f z&De#6xr`q)coL;8I3ySbFt$NrAAkNj`={ict<10QtpeS=_SuhE)(mL%1K8Js0l=En zj-AKGvV`h5%k*Jlagpn7X35gILepEs2~C&lTeY}?=En-^A$8eUOrcTtK@vO%3d{hb z{So^n{+n+=D`egL4N#7lW1_sZ3RC+qX%)`6ztO>%)EvpDF< zaYUN0p``+ZN==-{`NcF!fNKnp;3hV64-k9w8c-ldQh$B#hv*wVMy8C)C;$a6Cn_pG zwqR zu;Hlb%0hC01kbUV4bTGo*~j-jzk@xVdCdSg6Ul@J0wfkRO{_6XbnK;}3Mq3Hy3o)x zsXEP@d%D!~xPlh|R4&`Ql%YFeG@Q#g{78@lfdYRH+(kV0gVX2FpPt^irJHax1@`9$ z03Oc@f+nt=FCX=Nnn~Cd>i@tI4jHaov|9}zsd752LfL6>FQyW=BAnn%Zu)#qQ_!e! zM&HLo4woRP-+%tE!1ZSC@7#ZIe`oKTAEV0yfP?G60Rn_;s8Tph^YtyV7c!j;6;>~| z?bi-yw|$4`@4I-i_B)f#BdyChPcdJ=SO3y@^&w#Mt^SfOtV~rWl;UNUGG~)C`bzK| z!~Pj;@;%+%-Mzp4VCTVe)c*S~qL}btfb}|;C751pC5JTz@zWpL`o#sxb%^!8Ny+tj z5J2{}^8(iCto=$5J~3V$r>l5Us;3tzE3hE-lORyw@7?exiwsWckL7(j$K!hr=?Bm&PxC<6Db~?%nJ?Z4B#f6@ zFW=)dttIoMIT=Ul*P7mh=K9~vboQVE@89q2>}~^qfZva;2fnHR0YFWXM2?V7l9wu| zw?hSZ+w;>RGpUpC9^y1^`#_iFTlVd|ta*xlM2t?!U%(e1%E&aqt9NPGjFx}{VGa(> zX%P0V8$m{V4gs#7cD8{4@1wH2`~27U>}KFd04soCow!`4F0>H+nT*hjAb__64he86 zK7fu(_)anSPZRVfIzY_;=zKC_%eA&bm;~WWxqtgdz{3OMsC8-VO$M+e_FyJsvw+L~o;9qfej!by0Bcu%Iir@0B3* zj(_!wvt8YS4GnHTdv-FkKg2_h5zb0op--3NA>FMoA_i~s>< zFV&KWZ}xuQXqWFYBO54FJC5;pYYz5?O@` ze2OgCQs6U4aQnG+b62%sxSt49QNfF)`T@S*EN5vy!2tkoUmrkhA-5nOBS-uWo`vl| zmjE#@zz_)nfHR#l%Y=U)DexJn4s8jJ01&4cHOCj!=CpRy<#OHjv9~efGCl8Gc4H>= z5El~jLpM(UDG2aXrM!~jD)8k;tsVzzK>e;sd+A>{z~CWH0I=f_;QwT)aC-p2!4?bw z;HEdnr6nvqU8(Uc1570E&J^rJ1>S#f`fP7J0O7`(nhLsf98On6<#>6~ zZN#jPh5f9?2mV9)0)*J@Unj!>PB-OJGWjL^rBG*C#aPzEu}ql&xje+=m1Myln%tYrH<~Xl$xbp|~jokY%m3b31F=4=})pd6yH0)(bks&z|k=*$NEI zQH{XQ1jqn_swCB*5li*;W4Y)UBbf}x4P6Ue+C8kOZ)Z$07elY0GM?GL=Hua&x`YQAHds~qv&r;+C;pE z1l#m&^Ft@%egJ1@lQNaiuimhh{l#(bGI>&v1QiQl9D8c@L!ba3Jbm`;Z1)T{q^G_b z5g-Sk8360Gv`}e@6C{y7o^}j$vVMXlz|cd602tH^v;elGW;gXC_}e>G7?u_UbN*5o zK!4gaXa}C2KD7bfe?Ifz!F^!Ce*@0{_z}$e#fYm}Fxq3CfOVjtwZKiyFA%9U{)As& zW?FWD+MwgLP~Zq|haM6P(E4x?K=XC$aF%E0zl6WOH%)O|b{*A&aN9{!fd2XHD<(87UE(dQlU8xmaO~FQp1QnwW{PmlV;I_?g_pI~h zH#dHYGR_};7UYJb1H>6Mc~YpYE3?gNvLO_TUF)g$oloyXG8tGa+K2Q7=>7nBJyD3+?nuPfD&!F@L(CPlA4c?n8zG=s#uBb9Hp+`^EGnQRpUnGOd;*G?`uh z)Mvx8$A~fP;obkP)9F0xJOJ&#vkvedoj>2$xO*1@d_$L@&xVHp2>NnTZT~<^7KFom zE^yw%q}PU7AEC*?0B^ehPPzfIUVz?9-^L~sX_ILt7Q2_ZMwg~=$4p`=OoEyL@b2@@ z)7|?!+t1EGr=$bz7XW+{oP7rXeBxhMI+_I=00~;q#9Edp&!^Xq`GugNrAdzsdj;q@ z#K(6s1mJBKz}wEF{Qws^PG-^)kCSy7uBTu&s1toRvWEbFe(UC&PdlJL0vgl+U*|7x z-U0+~-I{|L{Er^N!I3Ko&;W?S37{vJlf>F$em-z?b1*>61JL!c6QJAeMgYi~SI!FS zsYIi#FS+WNOWaq23RK{&TQ@sTI}i3CzrC|(aMr^;KoE}0ee>v3_$BkB0fY@{pux&H zaZvRtaMP)RJ^&quL;+~Xv|l^g{Oz{+2ELG+lX(ibV%b)q%8^~3wMqp{ez-p;W;mBm!E zwV<50fYmlN)u;$Ltly$CORx^yxO?l(=csf#z@Ts4LjdpE)s?#?7?B?U2u)w8G%vCj zz?h3lN~_kJU562)+g>{v4xpzF!vfmTfdHLH!|TLX4vaA;^PQt+R-C3}nE}dMCh-JZ zTLyOQd;}dv3{Ly?26VdrC7}28KmP5_4bTSEtJMuVIl(Q#=m5JlS*Y}~m5iLGX-2Ic zOQLJnaCF=2`9hyc%3m}3KXw3|bPFv2p#8ThZPg~-J!eqiwWb%6GEXzTGA1XRg3w)0 z^K;=wd<6awKfed~-MV}8;iHE)fdjs^VE|nHr}mTP91@Ib!2qD#BMMSYJj|@m&w@YO zey&wI@&QcYiG|St-VOp7)N-_6%ZYja70#kvbU$1SKo zfbrfv1K_F+Fg8ED1?$0th6dLrsO6M)bKA+61o06eaKd3Am>xUkn5G0vg$f`_^FXd7Vo}$+Ep*nM&#)emd${i9`fuQ^V z0tCLqsXvze6Gy*m_$pAJD+dXJ?y#VW-27!NU99idCGq$qCC*>Q;KP)QUFL#>d3x{1 z@)Isn=JVRGZhHXwD@9L-&?`Ip;6!V-3g6qpnS2E$NKYr)({1_^S2Okc0iP5UvLGn} zZw-=o0$UK^Irk(U|2{l<6-f|Su#+GA1IJ2?Q&$9Nbms(3YUPyL^i)CC6fwC~pQv2M zzXad$QF*Dim4L6dgj^PSH75@nn~l;1!vk<~AVBNYW&SN-01ePXUnqTv-sQLC`OH2c zikjAoEhbhb$Oh=sQC3*NKSH+z`We60S=~a#&5vDmPBG$#wP16`IwHtus#wk^=`C&( zT&PlOXh*qA6@JO3L@;n@?7ca>kULbo4Q1;W^T8)AFeVGPt=@LB_qksC%@$OB8(>gt zH9f;Te%vIdwf33<>YQYjStAQI&?|=1h^@Gcdyp7zBoe=6utGNM0qDr{wTG650jLL^ zVUL&=leJuF{ve?VMI0yU^L%+$LYB+UHqh8Cql&TI{uky~-}XGZgP0`5Is(W-Q-OBSk!l(n{zhal|6!3iOH+1S|d@nip$1K`B4 z77V93pflqztXesk>YbciFfxtOp8&-3s>;}3^)Armv2^*Z^~P=Iqg(HU17xia9cQ}b z==gZW{0%&k{n5!G-K6vkK^!z)mlkkEsG})2x;JpA%Ajn=e{7w+>UJQgyyF09tgAm9 zKtqDiji@!|sDUZdJjE62Fx4ZMXdESfWPTGko;j*dF+DFpcRb$*&^2H(84A!Qh~7$c z&0nE~zHa`a6_S}0Tq6|DJ!FnHF|yH3$}l+SOn5U19>I5h?t|tm*0gn4t`0Ds1#Lk| z%%&&S()qH27vL?3wYd}e;xGlj=RG|ul&DlsRt|DhYEE{|kah9Aa+!2o=4duaF2|$_ zsT7TjUM?%uE9cYn3Srz`mN{DLYkgTqLh=(IX~( zd6CGG*`-Fk(1q(+qHpJj%{G;k(BhV$i6X8n;as+=QnSeeF4d-dS*vIcZ+{DR^+oip z9fq)A7eJVxS`!xF7G?F?;j%HT4-kqq;<#v3D`G807GRrupJ>$z*EUT%gH5koT=JO) zXeV!7sLO^$*0ah9S(jw<)-dznsGd_<3@DE%v;D-mO+c5OHjL=$K z?vii;SaDr8lbb;Eu)35;>Jv^?aZT*PB(5H_o|(8VeyGfL7rVt=C)^U`$5ldT-*BT1Nf%+HD5`jjmW|Yj9zHEYVdl0O2 zu-HCagY9WIL3EjqeJwvv`JwB(Cx)s5b%4-@;|L%jE@3ByhN35t(S&)EZCp8Sn8{8W zbSBx0dXHH%#80?}p++uK>&EQ)sq~4uIKgrChGn!`y)r%3)Erv_qd##y+rkp_l$HFe z6NK%A_&0+9uDWY-{>lJRcTUZ(74&_zDE$a@kFEWAMzV5dVK#71CK(9Yj!l5ae zag=k$7~7w|Ao)bw7{t^|MNQ|lLet?aVHiZHNY(hV%-ae4kl-P@$Uhro!frPVS~6Dx zh?-e2qHwvHk~Cutaq|vo<^tFM>WoS7K#;IpuZ<=sCMqZ8gIP=-7r^G6lGOJiO!b;6 zOcau)+ko5ztw%RqRXvKuNx6llK-+Uj072cwJ?sZ?b@kq=+YJK=UIk#B(>rf~kfaURe8B~anuB^c%rec z=89{`ZDX&!9VWzFITN||>*C0xDZAlA?~c{V1}#r0|+_Rt1+Z)4T<8kKwOpStgW7#5%< zKopr~Dr$B=-8BJ{W;e?H2UpwYayeP5tdJ`!7a1vgoWNH2-h~Lhzu?i~Fg?62@c+xQ zCe$p4^*6P8cNW2uqm-;6(>6ZQFL~!CAZQ40V|CTkph0ir z)~#FY58XYgxciSY5FlppL;2>QHGR-rHtv>lm8^}BNs%O%OEqd#cYU2&!`7E&70Zfg z;7X=04lri}+XawC1Hl35M5s{Nb11?6Vy2<8Rjionk=^9dv1pB_jYTfsx6HK>e zTMZ{c{hDt)ym{-EMbI|kRX9+5^Dc_;f6x7A%nb$5!4C=$m@v1FZOLZNgncJ29TE(j z=$@?2YkaBQPG}mh2W7CU7 zy74V5H#Kpw%e0ktYP}%I0HFEhBxlW)vl$XhrMjYVNi+=t9%1|uzq#qOVP^%X>kklQ z-viCRukD+h7z&`%I0@8hUQ1jMD;3`SGdo&I4uk}nsGTd#xA}$R*dYy9pXr@1C8xI< zlGvJ?f@8^B=Yaqx9RSTwFIiy|tMo{*rxKS{b++^^`wnnj7hRPQ=mG^gA~rzMe^bbM zDv5bQon1rj1{|gXjQ`oqn_&&X4V3QzB=|$PG?`<3lfokxI8%vP)EzfaU%L!CaW(1^ z+(nV}@iVk)5fnhzxj=47`3efb;*89w>kWCnOUUO_o3$kx!-VsMC(jb|0ZdHM`;+Vz zd6Z4a2e`m39#`9`_hI~uNK4F`TFQ0 zAK~4NTle7Fs@bw-gt^nvWk7mK{^U3;KrOZB>~0%#@#@N*%A?U@T&?AE&!!6Zqp zUdt{Cy*X-8r4qG-I3;i8dAzv(B`Zy`b&NF!*c|{_7K^hV%(CpeFkHI)Ez440uph7= zO|7TC{E&UG@CEzP>+Cykv22@thh>Gg*muCMc+g!LRS->=xT01|)fP(%ZvwpKsP}v# zTtx%zXd%Yj+t#0D2pgWmgmU?SNVJWxL2ho5hHJTX4S@c5RorwZ1RRZ*a*J7osGkM#Fn zd)U7xw+c0gmc^SPtZFbe3_vx1!OU&u8?t)X08PNPH0X#_IT_Am3A|IQ)1o(D#pEKK zxgikkxYAR}Qa!Fwud^Q=v+sZ^4PZKVjVW!h@3miN!P{T5`M2JkU_Y2* z-)XXMu@~A&oh1>#FD3AUeJ{(thXB5Xv+r=Au7Q+td`W&^nR>7pCcD@MbPa$1QjAvJi){6)2awz`(LeH@C{iH&_RUt-2NJl zw9s4uZJ*iyfs^Bz zN-GY#!RQlWt53XMCkSdmRa`F$q%|*6(|Wntr8o>F)fRZztYkn9Hp#BdI|1I-FJk4r zQKb~DzY4f^!(Dn`0M#DZMgxY58Bw4vnJ{K#;B+FAEpBWh>YOL|9cC$+|vh zhD6GK)O($+G|UVS9iZ`xjxzzS0AR>5oNI5yg3~B(x0N0dLtBI!!Xb93HP;WbwijisYlO@h{C*D zR$wg@!p{K_9!-?V%|x##J0dmEvFO7W20`}2FWGFVYNowlK7cI7#=d1g`2-yJz6ns$ zGyoLXGz%TaTkitX2EV@3W7!XjHo!#K9fF4eKIBdYWu``v;Ksf0fg12_j(B_(faaZ` zzZ}7|a=5i8a$kn93sPdVL(s?2 zW!)>i>x`Nb^!pczpdMF@$?5~{4;=F8z%g}4`5{o?&%Pqx&I}FEWvtMU=hO5c0b01T zi~EQEVL+WAj9Y{59q=@2ytKs*idHudS{DfoPGYr&ko@Cgz^n6Vyl(}gmj>L19>e~4 z2!Pxh-`topH$RNrnVZ8nH!JYPMJnV54c{O-4$jJy6`gYur1e&fcu3JgufER4*@0;w zqWS3l$_qRH<|bip|Q=5|3h=qP9|+I;vG=1EBR7&Tp~#`R>Z% z2mpd^Mf_fLfIrRt=5vmVnfp5wBLfV*hfsDdhWmC<(TmdF0 z>MQKvxND5a6kvGGf}RERK{!mG-C&n{{Qw%7z8?<_Q0r475fmLFG#O?M38DyBmMG8e zGshA5fznt=6HOW~NGL=`o13gVd%qC`c!c^P-i~lzfJTbZgt>z*H4cE$7>aHYnu$tq zh#8(=TTrwvvs7>%5msVAgj*u12?`1_>VuS|CweegfB;||AEp&(1B{zt>2U#!#IWuW zAqs86V3!O&;t2WpvUo5(Er^2|u1{>`iNn;&CIKFn=f}k^-%L*Q4360WgXk z50IgcU>uGzGG#rkMG?TDg_BZaP;)w&Yo~=pQ1zwsZGPH3ZLf3}5ukRCRx_6G?0U0~SEoWB(_z=U;xaVy6tGC(7CXAMk7DG>>xPMscJ?Qu+{hp(S3Vi?wM z2RrCxV$?x3(Wa?}2@rR-1p5YwP=6Fufw{+6{I7;H;qRfV-?1v`XyF6|&_!?*e#g7g1nh38v&rs z53XREe~iVx?;$iGN5KGSHME9NAnmLOqcaROVvC>=nL*i@QjKGdGY>qT9Czqbm3A?0Y|Kvi4wLEhX;C%coIzOyt9SPcm)?pfiqV!;UI#MY&lGVCP6bg zNLTdT*UGc07Ee-HA+@*_u(SItHakyNie*06IxZv?y(xp%xN~%f6JZiG<8e?!xu0Sa zS5jc!92t(7-eCa@A{a%8VFcX(iE^!8&lTzP`C>Iw*e}m<)K-S-E+w4!64(S&i!%ot z)vAM^HJPUu3-$VPmokhv;{xcDpm9fN4dRaCFFApfD-9-6M zq(!hEEJ5>rP+~T4rg5+0A}R2W4X`*Yz)*q%AiCRyqLZK*;YYJis1$#3nCvZdX+{yW z8YNw*Ss|7t3+Q&mM)k5HYwPt~LK8|noj%}HdM!6mP0EU!U_DTRRzO`B(p*3t7zLms zS$}8+_9fW2PE>;kT7yjpprE!&wOGBIo)Zs&ITG~cxp>KyX1RG$XzP1aFewHav5}FEa<*Ev(gpa9PZi)HwfR|v zW;8LDKChcChbg9#s%ru*5Ep2PhFWehmF4m|by+s|z;Fx;yCkT&0LGtu{s{Zy?+>Ry zG%Oc;Yy-TC0wWR(h8SSPIzR#qkF*-8ETke7&@s(r3iuXvqCHzRLpZf+n#ZSM!*A;V z$*aDYY)B%(T`Z$naI{I#CqdZ_5X-*t8TNbkhEpIK6nV`Nwz!f42UdjrAX;{8Nzh1S zrRj>)qU&(wVoh6*qsQ%$^%}=5HtM;Pf@#E+c(>4K0B=#RspyKwLK8HlHK|7RBw3Ga zL4rOBY94@C=27PNhO7gT0&mz(ING>e0Kg##`WSi$?xT6|L>;g_5H?eKD!SG%exj8F zn96Z_X}LWQZ+TfPE~aD!E}NvMCJ0)ussFrO;=4^i{lHxG*acAb0gQi>8CHRR;&H-J zdm^}>ATta?4?~v`@5gbp?_Uy#ZIhpujg=ydKM`E|nYxfI%tpM!KXaAWO*Z>p$C-5wayTc8uz#xJ{nK3F}5t<5A*I^x&uM!0c zRbs~X68b()l9*k|_tM}%o{MvZTrM-czffSh1$~hOJ3$cMQtvpIEy5WAT02KNBm4GO zD}o6Sd-%sgn(+6q_>G_3h<*L_SKP1w$3oB{L)9b*>Oi7GS5xF#HK}QwYe5lxi4nNqeP0_daM4VCQc@U*w^e z&;S$u9(E@Mx;k7IAj}L2Fo+;C3POY6K3tLOV5>moS`A(w+;9(_`@Mh_@^;_L^ICe zZ+|*e9XLLMwk4~m8iWAF)|Mt{a+9a+G{3A#P-{u+sXE*jHOKUFN-ovxrZ_lNDJ#qN z$`@988)y+Ry#}~kazWAwHvD@EW2d{jyL*qZAx(HSleL;Ku}5DGslf3Otk@zHVM{to z)l~*u>yW41d8X()HwjU1SJyeBye1zNE*5DHy-}NL71zvdAUOwmh67b&Sw7FtthZhM=%nV!Rigmf=zxEeIMLi;6|b= zaCLR{pWEYcpgsL*Ci1A9^>S7?F4l=5?lh9yAj%OSm;-Q8beuX)zJ3s>OkHemkT(FytbM$|NO z2f#pr%+(NDW?b*LNF$sWWqpYTC*{Oqvm{s7dmrfg$$&ZYR>{Jyvg{V1@DE6VyW4vh z_Kn+!!xaem?LKe-ypf8UB<%z^PJ)&QjhsM7jL?lRYaxWYVln%NQ~@r!X!Jn><}ACe zRJSbH`eL||@HY5w=a=!ETY}*LAHXy2+W=!G*i;insC`lVu4Shew?uvxZ8p~SE^e+*!tH0{%mg-dSUR--(Z}pEf}i6 zKRVmJ|Lp$%Y=;8xa5K+#?*HGz0~{|w!Pz7XM`*61g8C)7-pNS{bwkYI;6D0uG-9mp ze5!Az4&BH$<{n(PHevCWRkZW)o~^(P_VoVl&i{A?fFT60YQ`0-XV(W|+$300>sjWg zl&clt#)Sa@1Na44@R^Pel*d@i=|@5p_yZu?`_KN;DfVag?{EJPR{?k}1Rdc8y95wi zX{+sXzQD{@{(lZPBK~(* z0vJY+xgtUbL9YxQMw~_8%xFE(BWbPhTpcZHj0a{FIpk*nwEke7y*<>3G2IAu6JRe`(Pk72iVFu*^025~zSIMacfVPDOJ$4{{0Cg>8PB|$xl3$7(450{m)Ovl2e7#bbM%2T*`HFUvd4TvPTjchpn*ZnPcL$3qD`A?tDJU)F6Na{{}6o4;` zAVR1+VgL|sc5qUvW-+YM%#m1GVxLz?2g-w)u% zt($wh;6Jo;Go;rsE)%IU911X;;Aml1KLca%gv)Me+EHP#B^)$QjxlLnSrN2sbxl(z zNX`u3hXL%so#&zb8qcmbWKe$?7Vm@ySGffg2+u@&uOohXZ)SJ<(~$u7A$TPb_8}hleq5no64F8Ch-~mU=i9s01@Irt2#keKSK-d?b8L_i>k0%CJnQHp zJnNX(iQ+~203^Z*UP**~2uhG3Q7qM0G?){k9u}DxKVO0#Leh>4O@`_ZaL=mz91KxY z=7H{5bKyn|0B%6Zoq>x0g!ZLCf3P?bz-uEIG}B3}@54RaN`iiEwYGRrXb31O$iM;l zR3dn4jefy17d;fq+D0$$Z|gQ3|0Z05ckkXs=R<;L2%+V~|DVwS_9e)SpP;#_BU;>6 zoaNB2nMOk<(-&Z8*IjnZe|L8GjJ{52V-T)F3;Qpq5n~OYkZp)cO;& zQ>q0`T$?Y*iZ!em0#G(h*jokay^-ym?LDJ=5$;ET0z1frbrCxJ(C+TnBLeJC@CqU{ z2?o28eS4MamBp1Dx4sVenG0_R)`7BN!cOsRJO14@8Zw|mcP|v+#?3R-bcXN%Nchrl zLA!%vssjM_amCj|(Ciiy6}1{`XgqH9hWi0@o3K#898us^}!&A8H!plf$0K`pGcT^rwqPVQ2T7#0eo8ZLN8*B|&t2RIc9a21$v z2i1HIenwws4EPh_KR)HX_!@@;Yzm6 zN-%sKvW;6mhV5{@@-t%*Cc|B7WPk$*4lP2h4?)qIB9?_)rLM2Y0&v3C46jgtzXAf% zpBaVnQBQc=q^LJ!d^6{41#bL7r(;BM9F?hAi55o&NDLr2tO)xNv|_CBEM4i^a?VO#N@;h^=7rh$L9f<&NAi*I;Xd7`rMQ9UT z@8Vpt%Hh_Hi*)+P-i6mO{f6bKfq>u3bZc) z%3o3=103W?hBf0p1VwwG1a1kDlZy^75;n#47uNG{8)+SOTX+}vVe;3ZH6Z%~E_3?S z6N}J=Y^I3x^~4bYMj$wh2rGRE+CxpCF*AQDcFhEtfJMj5+`wOksX)9-u(|Y@=m47JyL*4k1DS1g*>&7?`0eq(XE3r&$|L!~kYSVzw%ji;grNXNaU{`2=#`*t#-f8@mY|Op^d$s+$uSndU+5v}9f#GLH6i+W_B_yr z&E4tEzOVz@j%C7ozZ@gLs05>l&__`76GXFdstOz!vD34B0Doomg}1HoINKCq+D6d0 z=G}}1&~hQphU7MqW~1V5{xE7A3*Pn_xe8Qjxd#;s_;0TNq8k_o%X+-8SG3) zvf~&W-rd_i>zv*T=Qm?2(5y1I?NO=Sz5iGoE5OJEBO&w?R6P>hk1@^TS{X3wrhGPR zon_>unzf!`xRzVq+wDC0#!K+Wc0T1(rvfehx;y&2{``gqNJJ(W!H)e#Y!bB06(dRw zuE1m)O@7Xjpa-D3YgJ*}NQXOSXy2&FVD6vWi0^)C&!Cz)wFfgzH*VAddwYX+tREWS z5CkKLFo2-uHDb8^Y`r1y_DTu9nf{$U8{w{HhL#%u<@5<|1r%2AzUf$A2g4p43fwVO zw_|#vv(6xXR{%H+!NDR70I0c)cpu~7@-nL1k9b-!4t#c2!mjOxQT8b}^XTTSjhl}i zeT}&br~_S9fOY!bFS`S2Tmj%P1P6*RNP@Z-XY0bct0~iPRe}Fttwn+#}I0?YMIUp#%cWlROr|$-pnWv@#ZR3R}{T&s7#gzaKMQ{+pAb{4Q3ucEdS2|p1lMaG@fE|>Y z;Wb_z1u)@008gKGjBuFaoV~s0Kf6AF!x0={$Dstx#pThKm1VA7Tj>3`M0$jAHX3A_7!2E5!-VVF(a&Xxz0PHGA@8>XYWi; zEQQk?EORu1QV=Qt_&5|GP+-R$QH803e@9;{Kw>z8eMQ)xAZA2X)7%M-+krus0)GYZ z>7Hb7&)cLyRbW2_A}{PvE~*gzzb@_HvT=+6hbGuhguwvOnhWMiqOd6gBxpqU6CQx7 zk=*Q4p=pi-6=+Ei{)BZVPhT^@p$Yaw*pDE5M9?FKW1MZ2DWel?I00(fZ=dP}JA1&K z&(6*q5oVM;e%fDws1k$(!M`v~wZrT8e4PM?C)mf1LkWr&K%ye4DBaCih}I2ImH$tK za1T**4wQom5WIQ%BwT@yPtlnuMHSTn9aI5cJHRUt3>9HWHE1qc0awvuxO%2g%Tu^M z(Cz^U5$Y;LEIMYbwrB9`uRz!kM5;a0Cp$bhZ}@rv4(W>fiZF~IT)ZcqB_y=>_(`#~ zpa{as0i5>GaIJa=i!2LIEruO4;~u^QRp5*cYl5I?*Z=0A0-r+N8vX|!&6u}KT`$0^ z5DY^Y0uT_~=kWQ96{%gziWtU_^@f~-yO<|@03pNQqM2H{LxD*2*)u?Z(1NGT1sz?t zvpI8m+A#>~xPN1Pdffo8L@>mT!;P3A7(pe`(!Yr^Tv)592s}U6kb(}E0W3?0I*-nC z;DaAy0rd3y`N_-ba0an}v-N(4hh7)r1XM@BSg#Qf&O3EXB$hJgjY4eN#e4Pf}( zaLNWhPz6qf-p=N!;YEz;a{rg(vug)PT!~;H!b+GC>wY8)zD-j(Spz>&Ff`$HBi0GZ zPoNA9Rdt>N3x50qx+>-dbiZh%)M7-YvG1kL56VDi3DT7)4cqb(RB zK~1S>Z`*c^1UMVck1js8073&^bbfaI0Iy0gNQ5B-fhX1pW^qCg70Ln_SPQ}euBE&U z?D)BX@AQt+?~i#pV+j@!A^Uj)FbxnfkJ5w!AF0l|EEnzy4`zJ0m%qUaYZ8u(_?18$?J6FfbA@*5Ao7Xxqv zfnhxL4a`P$=8DSBkF|!9EG6Qj)MV; z<`5l6q!($@+K@mBB&e7dQ+}J7xl`$H!1_%*e)4$cG2`R+q5zIUFv6yG)&R+V9QcvT zE@h2yHi8MdugH&bcP|LwNCfFY1RbNCaGX6UfTpx#gm@6Zk?!q90UV7W)1RPYlyg7E zteq?z^K*_7V!tC9p8#JRKw_lZr27(djuY<_yo5^(?cATwM{s-s98?L858$W-`|UC7 zN>zyC^QFV0mF?CDBB(g7#eY`-j!cjVC+N&Kf^)!na4DId5Tt_$nhE@(nJq(tg_P`w?zsmr}LXh?nv>+ML>3C^PQLHQvUo|*B3w{Xz z$3u{D6O{1)bRQ=ckM(Rf=L}fq!qWVBZsTPD91}s>LC_;XxI&qbr_g>G3I8PQ z?>xY95o9cat~u@czPq#vW7Dup=ab+VEx5lIxi)~~C+L7AB7j+XWg4wA&G`xb4gee% zLE0qflAsQ-($!GvK9}(>1TaPmerW*5PS9Bi!iORhL2a~!GW@P3k0<_}05~>+j84$e z8`;m!9}2>8VR=2t)!Kp}7CDC}`JDkcZi1Hn;I6TBuh4AC_3UBysNQPQXrR-U;25jG zmkDre1ZhN2mmum4qkTDZ#ztoG)FF>nH!@eb)Wb33`tFwraQp;CYxdWoSV-t z;m9}w5*#PMz74_a1~``J7AlCK9nRu#rgX7sO;u12dE8oI3rO&H2jF-Ks^;V`xB-)z z+bS;U{Imr|?$Y`s94JC#i~BK^mkV&r1mVCiho|XEZ$Z|2#Id2kZb{RY%Q6pj2xF|; z7`^bz1~^uNni$X0be>+J(H2bQyn2FR)3vhFKpQX-fNYw&;1Y0qQ+{0E`?3L!mtcm= zB9DvuB8!bWk;SkWoouY@T@sYW%4ODnrvQ$PAY&M@wU-(R10rd(a2r;nsHV~IC&tyTGV3*b0|Ggihgj0$GyQbU|?=C-8v31u%b zC`se21YZe&V+^r62bkjXhcr_@%r7fEy+vi5L!9H2V1Izw7X)y8Vg8CUG`NrBTvltV z8p+{!!Wq<3UJyWIYufJ;LH7U&T4_~fU^PJZ-^Y0KN!+GWruS=3u)eK|nCJLS>w39@^L>I2^zifRGsZkpvGxl=qv3xkgsD zpgz7n76}du@cJ!zWP*&9wxt>pgyT&4EzaII$j*@&nPA^%2?luW2uFP;JLkxrLINbH z&mFNXcszqkR|0t5mOSD!*%H(Vq5w^NzL>G*Jvb5t`IiImnh_GCJ(NR&$cz!e^;*}Q z_h2RaDx(v;GQjJ#U3czcX;V4hVxC!bZ!hJ4{<`KIV z0vK6>BLcimgrhu`Ah=ga(RaGfwm8hYn8&DTG9v@LMoT8H{#YIf0uiDOp65_o&_C^K z1c3b?AsWEzli}5$OYjoZV4rv*ht`C0y+2~I<#+&In+!(-SaFe(K#y*P0uq${0Qswa y4>dM`*Ca#YiVwyF5yUuL!MQ}xfilename = = ASCII 24 + If a VGA display is present, enter graphics mode and display + the graphic included in the specified file. The file format + is an ad hoc format called LSS16; the included Perl program + "ppmtolss16" can be used to produce these images. This Perl + program also includes the file format specification. + + The image is displayed in 640x480 16-color mode. Once in + graphics mode, the display attributes (set by code + sequences) work slightly differently: the background color is + ignored, and the foreground colors are the 16 colors specified + in the image file. For that reason, ppmtolss16 allows you to + specify that certain colors should be assigned to specific + color indicies. + + Color indicies 0 and 7, in particular, should be chosen with + care: 0 is the background color, and 7 is the color used for + the text printed by SYSLINUX itself. + = = ASCII 26 End of file (DOS convention). diff --git a/version b/version index 108a9ad..64d00e7 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.54 +1.60 -- 2.7.4