NULL
};
+extern int create_args_and_load(char *);
+
void execute(const char *cmdline, enum kernel_type type)
{
const char *p, *const *pp;
if (type == KT_COM32) {
/* new entry for elf format c32 */
- char **argv;
- int i, argc;
-
- q = args;
- for (argc = 0; *q; q++) {
- argc++;
-
- /* Find the end of this arg */
- while(*q && !my_isspace(*q))
- q++;
-
- /*
- * Now skip all whitespace between arguments.
- */
- while (*q && my_isspace(*q))
- q++;
- }
-
- /*
- * Generate a copy of argv on the stack as this is
- * traditionally where process arguments go.
- *
- * argv[0] must be the command name, so bump argc to
- * include argv[0].
- */
- argc += 1;
- argv = alloca(argc * sizeof(char *));
- argv[0] = kernel;
-
- for (q = args, i = 1; i < argc - 1; i++) {
- char *start;
- int len = 0;
-
- start = q;
-
- /* Find the end of this arg */
- while(*q && !my_isspace(*q)) {
- q++;
- len++;
- }
-
- argv[i] = malloc(len + 1);
- strncpy(argv[i], start, len);
- argv[i][len] = '\0';
-
- /*
- * Now skip all whitespace between arguments.
- */
- while (*q && my_isspace(*q))
- q++;
- }
-
- argv[argc] = NULL;
- spawn_load(kernel, argc, argv);
+ lfree(kernel);
+ create_args_and_load(cmdline);
} else if (type == KT_KERNEL) {
/* Need add one item for kernel load, as we don't use
* the assembly runkernel.inc any more */
+++ /dev/null
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; bootsect.inc
-;;
-;; Load a boot sector (or other bootstrap program.)
-;;
-;; Unlike previous versions of this software, this doesn't require that
-;; the length is 512 bytes. This allows PXE bootstraps and WinNT
-;; "CD boot sectors" to be invoked.
-;;
-
-;
-; Load a boot sector
-;
-is_bootsector:
-%if IS_SYSLINUX
- ; Transfer zero bytes
- push word 0
- jmp short load_bootsec
-
-is_bss_sector:
- ; Transfer the superblock
-SuperSize equ $+1
- push word superblock_len_fat16
-%endif
-load_bootsec:
- mov edi,free_high_memory
- mov [trackbuf+4],edi ; Copy from this address
- xor dx,dx ; No padding
- mov bx,abort_check ; Don't print dots, but allow abort
- call load_high
-
- sub edi,free_high_memory
- mov [trackbuf+8],edi ; Save length
-
- mov eax,7C00h ; Entry point
- mov [trackbuf],eax ; Copy to this address
-
-%if IS_SYSLINUX
- xor ecx,ecx
- pop cx
-
- ; For a BSS boot sector we have to patch.
- mov esi,superblock
- mov edi,free_high_memory+(superblock-bootsec)
- call bcopy
-%endif
- push eax ; Save entry point
-
- xor edx,edx
- xor esi,esi
-%if IS_SYSLINUX || IS_EXTLINUX
- ; Restore original FDC table
- mov eax,[OrigFDCTabPtr]
- mov [fdctab],eax
-
- mov dl,[DriveNumber]
- mov si,PartInfo ; Partition info buffer
- mov di,800h-18 ; Put partition info here
- push di
- mov cx,8 ; 16 bytes
- xor ax,ax
- rep movsw
- pop si ; DS:SI points to partition info
- xor bx,bx
-%elif IS_ISOLINUX
- mov dl,[DriveNumber]
- xor bx,bx
-%elif IS_PXELINUX
- mov byte [KeepPXE],03h ; Chainloading + keep PXE
- pm_call reset_pxe
- lfs si,[InitStack]
- ; Put restore DS, EDX and ESI to the true initial values
- mov bx,[fs:si+6]
- mov edx,[fs:si+28]
- mov esi,[fs:si+12]
-%endif
-
-;
-; replace_bootstrap for the special case where we have exactly one
-; descriptor, based in low memory. We will generate a second descriptor
-; to clear remaining FBM.
-;
-
-replace_bootstrap_one:
- mov eax,[trackbuf] ; Base address
- add eax,[trackbuf+8] ; Length
- movzx ecx,word [BIOS_fbm]
- shl ecx,10 ; Free Base Memory
- sub ecx,eax
- mov [trackbuf+12],eax
- or dword [trackbuf+16],-1 ; Zero memory
- mov [trackbuf+20],ecx
- push word 2 ; Length of descriptor list
- ; Fall through
-
-;
-; Entrypoint for "shut down and replace bootstrap" -- also invoked by
-; the COMBOOT API. This routine expects the entry point (CS, IP) and the
-; count of the descriptor sequence on the stack; the shuffle
-; descriptors start at the first byte of the trackbuf.
-;
-; The registers EDX and ESI are passed on to the called program,
-; and BX is passed on as DS.
-;
-replace_bootstrap:
- ;
- ; Prepare for shutting down
- ;
- call vgaclearmode
-
-;
-; We jump here when loading a kernel image, so that we don't reset
-; the screen mode in "quiet" mode
-;
-replace_bootstrap_noclearmode:
- call cleanup_hardware
-
- ;
- ; Set up initial stack frame (not used by PXE if keeppxe is
- ; set - we use the PXE stack then.)
- ;
- xor ax,ax
- mov ds,ax
- mov es,ax
-
-%if IS_PXELINUX
- cmp byte [KeepPXE],0
- je .stdstack
- les di,[InitStack] ; Reset stack to PXE original
- jmp .stackok
-%endif
-.stdstack:
- ; StackBuf is guaranteed to have 44 bytes free immediately
- ; above it, and it will not interfere with our existing stack.
- mov di,StackBuf
- push di
- mov cx,22 ; 44 bytes
- rep stosw
- pop di
-.stackok:
-
- mov [es:di+28],edx ; New EDX
- mov [es:di+12],esi ; New ESI
- mov [es:di+6],bx ; New DS
-
-%if IS_PXELINUX == 0
- ; DON'T DO THIS FOR PXELINUX...
- ; For PXE, ES:BX -> PXENV+, and this would corrupt
- ; that use.
-
- ; Restore ES:DI -> $PnP (if we were ourselves called
- ; that way...)
- mov ax,[OrigESDI]
- mov bx,[OrigESDI+2]
-
- mov [es:di+8],ax ; New DI
- mov [es:di+4],bx ; New ES
-%endif
- pop ax ; descriptor list entries count
-
- push di
- push es
-
- push ds
- pop es
-
- mov ebx,trackbuf
- imul di,ax,12
- push di ; length of list
- add di,bx ; DI <- end of list
-
- ; Terminating entry...
- lea eax,[replace_stub] ; Entrypoint
- push ax
- stosd
- xor ax,ax ; EAX[31:16] == 0 already
- stosd ; 16-bit mode
- stosd ; End of list
-
- ; Copy the stub
- pop di
- mov si,__replacestub_lma
- mov cx,__replacestub_dwords
- rep movsd
-
- ; ECX <- final list length
- xor ecx,ecx
- pop cx ; original length in bytes
- add cx, 12 ; + termination entry size
-
- pop word [replace_stub.ss]
- pop word [replace_stub.esp]
- pop dword [replace_stub.csip]
-
- cli
- mov ss,[replace_stub.ss]
- mov esp,[replace_stub.esp]
-
- mov edi,trackbuf
- mov esi,edi
-
- jmp shuffle_and_boot_raw
-
- ; This stub gets run after the shuffle. It is copied
- ; below 0x7c00 in order to properly handle the case
- ; of bootstrap replacement.
- section .replacestub
-replace_stub:
- mov cr0,eax
- jmp 0:.next
-.next:
- mov ax,strict word 0
-.ss equ $-2
- mov ss,ax
- mov esp,strict dword 0
-.esp equ $-4
- pop gs
- pop fs
- pop es
- pop ds
- popad
- popfd
- jmp 0:0
-.csip equ $-4
-
- section .text16
+++ /dev/null
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
-;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; cmdline.inc
-;;
-;; Common routine to assemble [null-terminated] command line into
-;; real_mode_seg:cmd_line_here.
-;; Not used by plain kernel due to BOOT_IMAGE= etc.
-;;
-
- section .text16
-
-;
-; Assumes DS == CS
-;
-make_plain_cmdline:
- push es
- ; ui.inc has already copied any APPEND options
- mov ax,real_mode_seg
- mov es,ax
-
- mov di,[CmdLinePtr]
- call do_ip_append
-
- mov si,[CmdOptPtr]
-
- call strcpy
-
- dec di
- mov [CmdLinePtr],di
- mov byte [es:di],0 ; Null-terminate
-
- pop es
- ret
-
-;
-; Actual IPAppend strings...
-;
-%if IS_PXELINUX
- extern IPOption, BOOTIFStr, SYSUUIDStr
- global IPAppends, numIPAppends
-
- section .data16
- alignz 2
-IPAppends dw IPOption
- dw BOOTIFStr
- dw SYSUUIDStr
-numIPAppends equ ($-IPAppends)/2
-%else
-IPAppends equ 0
-numIPAppends equ 0
-%endif
-
-;
-; Handle "ipappend" strings, if applicable
-;
-; Assumes DS == CS; pushes output to ES:DI
-;
- section .text16
-
-do_ip_append:
-%ifndef DEPEND
- %if numIPAppends > 0
- push cx
- push bx
- push si
-
- mov bx,IPAppends
- mov cx,[IPAppend]
- and cx,(1 << numIPAppends)-1
-.loop:
- jcxz .done
- mov si,[bx]
- inc bx
- inc bx
- test cl,1
- jz .not_this
-
- call strcpy
- mov byte [es:di-1],' ' ; Replace final null with space
-.not_this:
- shr cx,1
- jmp .loop
-.done:
- pop si
- pop bx
- pop cx
- %endif
-%endif
- ret
;
com32_entry equ free_high_memory
- section .text16
-is_com32_image:
- push si ; Save file handle
- push eax ; Save file length
-
- call make_plain_cmdline
- ; Copy the command line into the low cmdline buffer
- mov ax,real_mode_seg
- mov fs,ax
- mov si,cmd_line_here
- mov di,command_line
- mov cx,[CmdLinePtr]
- inc cx ; Include final null
- sub cx,si
- fs rep movsb
-
- mov si,KernelName
- mov di,Com32Name
- call strcpy
-
- call comboot_setup_api ; Set up the COMBOOT-style API
-
- mov edi,com32_entry ; Load address
- pop eax ; File length
- pop si ; File handle
- xor dx,dx ; No padding
- mov bx,abort_check ; Don't print dots, but allow abort
- call load_high
-
- mov esi,com32_entry
- mov edi,trackbuf
- mov ecx,5
- call bcopy
- cmp dword [trackbuf],0xcd4cfeb8
- jne not_com32r
- cmp byte [trackbuf+4],0x21
- jne not_com32r
-
-com32_start:
- ;
- ; Point the stack to the end of (permitted) high memory
- ;
- mov eax,[HighMemRsvd]
- xor ax,ax ; Align to a 64K boundary
- mov [PMESP],eax
- mov ebx,.pm ; Where to go in PM
- jmp enter_pm
-
-;
-; This is invoked right before the actually starting the COM32
-; progam, in 32-bit mode...
-;
- bits 32
- section .text
-.pm:
- ; Set up the calling stack frame
-
- push dword pm_api_vector
- push dword Com32Name ; Module filename
- push dword [HighMemSize] ; Memory managed by Syslinux
- push dword core_cfarcall ; Cfarcall entry point
- push dword core_farcall ; Farcall entry point
- push dword (1 << 16) ; 64K bounce buffer
- push dword core_real_mode ; Bounce buffer address
- push dword core_intcall ; Intcall entry point
- push dword command_line ; Command line pointer
- push dword 9 ; Argument count
- sti ; Interrupts OK now
- call com32_entry ; Run the program...
- ; ... on return, fall through to com32_exit ...
-com32_exit:
- mov bx,comboot_return
- jmp enter_rm
-
bits 16
- section .text16
-not_com32r:
- mov si,KernelName
- call writestr
- mov si,not_com32r_msg
- call writestr
- jmp enter_command
-
section .data16
-not_com32r_msg db ': not a COM32R image', CR, LF, 0
; Ersatz com32 invocation structure, to make libcom32
; code run the same if linked to the core. This is in
;;
;; Common code for running a COMBOOT image
;;
-
section .text16
; Parameter registers definition; this is the definition
%define P_DI word [bp]
%define P_HDI word [bp+2]
-; Looks like a COMBOOT image but too large
-comboot_too_large:
- pm_call pm_close_file
- mov si,err_comlarge
- call writestr
- jmp enter_command
-
-;
-; Load a COMBOOT image. A COMBOOT image is basically a DOS .COM file,
-; except that it may, of course, not contain any DOS system calls. We
-; do, however, allow the execution of INT 20h to return to SYSLINUX.
-;
-is_comboot_image:
- push si ; Save file handle
-
- call make_plain_cmdline
-
- call comboot_setup_api
-
- mov cx,comboot_seg
- mov es,cx
-
- xor di,di
- mov cx,64 ; 256 bytes (size of PSP)
- xor eax,eax ; Clear PSP
- rep stosd
-
- mov word [es:0], 020CDh ; INT 20h instruction
- ; First non-free paragraph
- ; This is valid because comboot_seg == real_mode_seg
- ; == the highest segment used by all derivatives
- int 12h ; Get DOS memory size
- shl ax,6 ; Kilobytes -> paragraphs
- mov word [es:02h],ax
-
-%ifndef DEPEND
-%if real_mode_seg != comboot_seg
-%error "This code assumes real_mode_seg == comboot_seg"
-%endif
-%endif
- ; Copy the command line from high memory
- mov si,cmd_line_here
- mov cx,125 ; Max cmdline len (minus space and CR)
- mov di,081h ; Offset in PSP for command line
- mov al,' ' ; DOS command lines begin with a space
- stosb
-
-.loop: es lodsb
- and al,al
- jz .done
- stosb
- loop .loop
-.done:
-
- mov al,0Dh ; CR after last character
- stosb
- mov ax,di
- sub al,82h ; Include space but not CR
- mov [es:80h],al ; Store command line length
-
- ; Now actually load the file...
- pop si ; File handle
- mov bx,100h ; Load at <seg>:0100h
- mov cx,0FF00h ; Maximum number of bytes
- pm_call getfsbytes
- cmp ecx,65536-256-2 ; Maximum size
- ja comboot_too_large
-
- ; And invoke the program...
- mov ax,es
- mov ds,ax
- mov ss,ax
- xor sp,sp
- push word 0 ; Return to address 0 -> exit
-
- jmp comboot_seg:100h ; Run it
-
;
; Set up the COMBOOT API interrupt vectors. This is now done at
; initialization time.
mov es,bp
mov bp,sp ; Set up stack frame
- call _adjust_screen ; The COMBOOT program might have changed the screen
+ pm_call pm_adjust_screen ; The COMBOOT program might hav changed the screen
mov cx,int21_count
mov si,int21_table
jmp comboot_exit_msg
comboot_bogus_tail:
xchg ax,dx
- call writehex2 ; Interrupt number
+ pm_call pm_writehex2 ; Interrupt number
mov al,' '
- call writechr
+ pm_call pm_writechr
xchg ax,dx
- call writehex4 ; Function number (AX)
+ pm_call pm_writehex4 ; Function number (AX)
mov al,' '
- call writechr
+ pm_call pm_writechr
mov eax,edi
- call writehex8 ; CS:IP of the origin
- call crlf
- jmp enter_command
+ pm_call pm_writehex8 ; CS:IP of the origin
+ pm_call crlf
+ jmp kaboom
; Proper return vector
; Note: this gets invoked both via INT 21h and directly via INT 20h.
pop bx ; Return address
RESET_STACK_AND_SEGS si ; Contains sti, cld
pm_call comboot_cleanup_lowmem
- call _adjust_screen ; The COMBOOT program might have changed the screen
+ pm_call pm_adjust_screen; The COMBOOT program might have change the screen
jcxz .nomsg
mov si,KernelName
- call writestr
+ pm_call pm_writestr
mov si,cx
- call writestr
+ pm_call pm_writestr
.nomsg:
jmp bx
; INT 21h system calls
;
comboot_getkey: ; 01 = get key with echo
- call vgashowcursor
+ pm_call vgashowcursor
call comboot_getchar
- call vgahidecursor
- call writechr
+ pm_call vgahidecursor
+ pm_call pm_writechr
clc
ret
comboot_writechr: ; 02 = writechr
mov al,P_DL
- call writechr
+ pm_call pm_writechr
clc
ret
comboot_writeserial: ; 04 = write serial port
mov al,P_DL
- call write_serial
+ pm_call pm_write_serial
clc
ret
.loop: es lodsb
cmp al,'$' ; End string with $ - bizarre
je .done
- call writechr
+ pm_call pm_writechr
jmp short .loop
.done: clc
ret
comboot_checkkey: ; 0B = check keyboard status
cmp byte [APIKeyFlag],00h
jnz .waiting
- call pollchar
+ pm_call pm_pollchar
.waiting: setz al
dec al ; AL = 0FFh if present, 0 if not
mov P_AL,al
comboot_getchar:
cmp byte [APIKeyFlag],00h
jne .queued
- call getchar ; If not queued get input
+ pm_call pm_getchar ; If not queued get input
and al,al ; Function key? (CF <- 0)
jnz .done
mov [APIKeyWait],ah ; High part of key
comboot_int29:
sti
cld
- call writechr ; Preserves registers!
+ pm_call pm_writechr
iret
;
mov es,bp
mov bp,sp ; Set up stack frame
- call _adjust_screen ; The COMBOOT program might have changed the screen
+ pm_call pm_adjust_screen ; The COMBOOT program might hav changed the screen
cmp ax,int22_count
jb .ok
comapi_writestr:
mov ds,P_ES
mov si,P_BX
- call writestr
+ pm_call pm_writestr
clc
ret
; ES:BX as if it had been entered by the user.
;
comapi_run:
- mov ds,P_ES
- mov si,P_BX
- mov di,command_line
- call strcpy
- push load_kernel ; Run a new kernel
- jmp comboot_exit ; Terminate task, clean up
+ mov es,P_ES
+ mov bx,P_BX
+ pm_call pm_env32_run
+ ret
;
; INT 22h AX=0004h Run default command
; Puts the video in standard text mode
;
comapi_textmode:
- call vgaclearmode
+ pm_call vgaclearmode
clc
ret
; INT 22h AX=000Bh Get Serial Console Configuration
;
comapi_serialcfg:
- mov ax,[SerialPort]
+ pm_call pm_serialcfg
mov P_DX,ax
- mov ax,[BaudDivisor]
- mov P_CX,ax
- mov ax,[FlowControl]
- or al,ah
- mov ah,[FlowIgnore]
- shr ah,4
- test byte [DisplayCon],01h
- jnz .normalconsole
- or ah,80h
-.normalconsole:
- mov P_BX,ax
+ mov P_CX,cx
+ mov P_BX,bx
clc
ret
mov eax,[OrigFDCTabPtr]
mov [fdctab],eax
%endif
- call cleanup_hardware
+ pm_call cleanup_hardware
clc
ret
; INT 22h AX=000Dh Clean up then replace bootstrap
;
comapi_chainboot:
- call comapi_cleanup
- mov eax,P_EDI
- mov [trackbuf+4],eax ; Copy from
- mov eax,P_ECX
- mov [trackbuf+8],eax ; Total bytes
- mov eax,7C00h
- mov [trackbuf],eax ; Copy to
- push eax ; Entry point on stack
- mov esi,P_ESI
- mov edx,P_EBX
- mov bx,P_DS
- jmp replace_bootstrap_one
+ ret
;
; INT 22h AX=000Eh Get configuration file name
;
comapi_localboot:
mov ax,P_DX
- jmp local_boot
+ pm_call pm_local_boot
+ ret
;
; INT 22h AX=0015h Feature flags
; INT 22h AX=0016h Run kernel image
;
comapi_runkernel:
- mov al,P_DL
- cmp al,VK_TYPES-1
- ja .error
- mov [KernelType],al
-
- ; It's not just possible, but quite likely, that ES:BX
- ; points into real_mode_seg or xfer_buf_seg, so we
- ; need to exercise some special care here... use
- ; VKernelBuf for temporary storage.
- push ds
- mov ds,P_ES
- mov si,P_BX
- mov di,VKernelBuf
- call strcpy
- pop ds
-
- push ds
- mov ds,P_DS
- mov si,P_SI
- mov di,KernelName
- pm_call pm_mangle_name
- pop ds
- pm_call pm_searchdir
- jz comapi_err
-
- ; The kernel image was found, so we can load it...
- mov [Kernel_SI],si
- mov [Kernel_EAX],eax
-
-%if IS_PXELINUX
- mov al,P_CL
- mov [IPAppend],al
-%endif
-
- call comboot_exit
-
-.finish:
- ; Copy the command line into its proper place
- push es
- mov dx,real_mode_seg
- mov es,dx
- mov si,VKernelBuf
- mov di,cmd_line_here
- call strcpy
- mov word [es:di-1],' ' ; Simulate APPEND: space plus null
- pop es
- mov [CmdLinePtr],di
- mov word [CmdOptPtr],zero_string
- jmp kernel_good_saved
-
-.error equ comapi_usingvga.error
+ ret
;
; INT 22h AX=0017h Report video mode change
mov ax,P_BX
cmp ax,0Fh ; Unknown flags = failure
ja .error
- mov [UsingVGA],al
mov cx,P_CX
mov dx,P_DX
- mov [GXPixCols],cx
- mov [GXPixRows],dx
- test al,08h
- jnz .notext
- call _adjust_screen
-.notext:
+ pm_call pm_usingvga
clc
ret
.error:
mov P_BX,aux.fontbuf
.done: ; CF=0 here
- mov P_AL,al
ret
;
; some derivatives.)
;
-%include "getc.inc" ; getc et al
-%include "configinit.inc" ; Initialize configuration
-%include "parseconfig.inc" ; High-level config file handling
-%include "parsecmd.inc" ; Low-level config file handling
%include "pm.inc" ; Protected mode
%include "bcopy32.inc" ; 32-bit bcopy
-%include "loadhigh.inc" ; Load a file into high memory
%include "strcpy.inc" ; strcpy()
%include "idle.inc" ; Idle handling
%include "adv.inc" ; Auxillary Data Vector
+++ /dev/null
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
-;; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; configinit.inc
-;;
-;; Initialize the configuration section
-;;
-
- section .text16
-
-reset_config:
- ; Initialize the .config section
- xor eax,eax
- mov si,__config_lma
- mov di,__config_start
- mov cx,__config_dwords
- rep movsd
-
-%ifndef DEPEND
-%if NULLFILE != 0
- mov al,NULLFILE
- mov di,FKeyName
- mov cx,MAX_FKEYS*(1 << FILENAME_MAX_LG2)
- rep stosb
-%endif
-%endif
-
- mov di,KbdMap ; Default keymap 1:1
- xor al,al
- inc ch ; CX <- 256
-mkkeymap: stosb
- inc al
- loop mkkeymap
-
- ret
static void msg_setfg(char data);
static void msg_putchar(char ch);
-uint8_t KbdMap[256]; /* Keyboard map */
-
/*
* loadkeys: Load a LILO-style keymap
*
kaboom2:
mov si,err_bootfailed
- call writestr
+ pm_call pm_writestr
cmp byte [kaboom.again+1],18h ; INT 18h version?
je .int18
- call getchar
- call vgaclearmode
+ pm_call pm_getchar
+ pm_call vgaclearmode
int 19h ; And try once more to boot...
.norge: jmp short .norge ; If int 19h returned; this is the end
.int18:
- call vgaclearmode
+ pm_call vgaclearmode
int 18h
.noreg: jmp short .noreg ; Nynorsk
; -----------------------------------------------------------------------------
%include "common.inc" ; Universal modules
-%include "writestr.inc" ; String output
-%include "localboot.inc" ; Disk-based local boot
; -----------------------------------------------------------------------------
; Begin data section
db 'a key to continue.', CR, LF, 0
;
-; Config file keyword table
-;
-%include "keywords.inc"
-
-;
-; Extensions to search for (in *forward* order).
-;
- alignz 4
-exten_table: db '.cbt' ; COMBOOT (specific)
-%if IS_SYSLINUX
- db '.bss' ; Boot sector (add superblock)
-%endif
- db '.bs', 0 ; Boot sector
- db '.com' ; COMBOOT (same as DOS)
- db '.c32' ; COM32
-exten_table_end:
- dd 0, 0 ; Need 8 null bytes here
-
-;
; Misc initialized (data) variables
;
%ifdef debug ; This code for debugging only
#include <fcntl.h>
#include <sys/file.h>
#include <fs.h>
+#include <ctype.h>
+#include <alloca.h>
#include <sys/exec.h>
#include <sys/module.h>
if (!search_config(&fp->i.fd, search_directories, filenames))
spawn_load(LDLINUX, 1, argv);
}
+
+int create_args_and_load(char *cmdline)
+{
+ char *p, **argv;
+ int argc;
+ int i;
+
+ if (!cmdline)
+ return -1;
+
+ for (argc = 0, p = cmdline; *p; argc++) {
+ /* Find the end of this arg */
+ while(*p && !isspace(*p))
+ p++;
+
+ /*
+ * Now skip all whitespace between arguments.
+ */
+ while (*p && isspace(*p))
+ p++;
+ }
+
+ /*
+ * Generate a copy of argv on the stack as this is
+ * traditionally where process arguments go.
+ *
+ * argv[0] must be the command name.
+ */
+ argv = alloca(argc * sizeof(char *));
+
+ for (i = 0, p = cmdline; i < argc; i++) {
+ char *start;
+ int len = 0;
+
+ start = p;
+
+ /* Find the end of this arg */
+ while(*p && !isspace(*p)) {
+ p++;
+ len++;
+ }
+
+ argv[i] = malloc(len + 1);
+ strncpy(argv[i], start, len);
+ argv[i][len] = '\0';
+
+ /*
+ * Now skip all whitespace between arguments.
+ */
+ while (*p && isspace(*p))
+ p++;
+ }
+
+ /* NUL-terminate */
+ argv[argc] = NULL;
+
+ return spawn_load(argv[0], argc, argv);
+}
+
+void pm_env32_run(com32sys_t *regs)
+{
+ char *cmdline;
+
+ cmdline = MK_PTR(regs->es, regs->ebx.w[0]);
+ if (create_args_and_load(cmdline) < 0)
+ printf("Failed to run com32 module\n");
+}
extern abort_load_new
; elflink/load_env32.c
- extern load_env32
+ extern load_env32, pm_env32_run
; memscan.c
extern highmem_init
; font.c
extern pm_getchar, pm_adjust_screen, pm_usingvga, pm_userfont
+ ; localboot.c
+ extern pm_local_boot
+
%endif ; EXTERN_INC
#include <core.h>
#include <fs.h>
+char ConfigName[FILENAME_MAX];
+
/*
* Common implementation of load_config
*
+++ /dev/null
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2010 Intel Corporation; author: H. Peter Anvin
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston MA 02110-1301, USA; either version 2 of the License, or
- * (at your option) any later version; incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * newconfig.c
- *
- * Load a new configuration file
- */
-
-#include "core.h"
-#include "fs.h"
-
-void pm_is_config_file(com32sys_t *regs)
-{
- char target_cwd[FILENAME_MAX];
- const char *p;
-
- (void)regs;
-
- /* Save configuration file as an absolute path for posterity */
- realpath(ConfigName, KernelName, FILENAME_MAX);
-
- /* If we got anything on the command line, do a chdir */
- p = cmd_line;
- while (*p && !not_whitespace(*p))
- p++;
-
- if (*p) {
- mangle_name(target_cwd, p);
- chdir(target_cwd);
- }
-}
+++ /dev/null
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; getc.inc
-;;
-;; Simple file handling library (open, getc, ungetc)
-;;
-;; WARNING: This interface uses the real_mode_seg/comboot_seg.
-;;
-
-MAX_GETC_LG2 equ 4 ; Max number of file nesting
-MAX_GETC equ (1 << MAX_GETC_LG2)
-bytes_per_getc_lg2 equ 16-MAX_GETC_LG2
-bytes_per_getc equ (1 << bytes_per_getc_lg2)
-MAX_UNGET equ 9 ; Max bytes that can be pushed back
-
- struc getc_file
-gc_file resw 1 ; File pointer
-gc_bufbytes resw 1 ; Bytes left in buffer
-gc_bufdata resw 1 ; Pointer to data in buffer
-gc_unget_cnt resb 1 ; Character pushed back count
-gc_unget_buf resb MAX_UNGET ; Character pushed back buffer
- endstruc
-getc_file_lg2 equ 4 ; Size of getc_file as a power of 2
-
-%ifndef DEPEND
-%if (getc_file_size != (1 << getc_file_lg2))
-%error "getc_file_size != (1 << getc_file_lg2)"
-%endif
-%endif
-
-;
-; open,getc: Load a file a character at a time for parsing in a manner
-; similar to the C library getc routine.
-; Up to MAX_GETC files can be open at the same time,
-; they are accessed in a stack-like fashion.
-;
-; All routines assume CS == DS.
-;
-; open: Input: mangled filename in DS:DI
-; Output: ZF set on file not found or zero length
-;
-; openfd: Input: file handle in SI, file size in EAX
-; Output: ZF set on getc stack overflow
-;
-; getc: Output: CF set on end of file
-; Character loaded in AL
-;
-; close: Output: CF set if nothing open
-;
- global core_open
-core_open:
- pm_call pm_searchdir
- jz openfd.ret
-openfd:
- push bx
-
- mov bx,[CurrentGetC]
- sub bx,getc_file_size
- cmp bx,GetCStack
- jb .stack_full ; Excessive nesting
- mov [CurrentGetC],bx
-
- mov [bx+gc_file],si ; File pointer
- xor ax,ax
- mov [bx+gc_bufbytes],ax ; Buffer empty
- mov [bx+gc_unget_cnt],al ; ungetc buffer empty
-
- inc ax ; ZF <- 0
- pop bx
-.ret: ret
-
-.stack_full:
- pm_call pm_close_file
- xor ax,ax ; ZF <- 1
- pop bx
- ret
-
-getc:
- push bx
- push si
- push di
- push es
-
- mov di,[CurrentGetC]
- movzx bx,byte [di+gc_unget_cnt]
- and bx,bx
- jnz .have_unget
-
- mov si,real_mode_seg ; Borrow the real_mode_seg
- mov es,si
-
-.got_data:
- sub word [di+gc_bufbytes],1
- jc .get_data ; Was it zero already?
- mov si,[di+gc_bufdata]
- mov al,[es:si]
- inc si
- mov [di+gc_bufdata],si
-.done:
- clc
-.ret:
- pop es
- pop di
- pop si
- pop bx
- ret
-.have_unget:
- dec bx
- mov al,[di+bx+gc_unget_buf]
- mov [di+gc_unget_cnt],bl
- jmp .done
-
-.get_data:
- pushad
- ; Compute start of buffer
- mov bx,di
- sub bx,GetCStack
- shl bx,bytes_per_getc_lg2-getc_file_lg2
-
- mov [di+gc_bufdata],bx
- mov si,[di+gc_file]
- and si,si
- mov [di+gc_bufbytes],si ; In case SI == 0
- jz .empty
- mov cx,bytes_per_getc
- pm_call getfsbytes
- mov [di+gc_bufbytes],cx
- mov [di+gc_file],si
- jcxz .empty
- popad
- TRACER 'd'
- jmp .got_data
-
-.empty:
- TRACER 'e'
- ; [di+gc_bufbytes] is zero already, thus we will continue
- ; to get EOF on any further attempts to read the file.
- popad
- xor al,al ; Return a predictable zero
- stc
- jmp .ret
-
-;
-; This is similar to getc, except that we read up to CX bytes and
-; store them in ES:DI. Eventually this could get optimized...
-;
-; On return, CX and DI are adjusted by the number of bytes actually read.
-;
-readc:
- push ax
-.loop:
- call getc
- jc .out
- stosb
- loop .loop
-.out:
- pop ax
- ret
-
-;
-; close: close the top of the getc stack
-;
-close:
- push bx
- push si
- mov bx,[CurrentGetC]
- mov si,[bx+gc_file]
- pm_call pm_close_file
- add bx,getc_file_size
- mov [CurrentGetC],bx
- pop si
- pop bx
- ret
-
-;
-; ungetc: Push a character (in AL) back into the getc buffer
-; Note: if more than MAX_UNGET bytes are pushed back, all
-; hell will break loose.
-;
-ungetc:
- push di
- push bx
- mov di,[CurrentGetC]
- movzx bx,[di+gc_unget_cnt]
- mov [bx+di+gc_unget_buf],al
- inc bx
- mov [di+gc_unget_cnt],bl
- pop bx
- pop di
- ret
-
-;
-; skipspace: Skip leading whitespace using "getc". If we hit end-of-line
-; or end-of-file, return with carry set; ZF = true of EOF
-; ZF = false for EOLN; otherwise CF = ZF = 0.
-;
-; Otherwise AL = first character after whitespace
-;
-skipspace:
-.loop: call getc
- jc .eof
- cmp al,1Ah ; DOS EOF
- je .eof
- cmp al,0Ah
- je .eoln
- cmp al,' '
- jbe .loop
- ret ; CF = ZF = 0
-.eof: cmp al,al ; Set ZF
- stc ; Set CF
- ret
-.eoln: add al,0FFh ; Set CF, clear ZF
- ret
-
-;
-; getint: Load an integer from the getc file.
-; Return CF if error; otherwise return integer in EBX
-;
-getint:
- mov di,NumBuf
-.getnum: cmp di,NumBufEnd ; Last byte in NumBuf
- jae .loaded
- push di
- call getc
- pop di
- jc .loaded
- stosb
- cmp al,'-'
- jnb .getnum
- call ungetc ; Unget non-numeric
-.loaded: mov byte [di],0
- mov si,NumBuf
- ; Fall through to parseint
-;
-; parseint: Convert an integer to a number in EBX
-; Get characters from string in DS:SI
-; Return CF on error
-; DS:SI points to first character after number
-;
-; Syntaxes accepted: [-]dec, [-]0+oct, [-]0x+hex, val+[KMG]
-;
-parseint:
- push eax
- push ecx
- push bp
- xor eax,eax ; Current digit (keep eax == al)
- mov ebx,eax ; Accumulator
- mov ecx,ebx ; Base
- xor bp,bp ; Used for negative flag
-.begin: lodsb
- cmp al,'-'
- jne .not_minus
- xor bp,1 ; Set unary minus flag
- jmp short .begin
-.not_minus:
- cmp al,'0'
- jb .err
- je .octhex
- cmp al,'9'
- ja .err
- mov cl,10 ; Base = decimal
- jmp short .foundbase
-.octhex:
- lodsb
- cmp al,'0'
- jb .km ; Value is zero
- or al,20h ; Downcase
- cmp al,'x'
- je .ishex
- cmp al,'7'
- ja .err
- mov cl,8 ; Base = octal
- jmp short .foundbase
-.ishex:
- mov al,'0' ; No numeric value accrued yet
- mov cl,16 ; Base = hex
-.foundbase:
- call unhexchar
- jc .km ; Not a (hex) digit
- cmp al,cl
- jae .km ; Invalid for base
- imul ebx,ecx ; Multiply accumulated by base
- add ebx,eax ; Add current digit
- lodsb
- jmp short .foundbase
-.km:
- dec si ; Back up to last non-numeric
- lodsb
- or al,20h
- cmp al,'k'
- je .isk
- cmp al,'m'
- je .ism
- cmp al,'g'
- je .isg
- dec si ; Back up
-.fini: and bp,bp
- jz .ret ; CF=0!
- neg ebx ; Value was negative
-.done: clc
-.ret: pop bp
- pop ecx
- pop eax
- ret
-.err: stc
- jmp short .ret
-.isg: shl ebx,10 ; * 2^30
-.ism: shl ebx,10 ; * 2^20
-.isk: shl ebx,10 ; * 2^10
- jmp .fini
-
- section .bss16
- alignb 4
-NumBuf resb 15 ; Buffer to load number
-NumBufEnd resb 1 ; Last byte in NumBuf
-
-GetCStack resb getc_file_size*MAX_GETC
-.end equ $
-
- section .data16
-CurrentGetC dw GetCStack.end ; GetCStack empty
-
-;
-; unhexchar: Convert a hexadecimal digit in AL to the equivalent number;
-; return CF=1 if not a hex digit
-;
- section .text16
-unhexchar:
- cmp al,'0'
- jb .ret ; If failure, CF == 1 already
- cmp al,'9'
- ja .notdigit
- sub al,'0' ; CF <- 0
- ret
-.notdigit: or al,20h ; upper case -> lower case
- cmp al,'a'
- jb .ret ; If failure, CF == 1 already
- cmp al,'f'
- ja .err
- sub al,'a'-10 ; CF <- 0
- ret
-.err: stc
-.ret: ret
-
-;
-;
-; getline: Get a command line, converting control characters to spaces
-; and collapsing streches to one; a space is appended to the
-; end of the string, unless the line is empty.
-; The line is terminated by ^J, ^Z or EOF and is written
-; to ES:DI. On return, DI points to first char after string.
-; CF is set if we hit EOF.
-;
-getline:
- call skipspace
- mov dl,1 ; Empty line -> empty string.
- jz .eof ; eof
- jc .eoln ; eoln
- call ungetc
-.fillloop: push dx
- push di
- call getc
- pop di
- pop dx
- jc .ret ; CF set!
- cmp al,' '
- jna .ctrl
- xor dx,dx
-.store: stosb
- jmp short .fillloop
-.ctrl: cmp al,10
- je .ret ; CF clear!
- cmp al,26
- je .eof
- and dl,dl
- jnz .fillloop ; Ignore multiple spaces
- mov al,' ' ; Ctrl -> space
- inc dx
- jmp short .store
-.eoln: clc ; End of line is not end of file
- jmp short .ret
-.eof: stc
-.ret: pushf ; We want the last char to be space!
- and dl,dl
- jnz .xret
- mov al,' '
- stosb
-.xret: popf
- ret
-
-;
-; parseint_esdi:
-; Same as parseint, but takes the input in ES:DI
-;
-parseint_esdi:
- push ds
- push es
- pop ds
- xchg si,di
- call parseint
- xchg si,di
- pop ds
- ret
void pm_usingvga(com32sys_t *regs)
{
- if (regs->eax.w[0] > 0x0F) {
- /* Unknown flags = failure */
- set_flags(regs, EFLAGS_CF);
- return;
- }
-
UsingVGA = regs->eax.b[0];
GXPixCols = regs->ecx.w[0];
GXPixRows = regs->edx.w[0];
push si
push cx
mov si,hlt_err
- call writestr
+ pm_call pm_writestr
mov si,sp
add si,10
mov cx,16
pm_call pm_writechr
jmp .errloop
.endloop:
- call crlf
+ pm_call crlf
pop cx
pop si
sti
extern char copyright_str[];
extern char aux_seg[];
+extern uint8_t KbdMap[256];
/* diskstart.inc isolinux.asm*/
extern void getlinsec(void);
return c;
}
+static inline int isspace(int c)
+{
+ return c <= ' ';
+}
+
#endif /* CTYPE_H */
void init(com32sys_t *regs)
{
+ int i;
+
/* Initialize timer */
bios_timer_init();
+ for (i = 0; i < 256; i++)
+ KbdMap[i] = i;
+
adjust_screen();
printf_init();
extern init
pm_call init
-;
-; Initialize configuration information
-;
- call reset_config
;
; Set up the COMBOOT APIs
;
call comboot_setup_api
-;
-; Inite the memmory subsystem
-;
-; pm_call mem_init
- mov eax,[HighMemSize]
- mov [VKernelEnd],eax
-
section .text16
;
; The code to decompress the PM code and initialize other segments.
; -----------------------------------------------------------------------------
%include "common.inc" ; Universal modules
-%include "rawcon.inc" ; Console I/O w/o using the console functions
-%include "localboot.inc" ; Disk-based local boot
; -----------------------------------------------------------------------------
; Begin data section
section .data16
err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0
-
-;
-; Config file keyword table
-;
-%include "keywords.inc"
-
-;
-; Extensions to search for (in *forward* order).
-;
- alignz 4
-exten_table: db '.cbt' ; COMBOOT (specific)
- db '.bin' ; CD boot sector
- db '.com' ; COMBOOT (same as DOS)
- db '.c32' ; COM32
-exten_table_end:
- dd 0, 0 ; Need 8 null bytes here
+++ /dev/null
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-;; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; loadhigh.inc
-;;
-;; Load a file into high memory
-;;
-
- section .text16
-
-;
-; load_high: loads (the remainder of) a file into high memory.
-;
-; Assumes CS == DS.
-;
-; Inputs: SI = file handle/cluster pointer
-; EDI = target address in high memory
-; EAX = maximum number of bytes to load
-; DX = zero-padding mask (e.g. 0003h for pad to dword)
-; BX = subroutine to call at the top of each loop
-; (to print status and check for abort)
-; [MyHighMemSize] = maximum load address
-;
-; Outputs: SI = file handle/cluster pointer
-; EBX = first untouched address (not including padding)
-; EDI = first untouched address (including padding)
-; CF = reached EOF
-;
- extern pm_load_high
-load_high:
- push ebp
- mov ebp,[MyHighMemSize]
- pm_call pm_load_high
- pop ebp
- jo .overflow
- ret
-
-.overflow: mov si,err_nohighmem
- jmp abort_load
-
- section .data16
-err_nohighmem db CR, LF
- db 'Not enough memory to load specified image.', CR, LF, 0
-
- section .bss16
- alignb 2
-PauseBird resw 1
-
- section .text16
--- /dev/null
+/* -----------------------------------------------------------------------
+ *
+ * Copyright 1999-2008 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., 51 Franklin St, Fifth Floor,
+ * Boston MA 02110-1301, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * -----------------------------------------------------------------------
+ */
+#include <sys/cpu.h>
+#include <core.h>
+
+/*
+ * localboot.c
+ *
+ * Boot from a local disk, or invoke INT 18h.
+ */
+
+#define LOCALBOOT_MSG "Booting from local disk..."
+
+#define retry_count 16
+
+extern void local_boot16(void);
+
+/*
+ * Boot a specified local disk. AX specifies the BIOS disk number; or
+ * -1 in case we should execute INT 18h ("next device.")
+ */
+void local_boot(int16_t ax)
+{
+ com32sys_t ireg, oreg;
+ unsigned long data;
+ int i;
+
+ vgaclearmode();
+
+ writestr(LOCALBOOT_MSG);
+ crlf();
+ cleanup_hardware();
+
+ if (ax == -1) {
+ /* Hope this does the right thing */
+ __intcall(0x18, &zero_regs, NULL);
+
+ /* If we returned, oh boy... */
+ kaboom();
+ }
+
+ /*
+ * Load boot sector from the specified BIOS device and jump to
+ * it.
+ */
+ ireg.edx.b[0] = ax & 0xff;
+ ireg.eax.w[0] = 0; /* Reset drive */
+ __intcall(0x13, &ireg, NULL);
+
+ ireg.eax.w[0] = 0x0201; /* Read one sector */
+ ireg.ecx.w[0] = 0x0001; /* C/H/S = 0/0/1 (first sector) */
+ ireg.ebx.w[0] = OFFS(trackbuf);
+ ireg.es = SEG(trackbuf);
+
+ for (i = 0; i < retry_count; i++) {
+ __intcall(0x13, &ireg, &oreg);
+
+ if (!(oreg.eflags.l & EFLAGS_CF))
+ break;
+ }
+
+ if (i == retry_count)
+ kaboom();
+
+ cli(); /* Abandon hope, ye who enter here */
+ memcpy(0x07C00, trackbuf, 512);
+
+ ireg.esi.w[0] = OFFS(trackbuf);
+ ireg.edi.w[0] = 0x07C00;
+ ireg.edx.w[0] = ax;
+ call16(local_boot16, &ireg, NULL);
+}
+
+void pm_local_boot(com32sys_t *regs)
+{
+ local_boot(regs->eax.w[0]);
+}
-; -----------------------------------------------------------------------
-;
-; Copyright 1999-2008 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., 51 Franklin St, Fifth Floor,
-; Boston MA 02110-1301, USA; either version 2 of the License, or
-; (at your option) any later version; incorporated herein by reference.
-;
-; -----------------------------------------------------------------------
-
-;
-; localboot.inc
-;
-; Boot from a local disk, or invoke INT 18h.
-;
-
-;
-; Boot a specified local disk. AX specifies the BIOS disk number; or
-; -1 in case we should execute INT 18h ("next device.")
-;
section .text16
-
-local_boot:
- call vgaclearmode
- RESET_STACK_AND_SEGS dx ; dx <- 0
- mov fs,dx
- mov gs,dx
- mov si,localboot_msg
- call writestr
- call cleanup_hardware
- cmp ax,-1
- je .int18
-
- ; Load boot sector from the specified BIOS device and jump to it.
- mov dl,al
- xor dh,dh
- push dx
- xor ax,ax ; Reset drive
- int 13h
- mov ax,0201h ; Read one sector
- mov cx,0001h ; C/H/S = 0/0/1 (first sector)
- mov bx,trackbuf
- mov bp,retry_count
-.again:
- pusha
- int 13h
- popa
- jnc .ok
- dec bp
- jnz .again
- jmp kaboom ; Failure...
-.ok:
- pop dx
- cli ; Abandon hope, ye who enter here
- mov si,trackbuf
- mov di,07C00h
- mov cx,512 ; Probably overkill, but should be safe
- rep movsd
- mov ss,cx ; SS <- 0
+ global local_boot16
+local_boot16:
+ mov cx,0
+ mov ss,cx
mov sp,7C00h
- jmp 0:07C00h ; Jump to new boot sector
-
-.int18:
- int 18h ; Hope this does the right thing...
- jmp kaboom ; If we returned, oh boy...
-
- section .data16
-localboot_msg db 'Booting from local disk...', CR, LF, 0
-
- section .text16
-
+ jmp 0:07C00h
+++ /dev/null
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; parsecmd.inc
-;;
-;; Command line parser code
-;;
-
- section .text16
-
-; -------------------------------------------------------------------------
-; getcommand: Get a keyword from the current "getc" file and match it
-; against a list of keywords (keywd_table). Each entry in
-; that table should have the following form:
-; <32 bit hash value> <16 bit handler offset>
-;
-; The handler is called, and upon return this function
-; returns with CF = 0. On EOF, this function returns
-; with CF = 1.
-; -------------------------------------------------------------------------
-
-getcommand.skipline:
- call skipline
-
-getcommand:
-.find:
- call skipspace ; Skip leading whitespace
- jz .eof ; End of file
- jc .find ; End of line: try again
-
- ; Do this explicitly so #foo is treated as a comment
- cmp al,'#' ; Leading hash mark -> comment
- je .skipline
-
- ; Abuse the trackbuf by putting the keyword there for
- ; possible error messaging...
- mov di,trackbuf
- stosb
- or al,20h ; Convert to lower case
- movzx ebx,al ; Hash for a one-char keyword
-.read_loop:
- call getc
- jc .eof
- cmp al,' ' ; Whitespace
- jbe .done
- stosb
- or al,20h
- rol ebx,5
- xor bl,al
- jmp short .read_loop
-.done: call ungetc
- xor ax,ax
- stosb ; Null-terminate the trackbuf
- call skipspace
- jz .eof
- jc .noparm
- call ungetc ; Return nonwhitespace char to buf
- mov si,keywd_table
- mov cx,keywd_count
-.table_search:
- lodsd
- cmp ebx,eax
- je .found_keywd
- lodsd ; Skip entrypoint/argument
- loop .table_search
-
- ; Otherwise unrecognized keyword
- mov si,err_badcfg
- call writestr
- mov si,trackbuf
- call writestr
- call crlf
- jmp .skipline
-
- ; No parameter
-.noparm:
- mov si,err_noparm
- call writestr
- mov si,trackbuf
- call writestr
- call crlf
- jmp .find
-
-.found_keywd: lodsw ; Load argument into ax
- call [si]
- clc
- ret
-
-.eof: stc
- ret
-
-skipline: cmp al,10 ; Search for LF
- je .end
- call getc
- jnc skipline
-.end: ret
-
- section .data16
-err_badcfg db 'Unknown keyword in configuration file: ',0
-err_noparm db 'Missing parameter in configuration file. Keyword: ',0
-
- section .uibss
- alignb 4
-vk_size equ (vk_end + 3) & ~3
-VKernelBuf: resb vk_size ; "Current" vkernel
-AppendBuf resb max_cmd_len+1 ; append=
-Ontimeout resb max_cmd_len+1 ; ontimeout
-Onerror resb max_cmd_len+1 ; onerror
- ; This could be in .uibss but that makes PXELINUX overflow
- section .bss16
-KbdMap resb 256 ; Keyboard map
-FKeyName resb MAX_FKEYS*FILENAME_MAX ; File names for F-key help
- global KernelName
-KernelName resb FILENAME_MAX ; Mangled name for kernel
-MNameBuf resb FILENAME_MAX
-InitRD resb FILENAME_MAX
-
- section .text16
+++ /dev/null
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; parseconfig.inc
-;;
-;; Configuration file operations
-;;
-
- section .text16
-;
-; "default" or "ui" command, with level (1 = default, 2 = ui)
-;
-pc_default: cmp ax,[DefaultLevel]
- jb skipline ; == call skipline + ret
- mov [DefaultLevel],ax
- mov di,default_cmd
- call getline
- mov byte [di-1],0 ; null-terminate
- ret
-
-;
-; "ontimeout" command
-;
-pc_ontimeout: mov di,Ontimeout
- call getline
- sub di,Ontimeout+1 ; Don't need final space
- mov [OntimeoutLen],di
- ret
-
-;
-; "onerror" command
-;
-pc_onerror: mov di,Onerror
- call getline
- sub di,Onerror
- mov [OnerrorLen],di
- ret
-
-;
-; "append" command
-;
-pc_append: cmp byte [VKernel],0
- ja .vk
- mov di,AppendBuf
- call getline
- sub di,AppendBuf
-.app1: mov [AppendLen],di
- ret
-.vk: mov di,VKernelBuf+vk_append ; "append" command (vkernel)
- call getline
- sub di,VKernelBuf+vk_append
- cmp di,byte 2
- jne .app2
- cmp byte [VKernelBuf+vk_append],'-'
- jne .app2
- xor di,di ; If "append -" -> null string
-.app2: mov [VKernelBuf+vk_appendlen],di
- ret
-
-;
-; "ipappend" command (PXELINUX only)
-;
-%if IS_PXELINUX
-pc_ipappend: call getint
- jc .err
- cmp byte [VKernel],0
- jne .vk
- mov [IPAppend],bl
-.err: ret
-.vk: mov [VKernelBuf+vk_ipappend],bl
- ret
-%endif
-
-;
-; "localboot" command
-;
-pc_localboot: call getint
- cmp byte [VKernel],0 ; ("label" section only)
- je .err
- mov [VKernelBuf+vk_rname],bx
- mov byte [VKernelBuf+vk_type],VK_LOCALBOOT
-.err: ret
-
-;
-; "kernel", "config", ... command
-;
-pc_kernel: cmp byte [VKernel],0
- je .err ; ("label" section only)
- mov [VKernelBuf+vk_type],al
- call pc_getline
- mov di,VKernelBuf+vk_rname
- pm_call pm_mangle_name
-.err: ret
-
-;
-; "timeout", "totaltimeout" command
-;
-; N.B. 1/10 s ~ 1.D2162AABh clock ticks
-;
-pc_timeout: push ax
- call getint
- pop si
- jc .err
- mov eax,0D2162AABh
- mul ebx ; clock ticks per 1/10 s
- add ebx,edx
- mov [si],ebx
-.err: ret
-
-
-;
-; "totaltimeout" command
-;
-pc_totaltimeout:
-
-;
-; Generic integer variable setting commands:
-; "prompt", "implicit"
-;
-pc_setint16:
- push ax
- call getint
- pop si
- jc .err
- mov [si],bx
-.err: ret
-
-;
-; Generic file-processing commands:
-; "font", "kbdmap",
-;
-pc_filecmd: push ax ; Function to tailcall
- call pc_getline
- mov di,MNameBuf
- pm_call pm_mangle_name
- pm_call pm_searchdir
- jnz .ok
- pop ax ; Drop the successor function
-.ok: ret ; Tailcall if OK, error return
-
-;
-; Commands that expect the file to be opened on top of the getc stack.
-; "display", "include"
-;
-pc_opencmd: push ax ; Function to tailcall
- call pc_getline
- mov di,MNameBuf
- pm_call pm_mangle_name
- call core_open
- jnz .ok
- pop ax ; Drop the successor function
-.ok: ret ; Tailcall if OK, error return
-
-;
-; "include" command (invoked from pc_opencmd)
-;
-pc_include: inc word [IncludeLevel]
-.err: ret
-
-;
-; "serial" command
-;
-pc_serial: call getint
- jc .err
- push bx ; Serial port #
- xor eax,eax
- mov [FlowControl],eax ; Default to no flow control
- call skipspace
- jc .nobaud
- call ungetc
- call getint
- jc .nobaud
-.valid_baud:
- push ebx
- call skipspace
- jc .no_flow
- call ungetc
- call getint ; Hardware flow control?
- jnc .valid_flow
-.no_flow:
- xor bx,bx ; Default -> no flow control
-.valid_flow:
- and bh,0Fh ; FlowIgnore
- shl bh,4
- mov [FlowIgnore],bh
- mov bh,bl
- and bx,0F00Bh ; Valid bits
- mov [FlowControl],bx
- pop ebx ; Baud rate
- jmp short .parse_baud
-.nobaud:
- mov ebx,DEFAULT_BAUD ; No baud rate given
-.parse_baud:
- pop di ; Serial port #
- cmp ebx,byte 75
- jb .err ; < 75 baud == bogus
- mov eax,BAUD_DIVISOR
- cdq
- div ebx
- mov [BaudDivisor],ax
- push ax ; Baud rate divisor
- cmp di,3
- ja .port_is_io ; If port > 3 then port is I/O addr
- shl di,1
- mov di,[di+serial_base] ; Get the I/O port from the BIOS
-.port_is_io:
- mov [SerialPort],di
-
- ;
- ; Begin code to actually set up the serial port
- ;
- call sirq_cleanup_nowipe ; Cleanup existing IRQ handler
-
- lea dx,[di+3] ; DX -> LCR
- mov al,83h ; Enable DLAB
- slow_out dx,al
-
- pop ax ; Divisor
- mov dx,di ; DX -> LS
- slow_out dx,al
-
- inc dx ; DX -> MS
- mov al,ah
- slow_out dx,al
-
- mov al,03h ; Disable DLAB
- inc dx ; DX -> LCR
- inc dx
- slow_out dx,al
-
- in al,dx ; Read back LCR (detect missing hw)
- cmp al,03h ; If nothing here we'll read 00 or FF
- jne .err ; Assume serial port busted
- dec dx ; DX -> IIR/FCR
- mov al,01h
- slow_out dx,al ; Enable FIFOs if present
- in al,dx
- cmp al,0C0h ; FIFOs enabled and usable?
- jae .fifo_ok
- xor ax,ax ; Disable FIFO if unusable
- slow_out dx,al
-.fifo_ok:
-
- inc dx
- inc dx ; DX -> MCR
- mov al,[FlowOutput] ; Assert bits
- slow_out dx,al
-
- ; Enable interrupts if requested
- test al,8
- jz .noirq
- call sirq_install
-.noirq:
-
- ; Show some life
- cmp byte [SerialNotice],0
- je .notfirst
- mov byte [SerialNotice],0
-
- mov si,syslinux_banner
- call write_serial_str
- mov si,copyright_str
- call write_serial_str
-.notfirst:
- ret
-
-.err:
- mov [SerialPort], word 0
- ret
-
-;
-; Store mangled filename command (F-keys, "initrd")
-;
-pc_filename: push ax
- call pc_getline
- pop di
- pm_call pm_mangle_name ; Mangle file name
- ret
-
-;
-; "label" command
-;
-pc_label: call commit_vk ; Commit any current vkernel
- mov byte [InitRD+NULLOFFSET],NULLFILE ; No "initrd" statement
- mov di,VKernelBuf ; Erase the vkernelbuf for better compression
- mov cx,(vk_size >> 1)
- xor ax,ax
- rep stosw
- call pc_getline
- mov di,VKernelBuf+vk_vname
- mov cx,FILENAME_MAX-1
-.loop:
- lodsb
- cmp al,' '
- jna .done
- stosb
- loop .loop
-.done:
- mov byte [VKernel],1 ; We've seen a "label" statement
- mov si,VKernelBuf+vk_vname ; By default, rname == mangled vname
- mov di,VKernelBuf+vk_rname
- pm_call pm_mangle_name
- mov si,AppendBuf ; Default append==global append
- mov di,VKernelBuf+vk_append
- mov cx,[AppendLen]
- mov [VKernelBuf+vk_appendlen],cx
- rep movsb
-%if IS_PXELINUX ; PXELINUX only
- mov al,[IPAppend] ; Default ipappend==global ipappend
- mov [VKernelBuf+vk_ipappend],al
-%endif
- ret
-
-;
-; "say" command
-;
-pc_say: call pc_getline ; "say" command
- call writestr
- jmp crlf ; tailcall
-
-;
-; "text" command; ignore everything until we get an "endtext" line
-;
-pc_text: call skipline ; Ignore rest of line
-.loop:
- call pc_getline
- jc .eof
-
- ; Leading spaces are already removed...
- lodsd
- and eax,0xdfdfdfdf ; Upper case
- cmp eax,'ENDT'
- jne .loop
- lodsd
- and eax,0x00dfdfdf ; Upper case and mask
- cmp eax,'EXT'
- jne .loop
- ; If we get here we hit ENDTEXT
-.eof:
- ret
-
-;
-; Comment line
-;
-pc_comment: ; Fall into pc_getline
-
-;
-; Common subroutine: load line into trackbuf; returns with SI -> trackbuf
-; CF is set on EOF.
-;
-pc_getline: mov di,trackbuf
- push di
- call getline
- mov byte [di],0 ; Null-terminate
- pop si
- ret
-
-;
-; Main loop for configuration file parsing
-;
-parse_config:
- mov di,VKernelBuf ; Clear VKernelBuf at start
- xor ax,ax
- mov cx,vk_size
- rep stosb
-
-.again:
- call getcommand ; Parse one command
- jnc .again ; If not EOF...
- call close
- dec word [IncludeLevel] ; Still parsing?
- jnz .again
-
- ;
- ; The fall through to commit_vk to commit any final
- ; VKernel being read
- ;
-;
-; commit_vk: Store the current VKernelBuf into buffer segment
-;
-commit_vk:
- cmp byte [VKernel],0
- jz .nolabel ; Nothing to commit...
-
- mov di,VKernelBuf+vk_append
- add di,[VKernelBuf+vk_appendlen]
-
- ; If we have an initrd statement, append it to the
- ; append statement
- cmp byte [InitRD+NULLOFFSET],NULLFILE
- je .noinitrd
-
- mov si,str_initrd
- mov cx,7 ; "initrd="
- rep movsb
- mov si,InitRD
- call strcpy
- mov byte [es:di-1],' '
-
- ; For better compression, clean up the append field
-.noinitrd:
- mov ax,di
- sub ax,VKernelBuf+vk_append
- mov [VKernelBuf+vk_appendlen],ax
- mov cx,max_cmd_len+1
- sub cx,ax
- xor ax,ax
- rep stosb
-
- ; Pack into high memory
- mov esi,VKernelBuf
- mov edi,[VKernelEnd]
- mov ecx,vk_size
- pm_call rllpack
- mov [VKernelEnd],edi
-.nolabel:
- ret
-.overflow:
- mov si,vk_overflow_msg
- call writestr
- ret
-
- section .data16
- global SerialNotice
-vk_overflow_msg db 'Out of memory parsing config file', CR, LF, 0
-SerialNotice db 1 ; Only print this once
-
- section .bss16
- alignb 4
-VKernelEnd resd 1 ; Lowest high memory address used
-
- ; This symbol should be used by loaders to indicate
- ; the highest address *they* are allowed to use.
-HighMemRsvd equ VKernelEnd
- ; by vkernels
- section .config
- alignz 4
-KbdTimeout dd 0 ; Keyboard timeout (if any)
-TotalTimeout dd 0 ; Total timeout (if any)
-AppendLen dw 0 ; Bytes in append= command
-OntimeoutLen dw 0 ; Bytes in ontimeout command
-OnerrorLen dw 0 ; Bytes in onerror command
-CmdLinePtr dw cmd_line_here ; Command line advancing pointer
-ForcePrompt dw 0 ; Force prompt
-NoEscape dw 0 ; No escape
-NoComplete dw 0 ; No label completion on TAB key
-AllowImplicit dw 1 ; Allow implicit kernels
-AllowOptions dw 1 ; User-specified options allowed
-IncludeLevel dw 1 ; Nesting level
-DefaultLevel dw 0 ; The current level of default
- global PXERetry
-PXERetry dw 0 ; Extra PXE retries
-VKernel db 0 ; Have we seen any "label" statements?
-
-%if IS_PXELINUX
-IPAppend db 0 ; Default IPAPPEND option
-%endif
-
- section .uibss
- alignb 4 ; For the good of REP MOVSD
-command_line resb max_cmd_len+2 ; Command line buffer
- alignb 4
-default_cmd resb max_cmd_len+1 ; "default" command line
%include "ui.inc"
;
-; Boot to the local disk by returning the appropriate PXE magic.
-; AX contains the appropriate return code.
-;
-local_boot:
- push cs
- pop ds
- mov [LocalBootType],ax
- call vgaclearmode
- mov si,localboot_msg
- call writestr_early
- ; Restore the environment we were called with
- pm_call reset_pxe
- call cleanup_hardware
- lss sp,[InitStack]
- pop gs
- pop fs
- pop es
- pop ds
- popad
- mov ax,[cs:LocalBootType]
- cmp ax,-1 ; localboot -1 == INT 18h
- je .int18
- popfd
- retf ; Return to PXE
-.int18:
- popfd
- int 18h
- jmp 0F000h:0FFF0h
- hlt
-
-;
; kaboom: write a message and bail out. Wait for quite a while,
; or a user keypress, then do a hard reboot.
;
; -----------------------------------------------------------------------------
%include "common.inc" ; Universal modules
-%include "rawcon.inc" ; Console I/O w/o using the console functions
; -----------------------------------------------------------------------------
; Begin data section
syslinux_banner db CR, LF, MY_NAME, ' ', VERSION_STR, ' ', DATE_STR, ' ', 0
;
-; Config file keyword table
-;
-%include "keywords.inc"
-
-;
-; Extensions to search for (in *forward* order).
-; (.bs and .bss16 are disabled for PXELINUX, since they are not supported)
-;
- alignz 4
-exten_table: db '.cbt' ; COMBOOT (specific)
- db '.0', 0, 0 ; PXE bootstrap program
- db '.com' ; COMBOOT (same as DOS)
- db '.c32' ; COM32
-exten_table_end:
- dd 0, 0 ; Need 8 null bytes here
-
-;
; Misc initialized (data) variables
;
section .data16
--- /dev/null
+/*
+ * writechr: Write a single character in AL to the console without
+ * mangling any registers. This does raw console writes,
+ * since some PXE BIOSes seem to interfere regular console I/O.
+ */
+#include <sys/io.h>
+#include <fs.h>
+#include <com32.h>
+#include "bios.h"
+
+void writechr(char data)
+{
+ if (UsingVGA & 0x08)
+ vgaclearmode();
+
+ write_serial(data); /* write to serial port if needed */
+
+ /* Write to screen? */
+ if (DisplayCon & 0x01) {
+ com32sys_t ireg, oreg;
+ bool curxyok = false;
+ uint16_t dx;
+
+ ireg.ebx.b[1] = *(uint8_t *)BIOS_page;
+ ireg.eax.b[1] = 0x03; /* Read cursor position */
+ __intcall(0x10, &ireg, &oreg);
+ ireg.edx.l = oreg.edx.l;
+
+ switch (data) {
+ case 8:
+ if (ireg.edx.b[0]--) {
+ curxyok = true;
+ break;
+ }
+
+ ireg.edx.b[0] = VidCols;
+ if (ireg.edx.b[1]--) {
+ curxyok = true;
+ break;
+ }
+
+ ireg.edx.b[1] = 0;
+ curxyok = true;
+ break;
+ case 13:
+ ireg.edx.b[0] = 0;
+ curxyok = true;
+ break;
+ case 10:
+ break;
+ default:
+ dx = ireg.edx.w[0];
+
+ ireg.ebx.b[1] = *(uint8_t *)BIOS_page;
+ ireg.ebx.b[0] = 0x07; /* White on black */
+ ireg.ecx.w[0] = 1; /* One only */
+ ireg.eax.b[0] = data;
+ ireg.eax.b[1] = 0x09; /* Write char and attribute */
+ __intcall(0x10, &ireg, NULL);
+
+ ireg.edx.w[0] = dx;
+ if (++ireg.edx.b[0] <= VidCols)
+ curxyok = true;
+ else
+ ireg.edx.b[0] = 0;
+ }
+
+ if (!curxyok && ++ireg.edx.b[1] > VidRows) {
+ /* Scroll */
+ ireg.edx.b[1]--;
+ ireg.ebx.b[1] = *(uint8_t *)BIOS_page;
+ ireg.eax.b[1] = 0x02;
+ __intcall(0x10, &ireg, NULL);
+
+ ireg.eax.w[0] = 0x0601; /* Scroll up one line */
+ ireg.ebx.b[1] = ScrollAttribute;
+ ireg.ecx.w[0] = 0;
+ ireg.edx.w[0] = ScreenSize; /* The whole screen */
+ __intcall(0x10, &ireg, NULL);
+ } else {
+ ireg.ebx.b[1] = *(uint8_t *)BIOS_page;
+ ireg.eax.b[1] = 0x02; /* Set cursor position */
+ __intcall(0x10, &ireg, NULL);
+ }
+ }
+}
+
+void pm_writechr(com32sys_t *regs)
+{
+ writechr(regs->eax.b[0]);
+}
+++ /dev/null
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-;; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; runkernel.inc
-;;
-;; Common code for running a Linux kernel
-;;
-
-;
-; Hook macros, that may or may not be defined
-;
-%ifndef HAVE_UNLOAD_PREP
-%macro UNLOAD_PREP 0
-%endmacro
-%endif
-
-;
-; A Linux kernel consists of three parts: boot sector, setup code, and
-; kernel code. The boot sector is never executed when using an external
-; booting utility, but it contains some status bytes that are necessary.
-;
-; First check that our kernel is at least 1K, or else it isn't long
-; enough to have the appropriate headers.
-;
-; We used to require the kernel to be 64K or larger, but it has gotten
-; popular to use the Linux kernel format for other things, which may
-; not be so large.
-;
-; Additionally, we used to have a test for 8 MB or smaller. Equally
-; obsolete.
-;
-is_linux_kernel:
- push si ; <A> file pointer
-
-;
-; Now start transferring the kernel
-;
- push word real_mode_seg
- pop es
-
-;
-; Start by loading the bootsector/setup code, to see if we need to
-; do something funky. It should fit in the first 32K (loading 64K won't
-; work since we might have funny stuff up near the end of memory).
-;
- call abort_check ; Check for abort key
- mov cx,8000h ; Half a moby (32K)
- xor bx,bx
- pop si ; <A> file pointer
- pm_call getfsbytes
- cmp cx,1024
- jb kernel_corrupt
- cmp word [es:bs_bootsign],0AA55h
- jne kernel_corrupt ; Boot sec signature missing
-
-;
-; Save the file pointer for later...
-;
- push si ; <A> file pointer
-
-;
-; Construct the command line (append options have already been copied)
-;
-construct_cmdline:
- mov di,[CmdLinePtr]
- mov si,boot_image ; BOOT_IMAGE=
- mov cx,boot_image_len
- rep movsb
- mov si,KernelName ; Unmangled kernel name
- call strcpy
- mov byte [es:di-1],' ' ; Follow by space
-
- call do_ip_append ; Handle IPAppend
-
- mov si,[CmdOptPtr] ; Options from user input
- call strcpy
-
-;
-; Scan through the command line for anything that looks like we might be
-; interested in. The original version of this code automatically assumed
-; the first option was BOOT_IMAGE=, but that is no longer certain.
-;
-parse_cmdline:
- mov di,cmd_line_here
-.skipspace: mov al,[es:di]
- inc di
-.skipspace_loaded:
- and al,al
- jz cmdline_end
- cmp al,' '
- jbe .skipspace
- dec di
-
- ; ES:DI now points to the beginning of an option
- mov si,options_list
-.next_opt:
- movzx cx,byte [si]
- jcxz .skip_opt
- push di
- inc si
- repe cmpsb
- jne .no_match
-
- ; This either needs to have been an option with parameter,
- ; or be followed by EOL/whitespace
- mov ax,[es:di-1] ; AL = last chr; AH = following
- cmp al,'='
- je .is_match
- cmp ah,' '
- ja .no_match
-.is_match:
- pop ax ; Drop option pointer on stack
- call [si]
-.skip_opt:
- mov al,[es:di]
- inc di
- cmp al,' '
- ja .skip_opt
- jmp .skipspace_loaded
-.no_match:
- pop di
- add si,cx ; Skip remaining bytes
- inc si ; Skip function pointer
- inc si
- jmp .next_opt
-
-opt_vga:
- mov ax,[es:di-1]
- mov bx,-1
- cmp ax,'=n' ; vga=normal
- je .vc0
- dec bx ; bx <- -2
- cmp ax,'=e' ; vga=ext
- je .vc0
- dec bx ; bx <- -3
- cmp ax,'=a' ; vga=ask
- je .vc0
- mov bx,0x0f04 ; bx <- 0x0f04 (current mode)
- cmp ax,'=c' ; vga=current
- je .vc0
- call parseint_esdi ; vga=<number>
- jc .skip ; Not an integer
-.vc0: mov [es:bs_vidmode],bx ; Set video mode
-.skip:
- ret
-
-opt_mem:
- call parseint_esdi
- jc .skip
-%if HIGHMEM_SLOP != 0
- sub ebx,HIGHMEM_SLOP
-%endif
- mov [MyHighMemSize],ebx
-.skip:
- ret
-
-opt_quiet:
- mov byte [QuietBoot],QUIET_FLAG
- ret
-
-%if IS_PXELINUX
-opt_keeppxe:
- or byte [KeepPXE],1 ; KeepPXE set by command line
- ret
-%endif
-
-opt_initrd:
- mov ax,di
- cmp byte [es:di],' '
- ja .have_initrd
- xor ax,ax
-.have_initrd:
- mov [InitRDPtr],ax
- ret
-
-;
-; After command line parsing...
-;
-cmdline_end:
- sub di,cmd_line_here
- mov [CmdLineLen],di ; Length including final null
-
-;
-; Now check if we have a large kernel, which needs to be loaded high
-;
-prepare_header:
- mov dword [RamdiskMax], HIGHMEM_MAX ; Default initrd limit
- cmp dword [es:su_header],HEADER_ID ; New setup code ID
- jne old_kernel ; Old kernel, load low
- mov ax,[es:su_version]
- mov [KernelVersion],ax
- cmp ax,0200h ; Setup code version 2.0
- jb old_kernel ; Old kernel, load low
- cmp ax,0201h ; Version 2.01+?
- jb new_kernel ; If 2.00, skip this step
- ; Set up the heap (assuming loading high for now)
- mov word [es:su_heapend],linux_stack-512
- or byte [es:su_loadflags],80h ; Let the kernel know we care
- cmp ax,0203h ; Version 2.03+?
- jb new_kernel ; Not 2.03+
- mov eax,[es:su_ramdisk_max]
- mov [RamdiskMax],eax ; Set the ramdisk limit
-
-;
-; We definitely have a new-style kernel. Let the kernel know who we are,
-; and that we are clueful
-;
-new_kernel:
- mov byte [es:su_loader],my_id ; Show some ID
- xor eax,eax
- mov [es:su_ramdisklen],eax ; No initrd loaded yet
-
-;
-; About to load the kernel. This is a modern kernel, so use the boot flags
-; we were provided.
-;
- mov al,[es:su_loadflags]
- or al,[QuietBoot] ; Set QUIET_FLAG if needed
- mov [es:su_loadflags],al
- mov [LoadFlags],al
-
-any_kernel:
- mov si,loading_msg
- call writestr_qchk
- mov si,KernelName ; Print kernel name part of
- call writestr_qchk ; "Loading" message
-
-;
-; Load the kernel. We always load it at 100000h even if we're supposed to
-; load it "low"; for a "low" load we copy it down to low memory right before
-; jumping to it.
-;
-read_kernel:
- movzx ax,byte [es:bs_setupsecs] ; Setup sectors
- and ax,ax
- jnz .sects_ok
- mov al,4 ; 0 = 4 setup sectors
-.sects_ok:
- inc ax ; Including the boot sector
- mov [SetupSecs],ax
-
- call dot_pause
-
-;
-; Move the stuff beyond the setup code to high memory at 100000h
-;
- movzx esi,word [SetupSecs] ; Setup sectors
- shl si,9 ; Convert to bytes
- mov ecx,8000h ; 32K
- sub ecx,esi ; Number of bytes to copy
- add esi,core_real_mode ; Pointer to source
- mov edi,free_high_memory ; Copy to free high memory
-
- call bcopy ; Transfer to high memory
-
- pop si ; <A> File pointer
- and si,si ; EOF already?
- jz high_load_done
-
- ; On exit EDI -> where to load the rest
-
- mov bx,dot_pause
- or eax,-1 ; Load the whole file
- mov dx,3 ; Pad to dword
- call load_high
-
-high_load_done:
- mov [KernelEnd],edi
- mov ax,real_mode_seg ; Set to real mode seg
- mov es,ax
-
- mov si,dot_msg
- call writestr_qchk
-
-;
-; Some older kernels (1.2 era) would have more than 4 setup sectors, but
-; would not rely on the boot protocol to manage that. These kernels fail
-; if they see protected-mode kernel data after the setup sectors, so
-; clear that memory.
-;
- push di
- mov di,[SetupSecs]
- shl di,9
- xor eax,eax
- mov cx,cmd_line_here
- sub cx,di
- shr cx,2
- rep stosd
- pop di
-
-;
-; 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:
- ; Cap the ramdisk memory range if appropriate
- mov eax,[RamdiskMax]
- cmp eax,[MyHighMemSize]
- ja .ok
- mov [MyHighMemSize],eax
-.ok:
- xor eax,eax
- cmp [InitRDPtr],ax
- jz .noinitrd
- call parse_load_initrd
-.noinitrd:
-
-;
-; Abandon hope, ye that enter here! We do no longer permit aborts.
-;
- call abort_check ; Last chance!!
-
- mov si,ready_msg
- call writestr_qchk
-
- UNLOAD_PREP ; Module-specific hook
-
-;
-; 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
-; capable of starting their setup from a different address.
-;
- mov ax,real_mode_seg
- mov es,ax
- mov fs,ax
-
-;
-; If the default root device is set to FLOPPY (0000h), change to
-; /dev/fd0 (0200h)
-;
- cmp word [es:bs_rootdev],byte 0
- jne root_not_floppy
- mov word [es:bs_rootdev],0200h
-root_not_floppy:
-
-;
-; Copy command line. Unfortunately, the old kernel boot protocol requires
-; the command line to exist in the 9xxxxh range even if the rest of the
-; setup doesn't.
-;
-setup_command_line:
- mov dx,[KernelVersion]
- test byte [LoadFlags],LOAD_HIGH
- jz .need_high_cmdline
- cmp dx,0202h ; Support new cmdline protocol?
- jb .need_high_cmdline
- ; New cmdline protocol
- ; Store 32-bit (flat) pointer to command line
- ; This is the "high" location, since we have bzImage
- mov dword [fs:su_cmd_line_ptr],cmd_line
- mov word [HeapEnd],linux_stack
- mov word [fs:su_heapend],linux_stack-512
- jmp .setup_done
-
-.need_high_cmdline:
-;
-; Copy command line down to fit in high conventional memory
-; -- this happens if we have a zImage kernel or the protocol
-; is less than 2.02.
-;
- mov si,cmd_line_here
- mov di,old_cmd_line_here
- mov [fs:kern_cmd_magic],word CMD_MAGIC ; Store magic
- mov [fs:kern_cmd_offset],di ; Store pointer
- mov word [HeapEnd],old_linux_stack
- mov ax,255 ; Max cmdline limit
- cmp dx,0201h
- jb .adjusted
- ; Protocol 2.01+
- mov word [fs:su_heapend],old_linux_stack-512
- jbe .adjusted
- ; Protocol 2.02+
- ; Note that the only reason we would end up here is
- ; because we have a zImage, so we anticipate the move
- ; to 90000h already...
- mov dword [fs:su_cmd_line_ptr],0x90000+old_cmd_line_here
- mov ax,old_max_cmd_len ; 2.02+ allow a higher limit
-.adjusted:
-
- mov cx,[CmdLineLen]
- cmp cx,ax
- jna .len_ok
- mov cx,ax ; Truncate the command line
-.len_ok:
- fs rep movsb
- stosb ; Final null, note AL=0 already
- mov [CmdLineEnd],di
- cmp dx,0200h
- jb .nomovesize
- mov [es:su_movesize],di ; Tell the kernel what to move
-.nomovesize:
-.setup_done:
-
-;
-; Time to start setting up move descriptors
-;
-setup_move:
- mov di,trackbuf
- xor cx,cx ; Number of descriptors
-
- mov bx,es ; real_mode_seg
- mov fs,bx
- push ds ; We need DS == ES == CS here
- pop es
-
- mov edx,100000h
- test byte [LoadFlags],LOAD_HIGH
- jnz .loading_high
-
-; Loading low: move real_mode stuff to 90000h, then move the kernel down
- mov eax,90000h
- stosd
- mov eax,core_real_mode
- stosd
- movzx eax,word [CmdLineEnd]
- stosd
- inc cx
- mov edx,10000h ; Revised target address
- mov bx,9000h ; Revised real mode segment
-
-.loading_high:
- mov eax,edx ; Target address of kernel
- stosd
- mov eax,free_high_memory ; Where currently loaded
- stosd
- neg eax
- add eax,[KernelEnd]
- stosd
- inc cx
-
- cmp word [InitRDPtr],0 ; Did we have an initrd?
- je .no_initrd
-
- mov eax,[fs:su_ramdiskat]
- stosd
- mov eax,[InitRDStart]
- stosd
- mov eax,[fs:su_ramdisklen]
- stosd
- inc cx
-
-.no_initrd:
- push dword run_linux_kernel
- push cx ; descriptor list entries count
-
- ; BX points to the final real mode segment, and will be loaded
- ; into DS.
-
- test byte [QuietBoot],QUIET_FLAG
- jz replace_bootstrap
- jmp replace_bootstrap_noclearmode
-
-run_linux_kernel:
-;
-; Set up segment registers and the Linux real-mode stack
-; Note: ds == the real mode segment
-;
- cli
- mov ax,ds
- mov ss,ax
- mov sp,strict word linux_stack
- ; Point HeapEnd to the immediate of the instruction above
-HeapEnd equ $-2 ; Self-modifying code! Fun!
- mov es,ax
- mov fs,ax
- mov gs,ax
-
-;
-; We're done... now RUN THAT KERNEL!!!!
-; Setup segment == real mode segment + 020h; we need to jump to offset
-; zero in the real mode segment.
-;
- add ax,020h
- push ax
- push word 0h
- retf
-
-;
-; Load an older kernel. Older kernels always have 4 setup sectors, can't have
-; initrd, and are always loaded low.
-;
-old_kernel:
- xor ax,ax
- cmp word [InitRDPtr],ax ; Old kernel can't have initrd
- je .load
- mov si,err_oldkernel
- jmp abort_load
-.load:
- mov byte [LoadFlags],al ; Always low
- mov word [KernelVersion],ax ; Version 0.00
- jmp any_kernel
-
-;
-; parse_load_initrd
-;
-; Parse an initrd= option and load the initrds. This sets
-; InitRDStart and InitRDEnd with dword padding between; we then
-; do a global memory shuffle to move it to the end of memory.
-;
-; On entry, EDI points to where to start loading.
-;
-parse_load_initrd:
- push es
- push ds
- mov ax,real_mode_seg
- mov ds,ax
- push cs
- pop es ; DS == real_mode_seg, ES == CS
-
- mov [cs:InitRDStart],edi
- mov [cs:InitRDEnd],edi
-
- mov si,[cs:InitRDPtr]
-
-.get_chunk:
- ; DS:SI points to the start of a name
-
- mov bx,si
-.find_end:
- lodsb
- cmp al,','
- je .got_end
- cmp al,' '
- jbe .got_end
- jmp .find_end
-
-.got_end:
- push ax ; Terminating character
- push si ; Next filename (if any)
- mov byte [si-1],0 ; Zero-terminate
- mov si,bx ; Current filename
-
- push di
- mov di,InitRD ; Target buffer for mangled name
- pm_call pm_mangle_name
- pop di
- call loadinitrd
-
- pop si
- pop ax
- mov [si-1],al ; Restore ending byte
-
- cmp al,','
- je .get_chunk
-
- ; Compute the initrd target location
- ; Note: we round to a page boundary twice here. The first
- ; time it is to make sure we don't use any fractional page
- ; which may be valid RAM but which will be ignored by the
- ; kernel (and therefore is inaccessible.) The second time
- ; it is to make sure we start out on page boundary.
- mov edx,[cs:InitRDEnd]
- sub edx,[cs:InitRDStart]
- mov [su_ramdisklen],edx
- mov eax,[cs:MyHighMemSize]
- and ax,0F000h ; Round to a page boundary
- sub eax,edx
- and ax,0F000h ; Round to a page boundary
- mov [su_ramdiskat],eax
-
- pop ds
- pop es
- ret
-
-;
-; Load RAM disk into high memory
-;
-; Input: InitRD - set to the mangled name of the initrd
-; EDI - location to load
-; Output: EDI - location for next initrd
-; InitRDEnd - updated
-;
-loadinitrd:
- push ds
- push es
- mov ax,cs ; CS == DS == ES
- mov ds,ax
- mov es,ax
- push edi
- mov di,InitRD
- pm_call pm_searchdir ; Look for it in directory
- pop edi
- jz .notthere
-
- push si
- mov si,crlfloading_msg ; Write "Loading "
- call writestr_qchk
- mov si,InitRD ; Write ramdisk name
- call writestr_qchk
- mov si,dotdot_msg ; Write dots
- call writestr_qchk
- pop si
-
-.li_skip_echo:
- mov dx,3
- mov bx,dot_pause
- call load_high
- mov [InitRDEnd],ebx
-
- pop es
- pop ds
- ret
-
-.notthere:
- mov si,err_noinitrd
- call writestr
- mov si,InitRD
- call writestr
- mov si,crlf_msg
- jmp abort_load
-
-;
-; writestr_qchk: writestr, except allows output to be suppressed
-; assumes CS == DS
-;
-writestr_qchk:
- test byte [QuietBoot],QUIET_FLAG
- jz writestr
- ret
-
- section .data16
-crlfloading_msg db CR, LF
-loading_msg db 'Loading ', 0
-dotdot_msg db '.'
-dot_msg db '.', 0
-ready_msg db 'ready.', CR, LF, 0
-err_oldkernel db 'Cannot load a ramdisk with an old kernel image.'
- db CR, LF, 0
-err_noinitrd db CR, LF, 'Could not find ramdisk image: ', 0
-
-boot_image db 'BOOT_IMAGE='
-boot_image_len equ $-boot_image
-
-;
-; Command line options we'd like to take a look at
-;
-%macro cmd_opt 2
-%strlen cmd_opt_len %1
- db cmd_opt_len
- db %1
- dw %2
-%endmacro
-options_list:
- cmd_opt "vga=", opt_vga
- cmd_opt "mem=", opt_mem
- cmd_opt "quiet", opt_quiet
-str_initrd equ $+1 ; Pointer to "initrd=" in memory
- cmd_opt "initrd=", opt_initrd
-%if IS_PXELINUX
- cmd_opt "keeppxe", opt_keeppxe
-%endif
- db 0
-
- section .bss16
- alignb 4
-MyHighMemSize resd 1 ; Possibly adjusted highmem size
-RamdiskMax resd 1 ; Highest address for ramdisk
-KernelSize resd 1 ; Size of kernel in bytes
-KernelSects resd 1 ; Size of kernel in sectors
-KernelEnd resd 1 ; Ending address of the kernel image
-InitRDStart resd 1 ; Start of initrd (pre-relocation)
-InitRDEnd resd 1 ; End of initrd (pre-relocation)
-CmdLineLen resw 1 ; Length of command line including null
-CmdLineEnd resw 1 ; End of the command line in real_mode_seg
-SetupSecs resw 1 ; Number of setup sectors (+bootsect)
-KernelVersion resw 1 ; Kernel protocol version
-;
-; These are derived from the command-line parser
-;
-InitRDPtr resw 1 ; Pointer to initrd= option in command line
-LoadFlags resb 1 ; Loadflags from kernel
-QuietBoot resb 1 ; Set if a quiet boot is requested
; Otherwise Linux kernel
jmp is_linux_kernel
-is_config_file:
- push si
- call make_plain_cmdline
- pm_call pm_is_config_file
- pop si
- call openfd
- call reset_config
- jmp load_config_file
-
; This is an image type we can't deal with
is_bad_image:
mov si,err_badimage
dw is_disk_image ; VK_FDIMAGE
dw is_comboot_image ; VK_COMBOOT
dw is_com32_image ; VK_COM32
- dw is_config_file ; VK_CONFIG
%endif
section .bss16
- global CmdOptPtr
+ global CmdOptPtr, KbdMap
alignb 4
ThisKbdTo resd 1 ; Temporary holder for KbdTimeout
ThisTotalTo resd 1 ; Temporary holder for TotalTimeout
KbdFlags resb 1 ; Check for keyboard escapes
FuncFlag resb 1 ; Escape sequences received from keyboard
KernelType resb 1 ; Kernel type, from vkernel, if known
+KbdMap resb 256 ; Keyboard map
global KernelName
KernelName resb FILENAME_MAX ; Mangled name for kernel
section .config
section .data16
global SerialNotice
SerialNotice db 1 ; Only print this once
+%if IS_PXELINUX
+ extern IPOption
+ global IPAppends, numIPAppends
+ alignz 2
+IPAppends dw IPOption
+numIPAppends equ ($-IPAppends)/2
+%else
+IPAppends equ 0
+numIPAppends equ 0
+%endif
section .text16
;
-; Linux kernel loading code is common.
-;
-%include "runkernel.inc"
-
-;
; COMBOOT-loading code
;
%include "comboot.inc"
%include "com32.inc"
-%include "cmdline.inc"
;
; Boot sector loading code
;
-%include "bootsect.inc"
;
; Abort loading code
;
; Hardware cleanup common code
;
+
+%include "localboot.inc"