diff -Naur syslinux-1.62.orig/add_crc syslinux-1.62/add_crc --- syslinux-1.62.orig/add_crc 1970-01-01 03:00:00 +0300 +++ syslinux-1.62/add_crc 2003-02-25 13:52:09 +0300 @@ -0,0 +1,49 @@ +#! /usr/bin/perl + +use integer; + +# patch crc over first sector - 64 bytes into isolinux + +$file = shift; +$list = "$file"; +$list =~ s/\.bin$/.lst/; + +open F, $list; + +while() { + if(/^\s*\d+\s*(\S+)\s*0+\s*csum_value\s*dd\s*0/) { + $ofs = hex $1; + } +} +close F; + +die "oops 1\n" unless $ofs && !($ofs & 3); + +# print "$ofs\n"; + +open F, $file or die "$file: $!\n"; + +$file_size = -s $file; + +sysread F, $buf, $file_size; + +close F; + +die "oops 1\n" if $file_size != length($buf); + +@x = unpack "V512", $buf; + +for ($sum = 0, $i = 16; $i < 512; $i++) { + $sum += $x[$i]; +} + +# printf "0x%08x\n", $sum; + +$ns = pack "V", -$sum; + +substr($buf, $ofs, 4) = $ns; + +open F, ">$file" or die "$file: $!\n"; + +syswrite F, $buf; + diff -Naur syslinux-1.62.orig/fixofs syslinux-1.62/fixofs --- syslinux-1.62.orig/fixofs 1970-01-01 03:00:00 +0300 +++ syslinux-1.62/fixofs 2003-02-25 13:52:09 +0300 @@ -0,0 +1,4 @@ +#! /usr/bin/perl -p + +$ok = 1 if /org\s+7c00h/i; +s/^(\s*(\d+)\s+)([0-9A-Fa-f]{8})/$1 . sprintf("%08X", hex($3)+0x7c00)/e if $ok; diff -Naur syslinux-1.62.orig/gfxlogo.inc syslinux-1.62/gfxlogo.inc --- syslinux-1.62.orig/gfxlogo.inc 1970-01-01 03:00:00 +0300 +++ syslinux-1.62/gfxlogo.inc 2003-02-25 13:52:41 +0300 @@ -0,0 +1,495 @@ +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +; gfx stuff +; +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +; != 0 -> everything's fine +; note: moved to ldlinux.asm/isolinux.asm +; gfx_ok db 0 + + align 4, db 0 +; the memory area we are working with +gfx_mem dd 0 ; linear address +gfx_mem_max dd 0 ; end address +gfx_mem_free dd 0 ; start of free area for malloc (after pcx image) + +; interface to loadable gfx extension (seg:ofs values) +gfx_bc_jt dd 0 + +gfx_bc_init dd 0 +gfx_bc_done dd 0 +gfx_bc_input dd 0 +gfx_bc_menu_init dd 0 +gfx_bc_infobox_init dd 0 +gfx_bc_infobox_done dd 0 +gfx_bc_progress_init dd 0 +gfx_bc_progress_done dd 0 +gfx_bc_progress_update dd 0 +gfx_bc_progress_limit dd 0 +gfx_bc_password_init dd 0 +gfx_bc_password_done dd 0 + +gfx_menu_max_entries equ 16 +gfx_menu_entries db 0 +gfx_menu_tmp equ mi_buf ; a reasonably sized buffer +gfx_menu_def zb 13 +gfx_menu_entry zb 13 * gfx_menu_max_entries +gfx_args_entry zb 1 * gfx_menu_max_entries + +%if 0 +gfx_password_buf zb 32 +gfx_msg_wrong_image db 'Could not find kernel image: ', 0 +gfx_msg_wrong_password db 'Sorry, incorrect password.', 0 +%endif + +; system config data +gfx_sysconfig equ $ +gfx_sc_vmode db 0 +gfx_sc_modes db 0 +gfx_bootloader db 1 + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; must not change registers! +; +gfx_get_sysconfig: + push ax + + mov al,[video_mode] + mov [gfx_sc_vmode],al + + mov al,3 +%if 0 + mov al,1 + cmp word [fb_mode_0],byte 0 + setnz ah + shl ah,1 + or al,ah +%endif + cmp word [fb_mode_1],byte 0 + setnz ah + shl ah,2 + or al,ah + cmp word [fb_mode_2],byte 0 + setnz ah + shl ah,3 + or al,ah + mov [gfx_sc_modes],al + + cmp byte [wants_update],0 + setnz al + shl al,7 + or [gfx_sc_vmode],al + + pop ax + ret + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +gfx_set_sysconfig: + push ax + mov al,[gfx_sc_vmode] + test al,80h + setnz ah + mov [wants_update],ah + and al,0fh + mov [video_mode],al + pop ax + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +; Initialize graphics code. Load and display graphics data. +; +; dx:ax file length +; si start cluster +; +; return: [gfx_ok] = 0/1 +; +gfx_init: + push es + + cld + + ; define our memory area + ; gfx_mem _must_ be 16-byte aligned + mov dword [gfx_mem],10000h + mov dword [gfx_mem_free],10000h + mov dword [gfx_mem_max],40000h + + call gfx_read_file + cmp byte [gfx_ok],0 + jz near gfx_init_90 + + ; align 4 + mov eax,[gfx_mem_free] + add eax,3 + and eax,~3 + mov [gfx_mem_free],eax + + ; setup jump table + les bx,[gfx_bc_jt] + + mov ax,[es:bx] + mov [gfx_bc_init],ax + mov [gfx_bc_init+2],es + + mov ax,[es:bx+2] + mov [gfx_bc_done],ax + mov [gfx_bc_done+2],es + + mov ax,[es:bx+4] + mov [gfx_bc_input],ax + mov [gfx_bc_input+2],es + + mov ax,[es:bx+6] + mov [gfx_bc_menu_init],ax + mov [gfx_bc_menu_init+2],es + + mov ax,[es:bx+8] + mov [gfx_bc_infobox_init],ax + mov [gfx_bc_infobox_init+2],es + + mov ax,[es:bx+10] + mov [gfx_bc_infobox_done],ax + mov [gfx_bc_infobox_done+2],es + + mov ax,[es:bx+12] + mov [gfx_bc_progress_init],ax + mov [gfx_bc_progress_init+2],es + + mov ax,[es:bx+14] + mov [gfx_bc_progress_done],ax + mov [gfx_bc_progress_done+2],es + + mov ax,[es:bx+16] + mov [gfx_bc_progress_update],ax + mov [gfx_bc_progress_update+2],es + + mov ax,[es:bx+18] + mov [gfx_bc_progress_limit],ax + mov [gfx_bc_progress_limit+2],es + + mov ax,[es:bx+20] + mov [gfx_bc_password_init],ax + mov [gfx_bc_password_init+2],es + + mov ax,[es:bx+22] + mov [gfx_bc_password_done],ax + mov [gfx_bc_password_done+2],es + + mov eax,[gfx_mem] + mov ebx,[gfx_mem_free] + mov ecx,[gfx_mem_max] + mov dx,cs + + mov si,gfx_sysconfig + call far [gfx_bc_init] + jc gfx_init_80 + + mov byte [gfx_ok],1 + + jmp gfx_init_90 + +gfx_init_80: + mov byte [gfx_ok],0 +gfx_init_90: + pop es + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +; Back to text mode. +; +; return: [gfx_ok] = 0 +; +gfx_done: + cmp byte [gfx_ok],0 + jz gfx_done_90 + call far [gfx_bc_done] + mov byte [gfx_ok],0 + call gfx_set_sysconfig +gfx_done_90: + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +gfx_input: + cmp byte [gfx_ok],0 + jz gfx_input_90 + call gfx_get_sysconfig + call far [gfx_bc_input] + pushf + call gfx_set_sysconfig + popf + jnc gfx_input_50 + mov ax,1 +gfx_input_50: + cmp ax,1 + jnz gfx_input_90 + push ax + call gfx_done + pop ax +gfx_input_90: + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +gfx_setup_menu: + cmp byte [gfx_ok],0 + jz gfx_setup_menu_90 + + push ds + pop es + mov si,default_cmd + mov di,gfx_menu_tmp + call mangle_name + mov si,gfx_menu_tmp + mov di,gfx_menu_def + call unmangle_name + mov ax,[VKernelCtr] + mov [gfx_menu_entries],al + or ax,ax + jz gfx_setup_menu_90 + xor si,si + mov di,gfx_menu_entry +gfx_setup_menu_20: + push di + push si + shl si,vk_shift + push ds + push word vk_seg + pop ds + call unmangle_name + pop ds + pop si + pop di + add di,13 + inc si + cmp si,byte gfx_menu_max_entries + jae gfx_setup_menu_40 + cmp si,[VKernelCtr] + jb gfx_setup_menu_20 + +gfx_setup_menu_40: + mov si,gfx_menu_def + mov di,gfx_menu_entry + mov bx,gfx_args_entry + mov al,[gfx_menu_entries] + mov ah,0xff + mov dx,13 + mov cx,1 + + call gfx_get_sysconfig + call far [gfx_bc_menu_init] + +gfx_setup_menu_90: + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +gfx_infobox: + pushad + cmp byte [gfx_ok],0 + jz gfx_infobox_90 + call far [gfx_bc_infobox_init] + xor di,di + xor ax,ax + call far [gfx_bc_input] + call far [gfx_bc_infobox_done] +gfx_infobox_90: + popad + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +gfx_progress_init: + pushad + cmp byte [gfx_ok],0 + jz gfx_progress_init_90 + movzx eax,ax + call far [gfx_bc_progress_init] +gfx_progress_init_90: + popad + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +gfx_progress_done: + pushad + cmp byte [gfx_ok],0 + jz gfx_progress_done_90 + call far [gfx_bc_progress_done] +gfx_progress_done_90: + popad + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +gfx_progress_update: + pushad + cmp byte [gfx_ok],0 + jz gfx_progress_update_90 + movzx eax,cx + call far [gfx_bc_progress_update] +gfx_progress_update_90: + popad + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +gfx_progress_limit: + pushad + cmp byte [gfx_ok],0 + jz gfx_progress_limit_90 + movzx eax,ax + movzx edx,dx + call far [gfx_bc_progress_limit] +gfx_progress_limit_90: + popad + ret + + +%if 0 +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +gfx_password: + pushad + cmp byte [gfx_ok],0 + stc + jz gfx_password_90 + call far [gfx_bc_password_init] + mov di,gfx_password_buf + mov cx,32 + xor ax,ax + call far [gfx_bc_input] + mov si,gfx_password_buf + call far [gfx_bc_password_done] + jnc gfx_password_90 + mov si,gfx_msg_wrong_password + xor di,di + mov al,0 + call far [gfx_bc_infobox_init] + xor di,di + xor ax,ax + call far [gfx_bc_input] + call far [gfx_bc_infobox_done] + stc +gfx_password_90: + popad + ret +%endif + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +; Read graphics data and store them at [gfx_mem]. +; +; dx:ax file length +; si start cluster +; +; return: [gfx_ok] = 0/1 +; +gfx_read_file: + push es + mov byte [gfx_ok],0 + mov edi,[gfx_mem] + push dx ; DX:AX = length of file + push ax + pop edx + mov eax,[gfx_mem_free] + add eax,edx + cmp eax,[gfx_mem_max] ; max. length + ja near gfx_read_file_90 + mov [gfx_mem_free],eax + +gfx_read_file_10: + mov bx,trackbuf + mov cx,[BufSafe] + push edi + push edx + call getfssec + pop edx + pop edi + movzx ecx,word [BufSafeBytes] + cmp edx,ecx + jae gfx_read_file_20 + mov ecx,edx +gfx_read_file_20: + push ecx + push edi + push si ; Save current cluster + push es + mov si,trackbuf + push edi + call gfx_l2so + pop di + pop es + rep movsb + pop es + pop si + pop edi + pop ecx + add edi,ecx + sub edx,ecx + ja gfx_read_file_10 + + push dword [gfx_mem] + call gfx_l2so + pop bx + pop es + + cmp dword [es:bx],0b2d97f00h ; header.magic_id + jnz gfx_read_file_90 + mov al,[es:bx+4] ; header.version + cmp al,1 + jb gfx_read_file_90 + cmp al,3 + ja gfx_read_file_90 + + mov eax,[es:bx+8] + or eax,eax + jz gfx_read_file_90 + add eax,[gfx_mem] + test al,0fh + jnz gfx_read_file_90 + shr eax,4 + mov [gfx_bc_jt+2],ax + + mov byte [gfx_ok],1 + +gfx_read_file_90: + pop es + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +; Convert 32bit linear address to seg:ofs. +; +; dword [esp + 2]: linear address +; +; return: +; dword [esp + 2]: seg:ofs +; +; Notes: +; - changes no regs +; +gfx_l2so: + push eax + mov eax,[esp + 6] + shr eax,4 + mov [esp + 8],ax + and word [esp + 6],byte 0fh + pop eax + ret + diff -Naur syslinux-1.62.orig/isolinux.asm syslinux-1.62/isolinux.asm --- syslinux-1.62.orig/isolinux.asm 2001-04-24 22:36:14 +0400 +++ syslinux-1.62/isolinux.asm 2003-02-25 13:52:36 +0300 @@ -23,6 +23,8 @@ ; %define DEBUG_TRACERS ; Uncomment to get debugging tracers ; %define DEBUG_MESSAGES ; Uncomment to get debugging messages +%define do_test 0 + %ifdef DEBUG_TRACERS %macro TRACER 1 @@ -164,7 +166,7 @@ ; 5000h - real_mode_seg ; vk_seg equ 4000h ; Virtual kernels -xfer_buf_seg equ 3000h ; Bounce buffer for I/O to high mem +xfer_buf_seg equ 8000h ; Bounce buffer for I/O to high mem comboot_seg equ 2000h ; COMBOOT image loading zone ; @@ -365,6 +367,15 @@ alignb open_file_t_size Files resb MAX_OPEN*open_file_t_size + alignb 4 +; VBE2 buffer +vbe_buf resb 200h +; for DDC info +ddc_buf resb 80h +; VBE mode info & disk buffer +mi_buf resb 200h + + section .text org 7C00h ;; @@ -429,6 +440,21 @@ mov [ImageSectors],ax ; boot file sectors mov [DriveNo],dl + + ; check whether the BIOS did load us correctly + cmp dl,80h ; some BIOSes try to do floppy emulation... + jb bios_err + cmp dword [FirstSecSum], byte 0 + jz bios_ok +bios_err: + mov si,broken_bios_msg + call writemsg + jmp short $ +broken_bios_msg db 13, 10, 'Cannot boot from this CD. Please use CD2 or try a BIOS update.', 13, 10, 0 + align 4 +csum_value dd 0 +bios_ok: + %ifdef DEBUG_MESSAGES mov si,startup_msg call writemsg @@ -437,6 +463,9 @@ call crlf %endif +%if 0 + ; Some BIOSes don't like that call. + ; Now figure out what we're actually doing ; Note: use passed-in DL value rather than 7Fh because ; at least some BIOSes will get the wrong value otherwise @@ -457,7 +486,15 @@ call crlf %endif +%endif + + found_drive: + +%if 0 + ; We cannot handle != 2k sectors anyway and + ; some BIOSes don't like that call either. + ; Get drive information mov ah,48h mov dl,[DriveNo] @@ -483,6 +520,8 @@ call crlf %endif +%endif + load_image: ; Some BIOSes apparently have limitations on the size ; that may be loaded (despite the El Torito spec being very @@ -555,6 +594,9 @@ %endif jmp all_read ; Jump to main code +%if 0 + ; does not work anyway, see above + ; INT 13h, AX=4B01h, DL=7Fh failed. Try to scan the ; entire 80h-FFh from the end. spec_query_failed: @@ -588,6 +630,7 @@ .still_broken: dec dx cmp dl, 80h jnb .test_loop +%endif fatal_error: mov si,nothing_msg @@ -740,9 +783,12 @@ .try: pushad int 13h jc .error +.noerror: add sp,byte 8*4 ; Clean up stack ret -.error: mov [DiskError],ah ; Save error code +.error: or ah,ah + jz .noerror + mov [DiskError],ah ; Save error code popad dec byte [RetryCount] jnz .try @@ -770,6 +816,16 @@ mov fs,ax mov gs,ax sti + + cmp byte [gfx_ok],0 + jz kaboom_nogfx + mov si,err_failed_gfx + xor di,di + mov al,1 + call gfx_infobox + call gfx_done + call do_reboot +kaboom_nogfx: mov si,err_bootfailed call cwritestr call getchar @@ -803,9 +859,11 @@ nothing_msg: db 'Failed to access CD-ROM device; boot failed.', CR, LF, 0 checkerr_msg: db 'Image checksum error, sorry...', CR, LF, 0 +err_failed_gfx db 'Error reading boot CD.', 0 err_bootfailed db CR, LF, 'Boot failed: press a key to retry...' bailmsg equ err_bootfailed crlf_msg db CR, LF, 0 +gfx_ok db 0 ; ; El Torito spec packet @@ -1019,6 +1077,12 @@ inc al loop mkkeymap + test byte [KbdFlags],3 + jpe do_nogfx_10 ; left xor right shift: skip BIOS calls/no gfx + mov byte [do_nogfx],1 + mov byte [no_fkeys],1 ; no special F-key processing +do_nogfx_10: + ; ; Now, we need to sniff out the actual filesystem data structures. ; mkisofs gave us a pointer to the primary volume descriptor @@ -1120,6 +1184,14 @@ je near pc_say cmp ax,'lo' ; LOcalboot je pc_localboot + cmp ax,'fr' ; FRamebuffer + je near pc_fb + cmp ax,'re' ; REadinfo + je near pc_info + cmp ax,'ve' ; VErbose + je near pc_verbose + cmp ax,'gf' ; GFxboot + je near pc_gfxboot cmp al,'f' ; F-key jne parse_config jmp pc_fkey @@ -1128,7 +1200,7 @@ call getline xor al,al stosb ; null-terminate - jmp short parse_config + jmp near parse_config pc_append: cmp word [VKernelCtr],byte 0 ; "append" command ja pc_append_vk @@ -1175,6 +1247,9 @@ pc_display: call pc_getfile ; "display" command jz parse_config_2 ; File not found? + cmp byte [gfx_ok],0 + jnz parse_config_2 + ; don't load if we have a graphics image call get_msg_file ; Load and display file jmp short parse_config_2 @@ -1183,23 +1258,59 @@ mov [ForcePrompt],bx jmp short parse_config_2 +pc_fb: call getint ; "framebuffer" command + jc parse_config_2 + mov [FrameBuffer],bx + call skipspace + jc parse_config_2 + call ungetc + call getint + jc parse_config_2 + mov [FrameBufferBits],bx + jmp short parse_config_2 + +pc_info: call getint ; "readinfo" command + jc parse_config_2 + mov [ReadInfo],bx + jmp short parse_config_2 + +pc_verbose: call getint ; "verbose" command + jc parse_config_2 + mov [do_write_msg],bl + jmp short parse_config_2 + +pc_gfxboot: call pc_getfile ; "gfxboot" command + jz parse_config_2 ; File not found? + cmp byte [do_nogfx],0 + jnz parse_config_2 + push si + mov si,load_gfx_msg + call cwritestr + pop si + call gfx_init ; Load and display file + cmp byte [gfx_ok],0 + jnz parse_config_2 + mov si,crlf_msg + call cwritestr + jmp short parse_config_2 + pc_implicit: call getint ; "implicit" command jc parse_config_2 mov [AllowImplicit],bx - jmp short parse_config_2 + jmp near parse_config_2 pc_serial: call getint ; "serial" command - jc parse_config_2 + jc near parse_config_2 push bx ; Serial port # call skipspace - jc parse_config_2 + jc near parse_config_2 call ungetc call getint jnc .valid_baud mov ebx,DEFAULT_BAUD ; No baud rate given .valid_baud: pop di ; Serial port # cmp ebx,byte 75 - jb parse_config_2 ; < 75 baud == bogus + jb near parse_config_2 ; < 75 baud == bogus mov eax,BAUD_DIVISOR cdq div ebx @@ -1336,7 +1447,43 @@ end_config_file: call commit_vk ; Commit any current vkernel no_config_file: + +; Use VESA 2.0 calls to read the EDID monitor record. The Data will +; later be appended to the kernel command line. +; +; Get the APM status from the BIOS. ; + inc byte [no_fkeys] + cmp word [ReadInfo],0 + jz skip_bios_calls + dec byte [no_fkeys] + mov al,[KbdFlags] + and al,3 + jpo skip_bios_calls ; left xor right shift: skip BIOS calls + jz no_verbose ; !(left and right shift) + mov byte [do_write_msg],1 +no_verbose: + call read_ddc ; read Display Data Channel + call read_fsc + call read_apm ; get APM status + cmp word [ReadInfo],1 + jb skip_read_hd + call read_hd ; get crc of 1st hd block +skip_read_hd: + call read_kbd + call read_vbe_modes ; get VBE2 mode support + mov si,lxrc_data + 1 + call xwritestr + mov si,crlf_msg + call xwritestr +skip_bios_calls: + + call chk_update + + cmp byte [gfx_ok],0 + jz check_for_key + call gfx_setup_menu + ; Check whether or not we are supposed to display the boot prompt. ; check_for_key: @@ -1346,8 +1493,21 @@ jz near auto_boot ; If neither, default boot enter_command: + cmp byte [gfx_ok],0 + jz enter_command_10 + mov di,command_line + mov cx,max_cmd_len + xor ax,ax + xchg ax,[KbdTimeOut] ; only the first time + call gfx_input + cmp ax,1 + jz enter_command_10 + jmp load_kernel +enter_command_10: + mov si,boot_prompt call cwritestr + call show_vmode mov byte [FuncFlag],0 ; not pressed mov di,command_line @@ -1372,6 +1532,7 @@ ; know the appropriate DX value time_loop: push cx tick_loop: push dx + call chk_update call pollchar jnz get_char_pop mov dx,[BIOS_timer] ; Get time "of day" @@ -1443,6 +1604,10 @@ jb get_char_2 shr ax,8 show_help: ; AX = func key # (0 = F1, 9 = F10) + + call process_fkeys + jnc fk_done + mov cl,al shl ax,FILENAME_MAX_LG2 ; Convert to offset mov bx,1 @@ -1468,8 +1633,9 @@ mov byte [di],0 ; Null-terminate command line mov si,command_line call cwritestr ; Write command line so far +fk_done: pop di - jmp short get_char_2 + jmp near get_char_2 auto_boot: mov si,default_cmd mov di,command_line @@ -1483,6 +1649,8 @@ xor al,al ; Store a final null stosb + + call chk_update load_kernel: ; Load the kernel now ; ; First we need to mangle the kernel name the way DOS would... @@ -1530,7 +1698,7 @@ ; Not a "virtual kernel" - check that's OK and construct the command line ; cmp word [AllowImplicit],byte 0 - je bad_implicit + je near bad_implicit push es push si push di @@ -1574,6 +1742,14 @@ push di call unmangle_name ; Get human form mov si,err_notfound ; Complain about missing kernel + cmp byte [gfx_ok],0 + jz bad_kernel_no_gfx + pop di + mov al,0 + call gfx_infobox + mov si,no_msg + jmp abort_load +bad_kernel_no_gfx: call cwritestr pop si ; KernelCName call cwritestr @@ -1688,8 +1864,12 @@ kernel_sane: push ax push dx push si + cmp byte [gfx_ok],0 + jnz kernel_sane_gfx + call hide_vmode mov si,loading_msg call cwritestr +kernel_sane_gfx: ; ; Now start transferring the kernel ; @@ -1824,6 +2004,38 @@ mov si,KernelCName ; Unmangled kernel name mov cx,[KernelCNameLen] rep movsb + +; +; Insert special linuxrc data here +; + cmp byte [lxrc_data1],0 + jz no_lxrc_data + mov si,lxrc_data + mov ax,[lxrc_vga_ptr] + sub ax,si + add ax,di + mov [vga_txt_ofs],ax + mov [vga_txt_seg],es +store_lxrc_data: + lodsb + or al,al + jz no_lxrc_data + stosb + jmp store_lxrc_data +no_lxrc_data: + + mov si,expert_txt +store_expert_data: + lodsb + or al,al + jz expert_data_end + stosb + jmp store_expert_data +expert_data_end: + lea ax,[di-1] + mov [expert_txt_ofs],ax + mov [expert_txt_seg],es + mov al,' ' ; Space stosb @@ -1831,6 +2043,17 @@ mov si,[CmdOptPtr] ; Options from user input mov cx,(kern_cmd_len+3) >> 2 rep movsd + +; debug: print final kernel command line + push ds + push es + pop ds + mov si,cmd_line_here + call xwritestr + pop ds + mov si,crlf_msg + call xwritestr + ; ; Scan through the command line for anything that looks like we might be ; interested in. The original version of this code automatically assumed @@ -1851,6 +2074,8 @@ je is_vga_cmd cmp eax,'mem=' je is_mem_cmd + cmp eax,'SLX=' + je is_slx_cmd push es ; Save ES -> real_mode_seg push cs pop es ; Set ES <- normal DS @@ -1871,6 +2096,7 @@ dec si jmp short get_next_opt is_vga_cmd: + inc byte [cs:vga_parm_cnt] add si,byte 4 mov eax,[si] mov bx,-1 @@ -1894,11 +2120,55 @@ sub ebx,HIGHMEM_SLOP mov [cs:HighMemSize],ebx jmp short skip_this_opt +is_slx_cmd: + add si,byte 4 + call parseint + jc skip_this_opt ; Not an integer + mov [cs:SLXOption],bx + jmp short skip_this_opt cmdline_end: push cs ; Restore standard DS pop ds sub si,cmd_line_here mov [CmdLineLen],si ; Length including final null + + call boot_hd + + and word [InitRDClust], byte 0 + test byte [initrd_flag],1 + jz kernel_noinitrd + + push es ; ES->real_mode_seg + push ds + pop es ; We need ES==DS + mov si,InitRD + mov di,InitRDCName + call unmangle_name ; Create human-readable name + sub di,InitRDCName + mov [InitRDCNameLen],di + mov di,InitRD + call searchdir ; Look for it in directory + pop es + jz near initrd_notthere + mov [initrd_ptr],si ; Save cluster pointer + mov [es:su_ramdisklen1],ax ; Ram disk length + mov [es:su_ramdisklen2],dx + div word [ClustSize] + and dx,dx ; Round up + setnz dl + movzx dx,dl + add ax,dx + mov [InitRDClust],ax ; Ramdisk clusters + +kernel_noinitrd: + cmp byte [gfx_ok],0 + jz kernel_nogfx + mov ax,[KernelClust] + add ax,[InitRDClust] + mov si,KernelCName + call gfx_progress_init +kernel_nogfx: + ; ; Now check if we have a large kernel, which needs to be loaded high ; @@ -1930,10 +2200,13 @@ ; jumping to it. ; read_kernel: + cmp byte [gfx_ok],0 + jnz read_kernel_nogfx mov si,KernelCName ; Print kernel name part of call cwritestr ; "Loading" message mov si,dotdot_msg ; Print dots call cwritestr +read_kernel_nogfx: mov eax,[HighMemSize] sub eax,100000h ; Load address @@ -1957,8 +2230,12 @@ push word xfer_buf_seg ; Transfer buffer segment pop es high_load_loop: + cmp byte [gfx_ok],0 + jnz high_load_loop_nogfx mov si,dot_msg ; Progress report call cwritestr +high_load_loop_nogfx: + call chk_update call abort_check mov cx,[KernelClust] cmp cx,[ClustPerMoby] @@ -1966,6 +2243,10 @@ mov cx,[ClustPerMoby] high_last_moby: sub [KernelClust],cx + cmp byte [gfx_ok],0 + jz high_last_moby_nogfx + call gfx_progress_update +high_last_moby_nogfx: xor bx,bx ; Load at offset 0 pop si ; Restore cluster pointer call getfssec @@ -1986,39 +2267,22 @@ mov ax,real_mode_seg ; Set to real mode seg mov es,ax - mov si,dot_msg - call cwritestr + cmp byte [gfx_ok],0 + jnz high_load_done_gfx + mov si,clrln_msg + call cwritestr +high_load_done_gfx: + - call crlf ; ; Now see if we have an initial RAMdisk; if so, do requisite computation ; We know we have a new kernel; the old_kernel code already will have objected ; if we tried to load initrd using an old kernel ; load_initrd: - test byte [initrd_flag],1 - jz nk_noinitrd - push es ; ES->real_mode_seg - push ds - pop es ; We need ES==DS - mov si,InitRD - mov di,InitRDCName - call unmangle_name ; Create human-readable name - sub di,InitRDCName - mov [InitRDCNameLen],di - mov di,InitRD - call searchdir ; Look for it in directory - pop es - jz initrd_notthere - mov [initrd_ptr],si ; Save cluster pointer - mov [es:su_ramdisklen1],ax ; Ram disk length - mov [es:su_ramdisklen2],dx - div word [ClustSize] - and dx,dx ; Round up - setnz dl - movzx dx,dl - add ax,dx - mov [InitRDClust],ax ; Ramdisk clusters + cmp word [initrd_ptr],byte 0 + jz near nk_noinitrd + mov edx,[HighMemSize] ; End of memory mov eax,HIGHMEM_MAX ; Limit imposed by kernel cmp edx,eax @@ -2032,6 +2296,14 @@ jmp short initrd_end initrd_notthere: + cmp byte [gfx_ok],0 + jz initrd_notthere_nogfx + mov si,err_noinitrda + mov di,InitRDCName + mov al,1 + call gfx_infobox + call do_reboot +initrd_notthere_nogfx: mov si,err_noinitrd call cwritestr mov si,InitRDCName @@ -2039,18 +2311,124 @@ mov si,crlf_msg jmp abort_load -no_high_mem: mov si,err_nohighmem ; Error routine +no_high_mem: + cmp byte [gfx_ok],0 + jz no_high_mem_nogfx + mov si,err_nohighmem + xor di,di + mov al,1 + call gfx_infobox + call do_reboot +no_high_mem_nogfx: + mov si,err_nohighmem ; Error routine jmp abort_load initrd_end: nk_noinitrd: + + cmp byte [gfx_ok],0 + jz initrd_end_nogfx + call gfx_progress_done + + call abort_check ; Last chance!! + jmp update_disk_05 + +initrd_end_nogfx: + ; ; Abandon hope, ye that enter here! We do no longer permit aborts. ; call abort_check ; Last chance!! - mov si,ready_msg + mov si,clrln_msg + call cwritestr + +update_disk_05: + +; +; if the user has an update disk, give him a chance to insert it now +; + cmp byte [wants_update],0 + jnz update_disk_10 + cmp byte [gfx_ok],0 + jnz update_disk_90 + mov si,crlf_msg + call cwritestr + jmp update_disk_90 +update_disk_10: + cmp byte [gfx_ok],0 + jz update_disk_20 + mov al,0 + mov si,upd_msg_1a + xor di,di + call gfx_infobox + jmp update_disk_90 +update_disk_20: + mov si,upd_msg_1 call cwritestr + call wait_for_key +update_disk_90: + call gfx_done + + push word real_mode_seg + pop fs + + mov al,[wants_serial] + shl al,1 + or al,[wants_update] + shl al,1 + cmp byte [video_mode],0 + setz ah + or al,ah + les bx,[expert_txt_ofs] + add [es:bx],al + + cmp byte [vga_parm_cnt],2 ; override via cmdline + jae vid_mode_90 + cmp word [lxrc_vga_ptr],0 + jz vid_mode_90 + les di,[vga_txt_ofs] + mov cx,[lxrc_vga_len] + or cx,cx + jz vid_mode_90 + cmp byte [video_mode],0 + jz vid_mode_50 + add di,cx + sub di,4 + + mov al,[video_mode] + mov cx,[fb_mode_0] + dec al + jz vid_mode_30 ; 1 + mov cx,[fb_mode_1] + dec al + jz vid_mode_30 ; 2 + mov cx,[fb_mode_2] + dec al + jnz vid_mode_50 ; 0, > 3 +vid_mode_30: + or cx,cx + jz vid_mode_50 + + mov si,di + add ch,2 + mov [fs:bs_vidmode],cx + mov al,ch + push ds + push es + pop ds + push cx + call byte_to_hex + pop ax + call byte_to_hex + pop ds + jmp vid_mode_90 +vid_mode_50: + mov al,' ' + rep stosb + mov word [fs:bs_vidmode],-1 +vid_mode_90: + call vgaclearmode ; We can't trust ourselves after this @@ -2186,6 +2564,7 @@ mov dx,03F2h xor al,al call slow_out + ; ; If we're debugging, wait for a keypress so we can read any debug messages ; @@ -2193,6 +2572,11 @@ xor ax,ax int 16h %endif + +%if do_test + jmp $ +%endif + ; ; Set up segment registers and the Linux real-mode stack ; Note: bx == the real mode segment @@ -2397,7 +2781,11 @@ dd 00009300h ; present, dpl 0, cover 64K bcopy_gdt_size: equ $-bcopy_gdt -bcopy: push eax +bcopy: +%if do_test + ret +%endif + push eax pushf ; Saves, among others, the IF flag push gs push fs @@ -2686,6 +3074,60 @@ ret ; +; terminate cdrom boot floppy emulation +; +detach_cd: + test byte [SLXOption],1 ; just make it configurable + jnz detach_cd_90 + push es ; you never know... + mov si,trackbuf + mov ax,4b00h + mov byte [si],13h ; packet size + mov dl,7fh ; 7fh: all drives + int 13h ; terminate floppy emulation + pop es +detach_cd_90: + ret + +; +; boot mbr, if SLXOption says so +; +boot_hd: + mov ax,[SLXOption] + test al,2 ; should we do it? + jz boot_hd_90 + push es + shr ax,2 + push ax + call detach_cd + pop dx + mov ax,0201h + xor cx,cx + mov es,cx + inc cx + xor dh,dh + mov bx,trackbuf + push bx + int 13h + pop si + jc boot_hd_80 + cmp word [si+0x1fe],0aa55h + jnz boot_hd_80 + cmp word [si], byte 0 + jz boot_hd_80 + mov di,7c00h + push di + mov cx,0x100 + cld + rep movsw + call gfx_done + ret +boot_hd_80: + pop es +boot_hd_90: + ret + +; ; Load RAM disk into high memory ; loadinitrd: @@ -2696,6 +3138,8 @@ mov edi,[InitRDat] ; initrd load address mov [es:su_ramdiskat],edi ; Offset for ram disk push si + cmp byte [gfx_ok],0 + jnz rd_load_loop mov si,loading_msg call cwritestr mov si,InitRDCName ; Write ramdisk name @@ -2703,9 +3147,13 @@ mov si,dotdot_msg ; Write dots call cwritestr rd_load_loop: + cmp byte [gfx_ok],0 + jnz rd_load_loop_gfx mov si,dot_msg ; Progress report call cwritestr +rd_load_loop_gfx: pop si ; Restore cluster pointer + call chk_update call abort_check mov cx,[InitRDClust] cmp cx,[ClustPerMoby] @@ -2713,6 +3161,10 @@ mov cx,[ClustPerMoby] rd_last_moby: sub [InitRDClust],cx + cmp byte [gfx_ok],0 + jz rd_last_moby_nogfx + call gfx_progress_update +rd_last_moby_nogfx: xor bx,bx ; Load at offset 0 push word xfer_buf_seg ; Bounce buffer segment pop es @@ -2730,7 +3182,13 @@ jne rd_load_loop ; Apparently not rd_load_done: pop si ; Clean up the stack - call crlf + cmp byte [gfx_ok],0 + jnz rd_load_done_gfx + push si + mov si,clrln_msg + call cwritestr + pop si +rd_load_done_gfx: pop es ; Restore original ES ret @@ -2738,6 +3196,10 @@ ; abort_check: let the user abort with or ; abort_check: + cmp byte [gfx_ok],0 + jz abort_check_nogfx + ret +abort_check_nogfx: call pollchar jz ac_ret1 pusha @@ -3439,7 +3901,8 @@ ; getchar: Read a character from keyboard or serial port ; getchar: -.again: mov ah,1 ; Poll keyboard +.again: call chk_update + mov ah,1 ; Poll keyboard int 16h jnz .kbd ; Keyboard input? mov bx,[SerialPort] @@ -4192,6 +4655,18 @@ linear_color db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 UsingVGA db 0 + +; +; most of the new stuff is now in suse.inc +; +%include "suse.inc" + +; +; add gfx stuff +; +%include "gfxlogo.inc" + + ; ---------------------------------------------------------------------------------- ; Begin data section ; ---------------------------------------------------------------------------------- @@ -4223,7 +4698,8 @@ db 'booting, and I will take your word for it.', 0Dh, 0Ah, 0 err_badcfg db 'Unknown keyword in config file.', CR, LF, 0 err_noparm db 'Missing parameter in config file.', CR, LF, 0 -err_noinitrd db CR, LF, 'Could not find ramdisk image: ', 0 +err_noinitrd db CR, LF +err_noinitrda db 'Could not find ramdisk image: ', 0 err_nohighmem db 'Not enough memory to load specified kernel.', CR, LF, 0 err_highload db CR, LF, 'Kernel transfer failure.', CR, LF, 0 err_oldkernel db 'Cannot load a ramdisk with an old kernel image.' @@ -4246,7 +4722,11 @@ default_str db 'default', 0 default_len equ ($-default_str) isolinux_dir db '/isolinux', 0 + zb 64 isolinux_cfg db 'isolinux.cfg', 0 +load_gfx_msg db 'Loading...', 0 +no_msg db 0 +clrln_msg db 0dh, ' ', 0dh, 0 %ifdef DEBUG_MESSAGES dbg_rootdir_msg db 'Root directory at LBA = ', 0 @@ -4290,6 +4770,12 @@ ; PXELINUX specific options... db 'ip' ; ipappend db 'lo' ; localboot + + db 'fr' ; framebuffer + db 're' ; readinfo + db 've' ; verbose + db 'gf' ; gfxboot + dw 0 ; ; Extensions to search for (in *forward* order). @@ -4320,6 +4806,10 @@ 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 +FrameBuffer dw 0 ; Add an appropriate vga= line for kernel fb's +FrameBufferBits dw 8 ; Color depth for the fb +ReadInfo dw 0 ; Get some info from BIOS +SLXOption dw 0 ; control sysliux via cmdline ScrollAttribute db 07h ; White on black (for text mode) ; diff -Naur syslinux-1.62.orig/ldlinux.asm syslinux-1.62/ldlinux.asm --- syslinux-1.62.orig/ldlinux.asm 2001-04-24 22:36:14 +0400 +++ syslinux-1.62/ldlinux.asm 2003-02-28 15:05:33 +0300 @@ -26,6 +26,8 @@ ; ; **************************************************************************** +%define do_test 0 + ; ; Some semi-configurable constants... change on your own risk. Most are imposed ; by the kernel. @@ -153,7 +155,7 @@ ; fat_seg equ 5000h ; 128K area for FAT (2x64K) vk_seg equ 4000h ; Virtual kernels -xfer_buf_seg equ 3000h ; Bounce buffer for I/O to high mem +xfer_buf_seg equ 8000h ; Bounce buffer for I/O to high mem comboot_seg equ 2000h ; COMBOOT image loading zone ; @@ -245,6 +247,9 @@ trackbufsize equ 16384 ; Safe size of track buffer ; trackbuf ends at 5000h +; VGA font buffer at the end of memory (so loading a font works even +; in graphics mode.) +vgafontbuf equ 5000h ; ; Constants for the xfer_buf_seg @@ -258,7 +263,8 @@ xbs_vgatmpbuf equ 2*trackbufsize - absolute 5000h ; Here we keep our BSS stuff + ; leave enough room for stack (8k) + absolute 7000h ; Here we keep our BSS stuff StackBuf equ $ ; Start the stack here (grow down - 4K) VKernelBuf: resb vk_size ; "Current" vkernel alignb 4 @@ -339,6 +345,15 @@ VGAFileBufEnd equ $ VGAFileMBuf resb 11 ; Mangled VGA image name + alignb 4 +; VBE2 buffer +vbe_buf resb 200h +; for DDC info +ddc_buf resb 80h +; VBE mode info & disk buffer +mi_buf resb 200h + + section .text org 7C00h ; @@ -782,6 +797,10 @@ ; We can really only rely on a single sector having been loaded. Hence ; we should load the FAT into RAM and start chasing pointers... ; + call update_fat + jmp near load_rest + +update_fat: mov dx,1 ; 64K xor ax,ax div word [bsBytesPerSec] ; sectors/64K @@ -876,6 +895,8 @@ have_fat12: mov ax,nextcluster_fat12 have_fat_type: mov word [NextCluster],ax + ret + ; ; Now we read the rest of LDLINUX.SYS. Don't bother loading the first ; cluster again, though. @@ -1201,6 +1222,11 @@ inc al loop mkkeymap + test byte [KbdFlags],3 + jpe do_nogfx_10 ; left xor right shift: skip BIOS calls/no gfx + mov byte [do_nogfx],1 + mov byte [no_fkeys],1 ; no special F-key processing +do_nogfx_10: ; ; Load configuration file ; @@ -1232,6 +1258,16 @@ je near pc_implicit cmp ax,'se' ; SErial je near pc_serial + cmp ax,'fr' ; FRamebuffer + je near pc_fb + cmp ax,'re' ; REadinfo + je near pc_info + cmp ax,'ve' ; VErbose + je near pc_verbose + cmp ax,'gf' ; GFxboot + je near pc_gfxboot + cmp ax,'in' ; INitrdsize + je near pc_initrdsize cmp al,'f' ; F-key jne parse_config jmp pc_fkey @@ -1240,7 +1276,7 @@ call getline xor al,al stosb ; null-terminate - jmp short parse_config + jmp near parse_config pc_append: cmp word [VKernelCtr],byte 0 ; "append" command ja pc_append_vk @@ -1248,7 +1284,7 @@ call getline sub di,AppendBuf pc_app1: mov [AppendLen],di - jmp short parse_config + jmp near parse_config pc_append_vk: mov di,VKernelBuf+vk_append ; "append" command (vkernel) call getline sub di,VKernelBuf+vk_append @@ -1278,8 +1314,16 @@ mov [KbdTimeOut],bx jmp short parse_config_2 +pc_initrdsize: call getint ; "initrdsize" command + jc parse_config_2 + mov [ExpInitRDClust],bx + jmp short parse_config_2 + pc_display: call pc_getfile ; "display" command jz parse_config_2 ; File not found? + cmp byte [gfx_ok],0 + jnz parse_config_2 + ; don't load if we have a graphics image call get_msg_file ; Load and display file parse_config_2: jmp parse_config @@ -1288,6 +1332,42 @@ mov [ForcePrompt],bx jmp short parse_config_2 +pc_fb: call getint ; "framebuffer" command + jc parse_config_2 + mov [FrameBuffer],bx + call skipspace + jc parse_config_2 + call ungetc + call getint + jc parse_config_2 + mov [FrameBufferBits],bx + jmp short parse_config_2 + +pc_info: call getint ; "readinfo" command + jc parse_config_2 + mov [ReadInfo],bx + jmp short parse_config_2 + +pc_verbose: call getint ; "verbose" command + jc parse_config_2 + mov [do_write_msg],bl + jmp short parse_config_2 + +pc_gfxboot: call pc_getfile ; "gfxboot" command + jz parse_config_2 ; File not found? + cmp byte [do_nogfx],0 + jnz parse_config_2 + push si + mov si,load_gfx_msg + call cwritestr + pop si + call gfx_init ; Load and display file + cmp byte [gfx_ok],0 + jnz parse_config_2 + mov si,crlf_msg + call cwritestr + jmp short parse_config_2 + pc_implicit: call getint ; "implicit" command jc parse_config_2 mov [AllowImplicit],bx @@ -1297,14 +1377,14 @@ jc parse_config_2 push bx ; Serial port # call skipspace - jc parse_config_2 + jc near parse_config_2 call ungetc call getint jnc .valid_baud mov ebx,DEFAULT_BAUD ; No baud rate given .valid_baud: pop di ; Serial port # cmp ebx,byte 75 - jb parse_config_2 ; < 75 baud == bogus + jb near parse_config_2 ; < 75 baud == bogus mov eax,BAUD_DIVISOR cdq div ebx @@ -1431,6 +1511,42 @@ end_config_file: call commit_vk ; Commit any current vkernel no_config_file: + +; Use VESA 2.0 calls to read the EDID monitor record. The Data will +; later be appended to the kernel command line. +; +; Get the APM status from the BIOS. +; + inc byte [no_fkeys] + cmp word [ReadInfo],0 + jz skip_bios_calls + dec byte [no_fkeys] + mov al,[KbdFlags] + and al,3 + jpo skip_bios_calls ; left xor right shift: skip BIOS calls + jz no_verbose ; !(left and right shift) + mov byte [do_write_msg],1 +no_verbose: + call read_ddc ; read Display Data Channel + call read_fsc + call read_apm ; get APM status + cmp word [ReadInfo],1 + jb skip_read_hd + call read_hd ; get crc of 1st hd block +skip_read_hd: + call read_kbd + call read_vbe_modes ; get VBE2 mode support + mov si,lxrc_data + 1 + call xwritestr + mov si,crlf_msg + call xwritestr +skip_bios_calls: + + call chk_update + + cmp byte [gfx_ok],0 + jz check_for_key + call gfx_setup_menu ; ; Check whether or not we are supposed to display the boot prompt. ; @@ -1441,8 +1557,21 @@ jz near auto_boot ; If neither, default boot enter_command: + cmp byte [gfx_ok],0 + jz enter_command_10 + mov di,command_line + mov cx,max_cmd_len + xor ax,ax + xchg ax,[KbdTimeOut] ; only the first time + call gfx_input + cmp ax,1 + jz enter_command_10 + jmp load_kernel +enter_command_10: + mov si,boot_prompt call cwritestr + call show_vmode mov byte [FuncFlag],0 ; not pressed mov di,command_line @@ -1467,6 +1596,7 @@ ; know the appropriate DX value time_loop: push cx tick_loop: push dx + call chk_update call pollchar jnz get_char_pop xor ax,ax @@ -1509,7 +1639,7 @@ get_char_2: jmp short get_char not_ascii: mov byte [FuncFlag],0 cmp al,0Dh ; Enter - je command_done + je near command_done cmp al,06h ; je set_func_flag cmp al,08h ; Backspace @@ -1539,6 +1669,10 @@ jb get_char_2 shr ax,8 show_help: ; AX = func key # (0 = F1, 9 = F10) + + call process_fkeys + jnc fk_done + mov cl,al shl ax,4 ; Convert to x16 mov bx,1 @@ -1564,8 +1698,9 @@ mov byte [di],0 ; Null-terminate command line mov si,command_line call cwritestr ; Write command line so far +fk_done: pop di - jmp short get_char_2 + jmp near get_char_2 auto_boot: mov si,default_cmd mov di,command_line @@ -1579,6 +1714,8 @@ xor al,al ; Store a final null stosb + + call chk_update load_kernel: ; Load the kernel now ; ; First we need to mangle the kernel name the way DOS would... @@ -1626,7 +1763,7 @@ ; Not a "virtual kernel" - check that's OK and construct the command line ; cmp word [AllowImplicit],byte 0 - je bad_implicit + je near bad_implicit push es push si push di @@ -1662,6 +1799,14 @@ push di call unmangle_name ; Get human form mov si,err_notfound ; Complain about missing kernel + cmp byte [gfx_ok],0 + jz bad_kernel_no_gfx + pop di + mov al,0 + call gfx_infobox + mov si,no_msg + jmp abort_load +bad_kernel_no_gfx: call cwritestr pop si ; KernelCName call cwritestr @@ -1765,8 +1910,12 @@ kernel_sane: push ax push dx push si + cmp byte [gfx_ok],0 + jnz kernel_sane_gfx + call hide_vmode mov si,loading_msg call cwritestr +kernel_sane_gfx: ; ; Now start transferring the kernel ; @@ -1899,11 +2048,64 @@ mov si,KernelCName ; Unmangled kernel name mov cx,[KernelCNameLen] rep movsb + +; +; Insert special linuxrc data here +; +; cmp byte [lxrc_data1],0 +; jz no_lxrc_data +; mov si,lxrc_data +; mov ax,[lxrc_vga_ptr] +; sub ax,si +; add ax,di +; mov [vga_txt_ofs],ax +; mov [vga_txt_seg],es + + cmp byte [lxrc_data1],0 + jz no_lxrc_data + mov si,lxrc_data + mov ax,[lxrc_vga_ptr] + sub ax,si + add ax,di + mov [vga_txt_ofs],ax + mov [vga_txt_seg],es + +store_lxrc_data: + lodsb + or al,al + jz no_lxrc_data + stosb + jmp store_lxrc_data +no_lxrc_data: + + mov si,expert_txt +store_expert_data: + lodsb + or al,al + jz expert_data_end + stosb + jmp store_expert_data +expert_data_end: + lea ax,[di-1] + mov [expert_txt_ofs],ax + mov [expert_txt_seg],es + mov al,' ' ; Space stosb mov si,[CmdOptPtr] ; Options from user input mov cx,(kern_cmd_len+3) >> 2 rep movsd + +; debug: print final kernel command line + push ds + push es + pop ds + mov si,cmd_line_here + call xwritestr + pop ds + mov si,crlf_msg + call xwritestr + ; %ifdef debug push ds ; DEBUG DEBUG DEBUG @@ -1934,6 +2136,8 @@ je is_vga_cmd cmp eax,'mem=' je is_mem_cmd + cmp eax,'SLX=' + je is_slx_cmd push es ; Save ES -> real_mode_seg push ss pop es ; Set ES <- normal DS @@ -1954,6 +2158,7 @@ dec si jmp short get_next_opt is_vga_cmd: + inc byte [cs:vga_parm_cnt] add si,byte 4 mov eax,[si] mov bx,-1 @@ -1976,11 +2181,34 @@ jc skip_this_opt ; Not an integer mov [cs:HighMemSize],ebx jmp short skip_this_opt +is_slx_cmd: + add si,byte 4 + call parseint + jc skip_this_opt ; Not an integer + mov [cs:SLXOption],bx + jmp short skip_this_opt cmdline_end: push cs ; Restore standard DS pop ds sub si,cmd_line_here mov [CmdLineLen],si ; Length including final null + + call boot_hd + call lookup_initrd + jnc start_loading + cmp word [ExpInitRDClust],byte 0 + jz near initrd_notthere + +start_loading: + + cmp byte [gfx_ok],0 + jz kernel_nogfx + mov ax,[KernelClust] + add ax,[InitRDClust] + mov si,KernelCName + call gfx_progress_init +kernel_nogfx: + ; ; Now check if we have a large kernel, which needs to be loaded high ; @@ -2001,60 +2229,9 @@ movzx ax,byte [es:bs_setupsecs] ; Variable # of setup sectors mov [SetupSecs],ax ; -; Now see if we have an initial RAMdisk; if so, do requisite computation -; - test byte [initrd_flag],1 - jz nk_noinitrd - push es ; ES->real_mode_seg - push ds - pop es ; We need ES==DS - mov si,InitRD - mov di,InitRDCName - call unmangle_name ; Create human-readable name - sub di,InitRDCName - mov [InitRDCNameLen],di - mov di,InitRD - call searchdir ; Look for it in directory - pop es - jz initrd_notthere - mov [initrd_ptr],si ; Save cluster pointer - mov [es:su_ramdisklen1],ax ; Ram disk length - mov [es:su_ramdisklen2],dx - div word [ClustSize] - and dx,dx ; Round up - setnz dl - movzx dx,dl - add ax,dx - mov [InitRDClust],ax ; Ramdisk clusters - mov edx,[HighMemSize] ; End of memory (64K chunks) - mov eax,HIGHMEM_MAX ; Limit imposed by kernel - cmp edx,eax - jna memsize_ok - mov edx,eax ; Adjust to fit inside limit -memsize_ok: - xor dx,dx ; Round down to 64K boundary - sub edx,[es:su_ramdisklen] ; Subtract size of ramdisk - xor dx,dx ; Round down to 64K boundary - mov [InitRDat],edx ; Load address - call loadinitrd ; Load initial ramdisk - jmp short initrd_end - -initrd_notthere: - mov si,err_noinitrd - call cwritestr - mov si,InitRDCName - call cwritestr - mov si,crlf_msg - jmp abort_load - -no_high_mem: mov si,err_nohighmem ; Error routine - jmp abort_load -; ; About to load the kernel. This is a modern kernel, so use the boot flags ; we were provided. ; -nk_noinitrd: -initrd_end: mov al,[es:su_loadflags] mov [LoadFlags],al ; @@ -2063,15 +2240,18 @@ ; jumping to it. ; read_kernel: + cmp byte [gfx_ok],0 + jnz read_kernel_nogfx mov si,KernelCName ; Print kernel name part of call cwritestr ; "Loading" message mov si,dotdot_msg ; Print dots call cwritestr +read_kernel_nogfx: mov eax,[HighMemSize] sub eax,100000h ; Load address cmp eax,[KernelSize] - jb no_high_mem ; Not enough high memory + jb near no_high_mem ; Not enough high memory ; ; Move the stuff beyond the setup code to high memory at 100000h ; @@ -2090,8 +2270,12 @@ push word xfer_buf_seg ; Transfer buffer segment pop es high_load_loop: + cmp byte [gfx_ok],0 + jnz high_load_loop_nogfx mov si,dot_msg ; Progress report call cwritestr +high_load_loop_nogfx: + call chk_update call abort_check mov cx,[KernelClust] cmp cx,[ClustPerMoby] @@ -2099,9 +2283,13 @@ mov cx,[ClustPerMoby] high_last_moby: sub [KernelClust],cx + cmp byte [gfx_ok],0 + jz high_last_moby_nogfx + call gfx_progress_update +high_last_moby_nogfx: xor bx,bx ; Load at offset 0 pop si ; Restore cluster pointer - call getfssec + call getfssec push si ; Save cluster pointer pushf ; Save EOF xor bx,bx @@ -2119,15 +2307,202 @@ mov ax,real_mode_seg ; Set to real mode seg mov es,ax - mov si,dot_msg - call cwritestr + cmp byte [gfx_ok],0 + jnz high_load_done_gfx + mov si,clrln_msg + call cwritestr +high_load_done_gfx: + + +; +; Now see if we have an initial RAMdisk; if so, do requisite computation +; We know we have a new kernel; the old_kernel code already will have objected +; if we tried to load initrd using an old kernel ; + + cmp byte [InitRDMissing],0 + jz load_initrd + + ; ok, the initrd is missing, ask user to replace disk + + cmp byte [gfx_ok],0 + jz load_i_10 + mov al,0 + mov si,mod_disk_msga + xor di,di + call gfx_infobox + jmp load_i_20 +load_i_10: + mov si,clrln_msg + call cwritestr + mov si,mod_disk_msg + call cwritestr + call wait_for_key + +load_i_20: + call detach_cd + call reload_boot + call update_fat + call lookup_initrd + pushf + cmp byte [gfx_ok],0 + jnz load_i_50 + mov si,clrln_msg + call cwritestr +load_i_50: + popf + jc initrd_notthere + +load_initrd: + cmp word [initrd_ptr],byte 0 + jz nk_noinitrd + + mov edx,[HighMemSize] ; End of memory + mov eax,HIGHMEM_MAX ; Limit imposed by kernel + cmp edx,eax + jna memsize_ok + mov edx,eax ; Adjust to fit inside limit +memsize_ok: + sub edx,[es:su_ramdisklen] ; Subtract size of ramdisk + xor dx,dx ; Round down to 64K boundary + mov [InitRDat],edx ; Load address + call loadinitrd ; Load initial ramdisk + jmp short initrd_end + +initrd_notthere: + cmp byte [gfx_ok],0 + jz initrd_notthere_nogfx + mov si,err_noinitrda + mov di,InitRDCName + mov al,1 + call gfx_infobox + call do_reboot +initrd_notthere_nogfx: + mov si,err_noinitrd + call cwritestr + mov si,InitRDCName + call cwritestr + mov si,crlf_msg + jmp abort_load + +no_high_mem: + cmp byte [gfx_ok],0 + jz no_high_mem_nogfx + mov si,err_nohighmem + xor di,di + mov al,1 + call gfx_infobox + call do_reboot +no_high_mem_nogfx: + mov si,err_nohighmem ; Error routine + jmp abort_load + +initrd_end: +nk_noinitrd: + + cmp byte [gfx_ok],0 + jz initrd_end_nogfx + call gfx_progress_done + + call abort_check ; Last chance!! + jmp update_disk_05 + +initrd_end_nogfx: + + ; Abandon hope, ye that enter here! We do no longer permit aborts. ; call abort_check ; Last chance!! - mov si,ready_msg + mov si,clrln_msg + call cwritestr + +update_disk_05: + +; +; if the user has an update disk, give him a chance to insert it now +; + cmp byte [wants_update],0 + jnz update_disk_10 + cmp byte [gfx_ok],0 + jnz update_disk_90 + mov si,crlf_msg + call cwritestr + jmp update_disk_90 +update_disk_10: + cmp byte [gfx_ok],0 + jz update_disk_20 + mov al,0 + mov si,upd_msg_1a + xor di,di + call gfx_infobox + jmp update_disk_90 +update_disk_20: + mov si,upd_msg_1 call cwritestr + call wait_for_key +update_disk_90: + call gfx_done + + push word real_mode_seg + pop fs + + mov al,[wants_serial] + shl al,1 + or al,[wants_update] + shl al,1 + cmp byte [video_mode],0 + setz ah + or al,ah + les bx,[expert_txt_ofs] + add [es:bx],al + + cmp byte [vga_parm_cnt],2 ; override via cmdline + jae vid_mode_90 + cmp word [lxrc_vga_ptr],0 + jz vid_mode_90 + les di,[vga_txt_ofs] + mov cx,[lxrc_vga_len] + or cx,cx + jz vid_mode_90 + cmp byte [video_mode],0 + jz vid_mode_50 + add di,cx + sub di,4 + + mov al,[video_mode] + mov cx,[fb_mode_0] + dec al + jz vid_mode_30 ; 1 + mov cx,[fb_mode_1] + dec al + jz vid_mode_30 ; 2 + mov cx,[fb_mode_2] + dec al + jnz vid_mode_50 ; 0, > 3 +vid_mode_30: + or cx,cx + jz vid_mode_50 + + mov si,di + add ch,2 + mov [fs:bs_vidmode],cx + mov al,ch + push ds + push es + pop ds + push cx + call byte_to_hex + pop ax + call byte_to_hex + pop ds + jmp vid_mode_90 +vid_mode_50: + mov al,' ' + rep stosb + mov word [fs:bs_vidmode],-1 +vid_mode_90: + call vgaclearmode ; We can't trust ourselves after this ; @@ -2257,6 +2632,7 @@ mov dx,03F2h xor al,al call slow_out + ; ; If we're debugging, wait for a keypress so we can read any debug messages ; @@ -2264,6 +2640,11 @@ xor ax,ax int 16h %endif + +%if do_test + jmp $ +%endif + ; ; Set up segment registers and the Linux real-mode stack ; Note: bx == the real mode segment @@ -2479,7 +2860,11 @@ dd 00009300h ; present, dpl 0, cover 64K bcopy_gdt_size: equ $-bcopy_gdt -bcopy: push eax +bcopy: +%if do_test + ret +%endif + push eax pushf ; Saves, among others, the IF flag push gs push fs @@ -2765,6 +3150,143 @@ ret ; +; terminate cdrom boot floppy emulation +; +detach_cd: + test byte [SLXOption],1 ; just make it configurable + jnz detach_cd_90 + push es ; you never know... + mov si,trackbuf + mov ax,4b00h + mov byte [si],13h ; packet size + xor dx,dx ; dl: drive 0 + int 13h ; terminate floppy emulation + pop es +detach_cd_90: + ret + +; +; boot mbr, if SLXOption says so +; +boot_hd: + mov ax,[SLXOption] + test al,2 ; should we do it? + jz boot_hd_90 + push es + shr ax,2 + xchg [bsDriveNumber],al + push ax + call detach_cd + xor ax,ax + xor dx,dx + mov es,ax + mov bx,trackbuf + push bx + call getonesec + pop si + cmp word [si+0x1fe],0aa55h + jnz boot_hd_80 + cmp word [si], byte 0 + jz boot_hd_80 + mov di,7c00h + push di + mov cx,0x100 + cld + rep movsw + call gfx_done + ret +boot_hd_80: + pop ax + mov [bsDriveNumber],al + pop es +boot_hd_90: + ret + +; +; reload boot block +; +reload_boot: + push es + xor ax,ax + xor dx,dx + mov es,ax + mov bx,trackbuf + push bx + call getonesec + pop si + add si,superblock-bootsec + mov di,superblock + mov cx,superblock_len + cld + rep movsb + + ; we can't reuse the bootblock code, it wouldn't fit :-(( + + movzx ax,[bsFATs] ; Number of FATs + mul word [bsFATsecs] ; Get the size of the FAT area + add ax,[bsHidden1] ; Add hidden sectors + adc dx,[bsHidden2] + add ax,[bsResSectors] ; And reserved sectors + adc dx,byte 0 + + mov [RootDir1],ax ; Location of root directory + mov [RootDir2],dx + mov [DataArea1],ax + mov [DataArea2],dx + + mov ax,32 ; Size of a directory entry + mul word [bsRootDirEnts] + mov bx,[bsBytesPerSec] + add ax,bx ; Round up, not down + dec ax + div bx ; Now we have the size of the root dir + mov [RootDirSize],ax + + add [DataArea1],ax + adc word [DataArea2],byte 0 + +reload_boot_90: + pop es + ret + +; +; look for initrd, get its size and prepare for loading it +; return: CF = 1 if it wasn't found +; +lookup_initrd: + and word [InitRDClust], byte 0 + test byte [initrd_flag],1 + jz lookup_initrd_90 + push word [ExpInitRDClust] + pop word [InitRDClust] + push es ; ES->real_mode_seg + push ds + pop es ; We need ES==DS + mov si,InitRD + mov di,InitRDCName + call unmangle_name ; Create human-readable name + sub di,InitRDCName + mov [InitRDCNameLen],di + mov di,InitRD + call searchdir ; Look for it in directory + pop es + stc + mov byte [InitRDMissing],1 ; remember for later + jz lookup_initrd_90 + mov byte [InitRDMissing],0 + mov [initrd_ptr],si ; Save cluster pointer + mov [es:su_ramdisklen1],ax ; Ram disk length + mov [es:su_ramdisklen2],dx + div word [ClustSize] + and dx,dx ; Round up + setnz dl + movzx dx,dl + add ax,dx + mov [InitRDClust],ax ; Ramdisk clusters +lookup_initrd_90: + ret + +; ; Load RAM disk into high memory ; loadinitrd: @@ -2775,14 +3297,22 @@ mov edi,[InitRDat] ; initrd load address mov [es:su_ramdiskat],edi ; Offset for ram disk push si + cmp byte [gfx_ok],0 + jnz rd_load_loop + mov si,loading_msg + call cwritestr mov si,InitRDCName ; Write ramdisk name call cwritestr mov si,dotdot_msg ; Write dots call cwritestr rd_load_loop: + cmp byte [gfx_ok],0 + jnz rd_load_loop_gfx mov si,dot_msg ; Progress report call cwritestr +rd_load_loop_gfx: pop si ; Restore cluster pointer + call chk_update call abort_check mov cx,[InitRDClust] cmp cx,[ClustPerMoby] @@ -2790,6 +3320,10 @@ mov cx,[ClustPerMoby] rd_last_moby: sub [InitRDClust],cx + cmp byte [gfx_ok],0 + jz rd_last_moby_nogfx + call gfx_progress_update +rd_last_moby_nogfx: xor bx,bx ; Load at offset 0 push word xfer_buf_seg ; Bounce buffer segment pop es @@ -2807,9 +3341,13 @@ jne rd_load_loop ; Apparently not rd_load_done: pop si ; Clean up the stack - call crlf - mov si,loading_msg ; Write new "Loading " for - call cwritestr ; the benefit of the kernel + cmp byte [gfx_ok],0 + jnz rd_load_done_gfx + push si + mov si,clrln_msg + call cwritestr + pop si +rd_load_done_gfx: pop es ; Restore original ES ret @@ -2817,6 +3355,10 @@ ; abort_check: let the user abort with or ; abort_check: + cmp byte [gfx_ok],0 + jz abort_check_nogfx + ret +abort_check_nogfx: call pollchar jz ac_ret1 pusha @@ -3398,7 +3940,8 @@ ; getchar: Read a character from keyboard or serial port ; getchar: -.again: mov ah,1 ; Poll keyboard +.again: call chk_update + mov ah,1 ; Poll keyboard int 16h jnz .kbd ; Keyboard input? mov bx,[SerialPort] @@ -3426,6 +3969,15 @@ ; starting with "kaboom.patch" with this part kaboom2: + cmp byte [gfx_ok],0 + jz kaboom2_nogfx + mov si,err_failed_gfx + xor di,di + mov al,1 + call gfx_infobox + call gfx_done + call do_reboot +kaboom2_nogfx: mov si,err_bootfailed call cwritestr call getchar @@ -4162,6 +4714,18 @@ linear_color db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 UsingVGA db 0 + +; +; most of the new stuff is now in suse.inc +; +%include "suse.inc" + +; +; add gfx stuff +; +%include "gfxlogo.inc" + + ; ---------------------------------------------------------------------------------- ; Begin data section ; ---------------------------------------------------------------------------------- @@ -4205,7 +4769,8 @@ db 'booting, and I will take your word for it.', CR, LF, 0 err_badcfg db 'Unknown keyword in syslinux.cfg.', CR, LF, 0 err_noparm db 'Missing parameter in syslinux.cfg.', CR, LF, 0 -err_noinitrd db CR, LF, 'Could not find ramdisk image: ', 0 +err_noinitrd db CR, LF +err_noinitrda db 'Could not find ramdisk image: ', 0 err_nohighmem db 'Not enough memory to load specified kernel.', CR, LF, 0 err_highload db CR, LF, 'Kernel transfer failure.', CR, LF, 0 err_oldkernel db 'Cannot load a ramdisk with an old kernel image.' @@ -4224,6 +4789,12 @@ crlf_msg db CR, LF, 0 crff_msg db CR, FF, 0 syslinux_cfg db 'SYSLINUXCFG' +err_failed_gfx db 'Error reading from disk.', 0 +load_gfx_msg db 'Loading...', 0 +no_msg db 0 +clrln_msg db 0dh, ' ', 0dh, 0 +gfx_ok db 0 + ; ; Command line options we'd like to take a look at ; @@ -4255,6 +4826,13 @@ db 'f8' ; F8 db 'f9' ; F9 db 'f0' ; F10 + + db 'fr' ; framebuffer + db 're' ; readinfo + db 've' ; verbose + db 'gf' ; gfxboot + db 'in' ; initrdsize + dw 0 ; ; Extensions to search for (in *reverse* order). Note that the last @@ -4280,7 +4858,6 @@ KbdTimeOut dw 0 ; Keyboard timeout (if any) FKeyMap dw 0 ; Bitmap for F-keys loaded CmdLinePtr dw cmd_line_here ; Command line advancing pointer -initrd_flag equ $ initrd_ptr dw 0 ; Initial ramdisk pointer/flag VKernelCtr dw 0 ; Number of registered vkernels ForcePrompt dw 0 ; Force prompt @@ -4290,6 +4867,13 @@ 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 +FrameBuffer dw 0 ; Add an appropriate vga= line for kernel fb's +FrameBufferBits dw 8 ; Color depth for the fb +ReadInfo dw 0 ; Get some info from BIOS +ExpInitRDClust dw 0 ; Expected ramdisk size in clusters +InitRDMissing db 0 ; Set if it was missig +initrd_flag db 0 ; used to be overlayed with initrd_ptr !? +SLXOption dw 0 ; control sysliux via cmdline ScrollAttribute db 07h ; White on black (for text mode) ; ; Stuff for the command line; we do some trickery here with equ to avoid @@ -4311,11 +4895,8 @@ 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 +; vgafontbuf is now at 0:5000h +; %if (getcbuf+trackbufsize) > vgafontbuf +; %error "Out of memory, better reorganize something..." +; %endif diff -Naur syslinux-1.62.orig/Makefile syslinux-1.62/Makefile --- syslinux-1.62.orig/Makefile 2001-04-24 22:36:15 +0400 +++ syslinux-1.62/Makefile 2003-02-25 13:52:09 +0300 @@ -20,7 +20,7 @@ CFLAGS = -Wall -O2 -fomit-frame-pointer LDFLAGS = -O2 -s -BINDIR = /usr/bin +BINDIR = $(RPM_BUILD_ROOT)/usr/sbin VERSION = $(shell cat version) @@ -34,7 +34,7 @@ # SOURCES = ldlinux.asm syslinux.asm syslinux.c copybs.asm \ pxelinux.asm pxe.inc mbr.asm gethostip.c \ - isolinux.asm + isolinux.asm suse.inc gfxlogo.inc BTARGET = bootsect.bin ldlinux.sys ldlinux.bin ldlinux.lst \ pxelinux.0 mbr.bin isolinux.bin isolinux-debug.bin ITARGET = syslinux.com syslinux copybs.com gethostip @@ -65,7 +65,7 @@ DATE := $(HEXDATE) endif -ldlinux.bin: ldlinux.asm +ldlinux.bin: ldlinux.asm suse.inc gfxlogo.inc $(NASM) -f bin -dVERSION="'$(VERSION)'" -dDATE_STR="'$(DATE)'" \ -dHEXDATE="$(HEXDATE)" \ -l ldlinux.lst -o ldlinux.bin ldlinux.asm @@ -76,16 +76,18 @@ -dHEXDATE="$(HEXDATE)" \ -l pxelinux.lst -o pxelinux.0 pxelinux.asm -isolinux.bin: isolinux.asm +isolinux.bin: isolinux.asm suse.inc gfxlogo.inc $(NASM) -f bin -dVERSION="'$(VERSION)'" -dDATE_STR="'$(DATE)'" \ -dHEXDATE="$(HEXDATE)" \ -l isolinux.lst -o isolinux.bin isolinux.asm + ./add_crc isolinux.bin # Special verbose version of isolinux.bin -isolinux-debug.bin: isolinux.asm +isolinux-debug.bin: isolinux.asm suse.inc gfxlogo.inc $(NASM) -f bin -dVERSION="'$(VERSION)'" -dDATE_STR="'$(DATE)'" \ -dHEXDATE="$(HEXDATE)" -dDEBUG_MESSAGES \ -l isolinux-debug.lst -o isolinux-debug.bin isolinux.asm + ./add_crc isolinux-debug.bin bootsect.bin: ldlinux.bin dd if=ldlinux.bin of=bootsect.bin bs=512 count=1 @@ -143,7 +145,7 @@ rm -f *~ \#* core spotless: clean dist - rm -f $(BTARGET) + rm -f $(BTARGET) mbr.lst # # Hook to add private Makefile targets for the maintainer. diff -Naur syslinux-1.62.orig/README.SuSE syslinux-1.62/README.SuSE --- syslinux-1.62.orig/README.SuSE 1970-01-01 03:00:00 +0300 +++ syslinux-1.62/README.SuSE 2003-02-25 13:52:27 +0300 @@ -0,0 +1,51 @@ +syslinux/isolinux now support a graphical boot screen using VESA BIOS +extensions. (Note that this is different from the graphics support that +syslinux comes with which uses a 640x480, 16 colors VGA mode). + +To use it you have to prepare a special boot logo file and put a line like +this into syslinux.cfg/iso.linux.cfg: + + gfxboot bootscreen + +The tools to create 'bootscreen' from the above example are in the +gfxboot-devel package. Please _do_ have a look at its documentation before +you begin. + +Note that you currently cannot use comboot images and graphics at the same +time as the memory used for the picture overlaps the comboot loading area. + + +Before starting the Linux kernel syslinux will get some info from the BIOS. +To control this, there are some new options in syslinux.cfg: + + - readinfo + + "readinfo 1" enables the above feature; the default is 0 + "readinfo 2" enables even features + + - framebuffer + + "framebuffer 1" will get the mode number for 640x480x8 from the VESA + BIOS and adds an appropriate vga= line the kernel cmd line. + + "framebuffer " does the same but for the chosen + mode. E.g. "framebuffer 1024 16" sets the frame buffer to 1024x768x16. + Note: this causes problems on some cards as only the mode width is + compared. + + - verbose + + "verbose 1" enables some debug messages + +It is possible to have the initrd on a different disk as the kernel. +syslinux will then ask for a disk change if it doesn't find the initrd. To +use that feature, put a line with + + initrdsize + +into syslinux.cfg (Note: this feature is not available in isolinux). + must be > 0 and should be an approximation of the initrd +size. (The value is used to adjust the progress bar only.) + + + Steffen Winterfeldt diff -Naur syslinux-1.62.orig/suse.inc syslinux-1.62/suse.inc --- syslinux-1.62.orig/suse.inc 1970-01-01 03:00:00 +0300 +++ syslinux-1.62/suse.inc 2003-05-19 19:53:28 +0400 @@ -0,0 +1,1040 @@ +; +; some extra functionality for syslinux +; + +vbe_msg_0 db 'looking for VBE...', 13, 10, 0 +vbe_msg_1 db 'VBE ok', 13, 10, 0 +vbe_msg_2 db 'DDC supported', 13, 10, 0 +vbe_msg_3 db 'got EDID record', 13, 10, 0 +vbe_msg_4 db 'VBE version >= 2.0, looking for frame buffer modes...', 13, 10, 0 +vbe_msg_5 db ' mode found', 13, 10, 0 +vbe_msg_6 db 'x', 0, +vbe_msg_7 db 'fb modes broken', 13, 10, 0 +apm_msg_0 db 'looking for APM...', 13, 10, 0 +apm_msg_1 db 'APM ok', 13, 10, 0 +hd_msg_0 db 'reading mbr...', 13, 10, 0 +hd_msg_1 db 'got mbr', 13, 10, 0 +hd_msg_2 db 'edd?', 13, 10, 0 +hd_msg_3 db 'edd ok', 13, 10, 0 +hd_msg_4 db 'drive 8' +hd_msg_4a db '0h ok', 13, 10, 0 +hd_msg_5 db 'cd type 4 boot', 13, 10, 0 +kbd_msg_0 db 'kbd id?', 13, 10, 0 +kbd_msg_1 db 'got kbd id', 13, 10, 0 +upd_msg_0 db ' Update floppy', 0 +upd_msg_1 db 13, ' ' + db 13, 'Please insert the Driver Update floppy/CDROM; then press a key to continue.', 0 +upd_msg_1a db 'Please insert the Driver Update floppy/CDROM.', 0 +upd_msg_2 db ' Text mode install', 0 +upd_msg_3 db ' Install via serial line', 0 +mod_disk_msg db 'Please insert module disk 1; then press a key to continue.', 0 +mod_disk_msga db 'Please insert module disk 1.', 0 +prod_excl db 'VMware', 0 +prod_excl_end equ $-1 + +do_write_msg db 0 ; set to get some debug messages +wants_update db 0 +wants_serial db 0 +do_nogfx db 0 +no_fkeys db 0 +vmode_shown db 0 +hd_disk db 80h +expert_txt db ' ', 0 +expert_txt_ofs dw 0 +expert_txt_seg dw 0 +dec_buf zb 10h +vbe_mode_parm db ' vga=0x', 0 +; buffer for our added command line parametes +lxrc_vga_ptr dw 0 +lxrc_vga_len dw 0 +vga_txt_ofs dw 0 +vga_txt_seg dw 0 +ddc_timings dw 0 +video_mem dw 0 +fb_mode_0 dw 0 ; 640x480 +fb_mode_1 dw 0 ; 800x600 +fb_mode_2 dw 0 ; 1024x768 +fb_bits_0 db 0 +fb_bits_1 db 0 +fb_bits_2 db 0 +video_mode db 1 +vga_parm_cnt db 0 +xread_pack db 10h ; packet size + db 0 ; reserved + dw 1 ; sector count + dw mi_buf ; buffer offset +xread_pack_seg dw 0 ; buffer segment + dd 0, 0 ; sector number + +lxrc_ptr dw lxrc_data1 +lxrc_data db ' altcode=' +lxrc_data1 zb 0fah + +; +; Read EDID record via DDC and create an appropriate +; lxrc=... command line entry. +; +read_ddc: + pushad ; don't modify any regs + push es + push ds + pop es + mov si,vbe_msg_0 + call xwritestr + mov di,vbe_buf + mov dword [di],32454256h ; 'VBE2' + mov ax,4f00h + int 10h + cmp ax,4fh + jnz near read_ddc_done + mov ax,[vbe_buf+12h] + mov [video_mem],ax + mov si,vbe_msg_1 + call xwritestr + xor cx,cx + xor dx,dx + mov ax,4f15h + mov bl,0 + int 10h + cmp ax,4fh + jnz near read_ddc_done + mov si,vbe_msg_2 + call xwritestr + push ds + pop es + mov di,ddc_buf + push di + mov cx,80h + xor ax,ax + rep stosb + pop di + mov ax,4f15h + mov bl,1 + xor cx,cx + xor dx,dx + int 10h + cmp ax,4fh + jnz near read_ddc_done + mov si,vbe_msg_3 + call xwritestr + mov si,[lxrc_ptr] + mov bx,ddc_buf + +%if 0 + mov ax,[bx+08h] + xchg al,ah ; big endian! + call unpack_eisa + + mov al,[bx+0bh] + call byte_to_hex + mov al,[bx+0ah] + call byte_to_hex + mov al,[bx+15h] + call byte_to_hex + mov al,[bx+16h] + call byte_to_hex +%endif + mov al,[bx+23h] + mov [ddc_timings],al +%if 0 + call byte_to_hex +%endif + mov al,[bx+24h] + mov [ddc_timings+1],al +%if 0 + call byte_to_hex + xor di,di +read_ddc_50: + mov ax,[bx+di+26h] + cmp ax,0000h + jz read_ddc_60 + cmp ax,0101h + jz read_ddc_60 + call byte_to_hex + mov al,ah + call byte_to_hex + inc di + inc di + cmp di,10h + jb read_ddc_50 +read_ddc_60: + mov al,[bx+11h] + call byte_to_hex + xor di,di +read_ddc_61: + mov eax,[bx+di+36h] + shl eax,8 + jnz read_ddc_69 + mov al,[bx+di+36h+3] + cmp al,0fch + jb read_ddc_69 + sub al,0fch + mov byte [si],'^' + inc si + mov [si],al + add byte [si],'0' + inc si + cmp al,1 + jnz read_ddc_62 + mov al,[bx+di+36h+5] + call byte_to_hex + mov al,[bx+di+36h+6] + call byte_to_hex + mov al,[bx+di+36h+7] + call byte_to_hex + mov al,[bx+di+36h+8] + call byte_to_hex + jmp read_ddc_69 +read_ddc_62: + push di + lea di,[bx+di+36h+5] + mov dx,0dh +read_ddc_63: + mov al,[di] + inc di + cmp al,0 + jz read_ddc_65 + cmp al,0ah + jz read_ddc_65 + cmp al,20h + ja read_ddc_64 + mov al,'_' +read_ddc_64: + mov [si],al + inc si + dec dx + jnz read_ddc_63 +read_ddc_65: + pop di +read_ddc_69: + add di,12h + cmp di,4*12h + jb read_ddc_61 +%endif + + mov [lxrc_ptr],si + mov byte [si],0 + +read_ddc_done: + pop es + popad + ret + +; get apm capabilities & VBE video memory size +read_apm: + pushad ; don't modify any regs + push es + push ds + pop es + + mov si,[lxrc_ptr] + mov byte [si],',' + inc word [lxrc_ptr] + + mov si,apm_msg_0 + call xwritestr + mov ax,5300h + xor bx,bx + int 15h + jc read_apm_done + push cx + push ax + mov si,apm_msg_1 + call xwritestr + pop ax + + mov si,[lxrc_ptr] + + shl ah,4 + and al,0fh + or al,ah + call byte_to_hex + + pop ax + call byte_to_hex + + ; add VBE version info + + mov ax,[vbe_buf+4] + shl ah,4 + and al,0fh + or al,ah + call byte_to_hex + + ; add video mem size + + mov ax,[vbe_buf+12h] + xchg al,ah + call byte_to_hex + xchg al,ah + call byte_to_hex + + mov [lxrc_ptr],si + mov byte [si],0 + +read_apm_done: + pop es + popad + ret + +; read 1st hd sector & compute crc +read_hd: + pushad ; don't modify any regs + push es + push ds + pop es + + mov si,[lxrc_ptr] + mov byte [si],',' + inc word [lxrc_ptr] + mov byte [si + 1],0 + + ; maybe we booted from cdrom with an hd image + ; (special magic from our mbr loader) + cmp byte [7c03h],19 + jnz read_hd_03 + mov byte [hd_disk],81h + mov byte [hd_msg_4a],'1' + mov si,hd_msg_5 + call xwritestr +read_hd_03: + + mov si,hd_msg_2 + call xwritestr + + mov ah,41h + mov bx,55aah + mov dl,[hd_disk] + int 13h + mov bp,0 + jc read_hd_05 + cmp bx,0aa55h + jnz read_hd_05 + test cl,1 + jz read_hd_05 + + inc bp + + mov si,hd_msg_3 + call xwritestr + +read_hd_05: + mov si,hd_msg_0 + call xwritestr + + mov ah,10h + mov dl,[hd_disk] + push bp + int 13h + pop bp + jc read_hd_done + cmp ah,0 + jnz read_hd_done + + mov si,hd_msg_4 + call xwritestr + + mov ax,0201h + mov cx,1 + mov dh,ch ; dh = 0 + mov dl,[hd_disk] + mov bx,mi_buf + push bp + int 13h + pop bp + jc near read_hd_done + + mov si,hd_msg_1 + call xwritestr + + mov si,mi_buf + xor ebx,ebx + mov cx,200h + mov edi,57 + stc + sbb eax,eax +read_hd_20: + mov bl,[si] + inc si + add eax,ebx + mul edi + dec cx + jnz read_hd_20 + + mov si,[lxrc_ptr] + + mov bx,4 +read_hd_40: + rol eax,8 + call byte_to_hex + dec bx + jnz read_hd_40 + + or bp,bp + jz read_hd_90 + mov byte [si],'.' + inc si + +read_hd_90: + mov [lxrc_ptr],si + mov byte [si],0 + +read_hd_done: + pop es + popad + ret + +; read keyboard id +read_kbd: + pushad ; don't modify any regs + push es + push ds + pop es + + mov si,[lxrc_ptr] + mov byte [si],',' + inc word [lxrc_ptr] + + mov si,kbd_msg_0 + call xwritestr + mov ax,900h + int 16h + test al,10h + jz read_kbd_done + + mov si,kbd_msg_1 + call xwritestr + mov ah,0ah + xor bx,bx + int 16h + + mov si,[lxrc_ptr] + mov al,bh + call byte_to_hex + mov al,bl + call byte_to_hex + + mov [lxrc_ptr],si + mov byte [si],0 + +read_kbd_done: + pop es + popad + ret + +; +; Read VBE2 mode info +; +; We use the VBE record returned earlier by the DDC calls. +; +; Go through the mode list and look for a video mode with frame buffer +; support. +; +read_vbe_modes: + pushad ; don't modify any regs + push es + push gs + push ds + pop es + + cmp word [FrameBuffer],byte 0 + jz near read_vbe_done + cmp word [vbe_buf+4],200h + jb near read_vbe_done + mov si,vbe_msg_4 + call xwritestr + xor ebx,ebx + lgs bx,[vbe_buf+1ah] + mov eax,gs + shl eax,4 + add eax,ebx + or eax,eax + jz read_vbe_05 + cmp eax,100000h + jae read_vbe_05 + call check_prod_excl + jc read_vbe_05 + mov si,vbe_msg_7 + call xwritestr + jmp near read_vbe_done +read_vbe_05: + lgs bx,[vbe_buf+0eh] +read_vbe_10: + mov cx,[gs:bx] + inc bx + inc bx + cmp cx,0xffff + jz near read_vbe_25 + + mov ax,4f01h + mov di,mi_buf + push cx + int 10h + pop cx + cmp ax,4fh + jnz read_vbe_10 + +read_vbe_15: + test byte [mi_buf],1 ; mode supported? + jz read_vbe_10 + cmp dword [mi_buf+28h],byte 0 ; frame buffer start + jz read_vbe_10 + + mov esi,[mi_buf+12h] ; size + mov dl,[mi_buf+1bh] ; color mode (aka memory model) + mov dh,[mi_buf+19h] ; color depth + cmp dl,6 ; direct color + jnz read_vbe_16 + sub dh,[mi_buf+25h] ; reserved color bits + jmp read_vbe_17 +read_vbe_16: + cmp dl,4 ; PL8 + jnz read_vbe_10 + mov dh,8 +read_vbe_17: + + cmp esi,640 + (400 << 16) + jz read_vbe_10 ; skip 640x400 mode + + mov ax,[FrameBuffer] + cmp ax,1 + jz read_vbe_20 + + cmp si,ax + jnz read_vbe_10 + + mov ax,[FrameBufferBits] + cmp al,dh + jnz read_vbe_10 + + mov [fb_mode_0],cx + mov [fb_bits_0],dh + + jmp read_vbe_25 + +read_vbe_20: + cmp dh,8 ; color bits: 8 or 16 + jz read_vbe_205 + cmp dh,16 + jnz read_vbe_10 + +read_vbe_205: + cmp dh,[fb_bits_0] + jbe read_vbe_21 + cmp esi,640 + (480 << 16) + jnz read_vbe_21 + mov [fb_mode_0],cx + mov [fb_bits_0],dh +read_vbe_21: + cmp dh,[fb_bits_1] + jbe read_vbe_22 + cmp esi,800 + (600 << 16) + jnz read_vbe_22 + mov [fb_mode_1],cx + mov [fb_bits_1],dh +read_vbe_22: + cmp dh,[fb_bits_2] + jbe read_vbe_23 + cmp esi,1024 + (768 << 16) + jnz read_vbe_23 + mov [fb_mode_2],cx + mov [fb_bits_2],dh +read_vbe_23: + xor ax,ax + xor cx,cx + cmp byte [fb_bits_0],16 + adc ax,cx + cmp byte [fb_bits_1],16 + adc ax,cx + cmp byte [fb_bits_2],16 + adc ax,cx + ; early out if all 3 modes have been found + jnz near read_vbe_10 + +read_vbe_25: + mov cx,[fb_mode_0] + or cx,cx + jz read_vbe_done + + cmp word [fb_mode_1],byte 0 + jz read_vbe_28 + test word [ddc_timings],0f7c0h + jnz read_vbe_27 + cmp word [video_mem],0x3e ; at least 4MB-128k + jb read_vbe_28 +read_vbe_27: + mov cx,[fb_mode_1] + mov byte [video_mode],2 +read_vbe_28: + + cmp word [fb_mode_2],byte 0 + jz read_vbe_29 + test word [ddc_timings],0f000h + jz read_vbe_29 + mov cx,[fb_mode_2] + mov byte [video_mode],3 +read_vbe_29: + +%if 0 + mov ax,[mi_buf+12h] + call xwritedec + mov si,vbe_msg_6 + call xwritestr + mov ax,[mi_buf+14h] + call xwritedec + mov si,vbe_msg_6 + call xwritestr + mov ax,[FrameBufferBits] + call xwritedec + mov si,vbe_msg_5 + call xwritestr +%endif + add ch,2 ; for linux kernel + + mov di,[lxrc_ptr] + + ; check if the SuSE string is empty + cmp di,lxrc_data1 + jnz read_vbe_70 + mov di,lxrc_data +read_vbe_70: + + mov si,vbe_mode_parm + mov [lxrc_vga_ptr],di +read_vbe_80: + lodsb + stosb + or al,al + jnz read_vbe_80 + lea si,[di-1] + xchg ax,cx + xchg al,ah + call byte_to_hex + mov al,ah + call byte_to_hex + + mov [lxrc_ptr],si + mov byte [si],0 + sub si,[lxrc_vga_ptr] + mov [lxrc_vga_len],si + +read_vbe_done: + pop gs + pop es + popad + ret + + +; go through exclude list +; +; in: gs:bx product string +; out: CF 0/1 found/not found +; +check_prod_excl: + cld + mov si,prod_excl +check_prod_excl_20: + mov di,bx + dec di +check_prod_excl_30: + inc di + lodsb + or al,al + jz check_prod_excl_90 + cmp al,[gs:di] + jz check_prod_excl_30 +check_prod_excl_40: + lodsb + or al,al + jnz check_prod_excl_40 + cmp si,prod_excl_end + jb check_prod_excl_20 + stc +check_prod_excl_90: + ret + +; unpack EISA ID +; ax -> [si] +; +unpack_eisa: + mov cx,ax + shr cx,10 + and cl,1fh + add cl,'A'-1 + mov [si],cl + mov cx,ax + shr cx,5 + and cl,1fh + add cl,'A'-1 + mov [si+1],cl + mov cx,ax + and cl,1fh + add cl,'A'-1 + mov [si+2],cl + add si,3 + ret + +; al -> to hex +; +byte_to_hex: + mov cl,al + shr cl,4 + call byte_to_hex_10 + mov cl,al + and cl,0fh +byte_to_hex_10: + cmp cl,10 + jb byte_to_hex_20 + add cl,7 +byte_to_hex_20: + add cl,'0' + mov [si],cl + inc si + ret + +; +; write function +; +xwritestr: + cmp byte [cs:do_write_msg],0 + jz xwritestr_10 + call cwritestr +xwritestr_10: + ret + +; +; ax: Number +; +xwritedec: + pusha + mov si,dec_buf+0fh + mov byte [si],0 +xwritedec_20: + xor dx,dx + mov cx,10 + div cx + add dl,'0' + dec si + mov [si],dl + or ax,ax + jnz xwritedec_20 + call xwritestr + popa + ret + +; +; see if user wants to use an update disk +; +chk_update: + cmp byte [gfx_ok],0 + jz chk_update_nogfx + ret +chk_update_nogfx: + pusha + clc + mov ah,12h + int 16h + jc chk_update_90 + + cmp byte [wants_serial],0 + jnz chk_update_20 + test ah,08h ; right ALT key + jz chk_update_20 + mov byte [wants_serial],1 + mov cx,1737h + mov si,upd_msg_3 + push ax + call cwritestr_xy + pop ax + +chk_update_20: + cmp byte [wants_update],0 + jnz chk_update_50 + test ah,02h ; left ALT key + jz chk_update_50 + mov byte [wants_update],1 + mov cx,183bh + mov si,upd_msg_0 + push ax + call cwritestr_xy + pop ax + +chk_update_50: + cmp byte [video_mode],0 + jz chk_update_90 + test ah,01h ; left Ctrl key + jz chk_update_90 + mov byte [video_mode],0 + mov cx,1737h + mov si,upd_msg_2 + call cwritestr_xy + +chk_update_90: + popa + ret + +; +; cl, ch: x,y +; si: text +; +cwritestr_xy: + push ds + pusha + push cx + mov ah,3 + mov bh,0 + int 10h + pop cx + push dx + mov dx,cx + mov ah,2 + mov bh,0 + int 10h + call cwritestr +cwritestr_xy_80: + pop dx + mov ah,2 + mov bh,0 + int 10h +cwritestr_xy_90: + popa + pop ds + ret + +; +; wait for any key pressed +; +wait_for_key: + pusha + mov ah,2 + int 16h + mov cl,al + mov ah,1 + int 16h + mov dx,0 + jz wait_for_key_10 + mov dx,ax +wait_for_key_10: + mov ah,2 + int 16h + mov ch,al + mov ah,1 + int 16h + jnz wait_for_key_50 + xor ax,ax +wait_for_key_50: + cmp ax,dx + jnz wait_for_key_90 + cmp ch,cl + jz wait_for_key_10 +wait_for_key_90: + popa + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +vmode_msg_0 db 'F2=Text mode' +vmode_msg_1 db 'F3=640x480' +vmode_msg_2 db 'F4=800x600' +vmode_msg_3 db 'F5=1024x768' +vmode_msg_clr times vmode_msg_clr - vmode_msg_0 + 3 * 3 db ' ' +vmode_msg_end equ $ + +show_vmode: + push es + pusha + + cmp byte [no_fkeys],0 + jnz near show_vmode_95 + + mov ah,3 + mov bh,0 + int 10h + push dx + + mov byte [vmode_shown],1 + + push ds + pop es + + mov dx,1800h + mov cx,vmode_msg_1 - vmode_msg_0 + mov bp,vmode_msg_0 + mov bx,07h + cmp byte [video_mode],0 + jnz show_vmode_10 + mov bl,70h +show_vmode_10: + mov ax,1300h + int 10h + + mov dh,18h + mov dl,vmode_msg_1 - vmode_msg_0 + 3 + mov cx,vmode_msg_2 - vmode_msg_1 + mov bp,vmode_msg_1 + mov bx,07h + cmp byte [video_mode],1 + jnz show_vmode_20 + mov bl,70h +show_vmode_20: + mov ax,1300h + int 10h + + cmp word [fb_mode_1],byte 0 + jz show_vmode_40 + + mov dh,18h + mov dl,vmode_msg_2 - vmode_msg_0 + 2 * 3 + mov cx,vmode_msg_3 - vmode_msg_2 + mov bp,vmode_msg_2 + mov bx,07h + cmp byte [video_mode],2 + jnz show_vmode_30 + mov bl,70h +show_vmode_30: + mov ax,1300h + int 10h +show_vmode_40: + + cmp word [fb_mode_2],byte 0 + jz show_vmode_60 + + mov dh,18h + mov dl,vmode_msg_3 - vmode_msg_0 + 3 * 3 + mov cx,vmode_msg_clr - vmode_msg_3 + mov bp,vmode_msg_3 + mov bx,07h + cmp byte [video_mode],3 + jnz show_vmode_50 + mov bl,70h +show_vmode_50: + mov ax,1300h + int 10h +show_vmode_60: + + +show_vmode_90: + pop dx + mov ah,2 + mov bh,0 + int 10h + +show_vmode_95: + + popa + pop es + ret + +hide_vmode: + pusha + cmp byte [vmode_shown],0 + jz hide_vmode_90 + + mov ah,3 + mov bh,0 + int 10h + push dx + + mov dx,1800h + mov cx,vmode_msg_end - vmode_msg_clr + mov bp,vmode_msg_clr + mov bx,07h + mov ax,1300h + int 10h + + pop dx + mov ah,2 + mov bh,0 + int 10h + +hide_vmode_90: + popa + ret + +process_fkeys: + cmp al,1 + jb process_fkeys_90 + cmp al,5 + cmc + jc process_fkeys_90 + + cmp al,3 + jnz process_fkeys_20 + cmp word [fb_mode_1],byte 0 + jz process_fkeys_90 +process_fkeys_20: + cmp al,4 + jnz process_fkeys_30 + cmp word [fb_mode_2],byte 0 + jz process_fkeys_90 +process_fkeys_30: + + mov [video_mode],al + sub byte [video_mode],1 + call show_vmode + clc +process_fkeys_90: + ret + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; do a reboot +; +do_reboot: + call gfx_done + mov word [472h],1234h + push word 0ffffh + push word 0 + retf + int 19h + jmp $ + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; look for a fsc notebook lcd panel and set ddc_timings +read_fsc: + pushad + push es + push ds + cmp word [ddc_timings],byte 0 + jnz read_fsc_90 + + push word 0xf000 + pop ds + xor di,di +read_fsc_10: + cmp dword [di],0x696a7546 + jnz read_fsc_30 + cmp dword [di+4],0x20757374 + jnz read_fsc_30 + mov cx,0x20 + xor bx,bx + mov si,di +read_fsc_20: + lodsb + add bl,al + dec cx + jnz read_fsc_20 + or bl,bl + jnz read_fsc_30 + mov al,[di+23] + and al,0xf0 + jnz read_fsc_90 + mov bl,[di+21] + and bx,0xf0 + shr bx,3 + mov ax,[cs:bx+fsc_bits] + mov [cs:ddc_timings],ax + jmp read_fsc_90 +read_fsc_30: + add di,0x10 + jnz read_fsc_10 +read_fsc_90: + pop ds + pop es + popad + ret + +fsc_bits: + dw 0, 0x0020, 0x0200, 0x4000, 0x4000, 0x4000, 0, 0x0200 + dw 0x4000, 0, 0, 0, 0, 0, 0, 0 +