📄 runkernel.inc
字号:
;; $Id: runkernel.inc,v 1.12 2003/08/22 03:39:37 hpa Exp $;; -----------------------------------------------------------------------;; ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved;;;; This program is free software; you can redistribute it and/or modify;; it under the terms of the GNU General Public License as published by;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,;; Bostom 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_SPECIAL_APPEND%macro SPECIAL_APPEND 0%endmacro%endif%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 and less than 8M (if it is; more than 8M, we need to change the logic for loading it anyway...);; 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.;is_linux_kernel: cmp dx,80h ; 8 megs ja kernel_corrupt and dx,dx jnz kernel_sane cmp ax,1024 ; Bootsect + 1 setup sect jb kernel_corruptkernel_sane: push ax push dx push si mov si,loading_msg call cwritestr;; Now start transferring the kernel; push word real_mode_seg pop es movzx eax,ax ; Fix this by using a 32-bit shl edx,16 ; register for the kernel size or eax,edx mov [KernelSize],eax xor edx,edx div dword [ClustSize] ; # of clusters total ; Round up... add edx,byte -1 ; Sets CF if EDX >= 1 adc eax,byte 0 ; Add 1 to EAX if CF set mov [KernelClust],eax;; Now, if we transfer these straight, we'll hit 64K boundaries. Hence we; have to see if we're loading more than 64K, and if so, load it step by; step.;;; 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).; If we have larger than 32K clusters, yes, we're hosed.; call abort_check ; Check for abort key mov ecx,[ClustPerMoby] shr ecx,1 ; Half a moby cmp ecx,[KernelClust] jna .normalkernel mov ecx,[KernelClust].normalkernel: sub [KernelClust],ecx xor bx,bx pop si ; Cluster pointer on stack call getfssec cmp word [es:bs_bootsign],0AA55h jne kernel_corrupt ; Boot sec signature missing;; Save the cluster pointer for later...; push si;; Get the BIOS' idea of what the size of high memory is.; call highmemsize;; 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,KernelCName ; Unmangled kernel name mov cx,[KernelCNameLen] rep movsb mov al,' ' ; Space stosb SPECIAL_APPEND ; Module-specific hook mov si,[CmdOptPtr] ; Options from user input mov cx,(kern_cmd_len+3) >> 2 rep movsd;; 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.; mov si,cmd_line_here mov byte [initrd_flag],0 push es ; Set DS <- real_mode_seg pop dsget_next_opt: lodsb and al,al jz cmdline_end cmp al,' ' jbe get_next_opt dec si mov eax,[si] cmp eax,'vga=' je is_vga_cmd cmp eax,'mem=' je is_mem_cmd%if IS_PXELINUX cmp eax,'keep' ; Is it "keeppxe"? jne .notkeep cmp dword [si+3],'ppxe' jne .notkeep cmp byte [si+7],' ' ; Must be whitespace or EOS ja .notkeep or byte [cs:KeepPXE],1.notkeep:%endif push es ; Save ES -> real_mode_seg push cs pop es ; Set ES <- normal DS mov di,initrd_cmd mov cx,initrd_cmd_len repe cmpsb jne not_initrd mov di,InitRD push si ; mangle_dir mangles si call mangle_name ; Mangle ramdisk name pop si cmp byte [es:InitRD],NULLFILE ; Null filename? seta byte [es:initrd_flag] ; Set flag if notnot_initrd: pop es ; Restore ES -> real_mode_segskip_this_opt: lodsb ; Load from command line cmp al,' ' ja skip_this_opt dec si jmp short get_next_optis_vga_cmd: add si,4 mov eax,[si-1] mov bx,-1 cmp eax,'=nor' ; vga=normal je vc0 dec bx ; bx <- -2 cmp eax,'=ext' ; vga=ext je vc0 dec bx ; bx <- -3 cmp eax,'=ask' ; vga=ask je vc0 call parseint ; vga=<number> jc skip_this_opt ; Not an integervc0: mov [bs_vidmode],bx ; Set video mode jmp short skip_this_optis_mem_cmd: add si,4 call parseint jc skip_this_opt ; Not an integer%if HIGHMEM_SLOP != 0 sub ebx,HIGHMEM_SLOP%endif mov [cs:HighMemSize],ebx jmp short skip_this_optcmdline_end: push cs ; Restore standard DS pop ds sub si,cmd_line_here mov [CmdLineLen],si ; Length including final null;; Now check if we have a large kernel, which needs to be loaded high; 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 cmp word [es:su_version],0200h ; Setup code version 2.0 jb old_kernel ; Old kernel, load low cmp word [es:su_version],0201h ; Version 2.01+? jb new_kernel ; If 2.00, skip this step mov word [es:su_heapend],linux_stack ; Set up the heap or byte [es:su_loadflags],80h ; Let the kernel know we care cmp word [es:su_version],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 movzx ax,byte [es:bs_setupsecs] ; Variable # of setup sectors mov [SetupSecs],ax;; About to load the kernel. This is a modern kernel, so use the boot flags; we were provided.; mov al,[es:su_loadflags] mov [LoadFlags],al;; 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: mov si,KernelCName ; Print kernel name part of call cwritestr ; "Loading" message mov si,dotdot_msg ; Print dots call cwritestr mov eax,[HighMemSize] sub eax,100000h ; Load address cmp eax,[KernelSize] jb no_high_mem ; Not enough high memory;; Move the stuff beyond the setup code to high memory at 100000h; movzx esi,word [SetupSecs] ; Setup sectors inc si ; plus 1 boot sector shl si,9 ; Convert to bytes mov ecx,8000h ; 32K sub ecx,esi ; Number of bytes to copy push ecx add esi,(real_mode_seg << 4) ; Pointer to source mov edi,100000h ; Copy to address 100000h call bcopy ; Transfer to high memory ; On exit EDI -> where to load the rest mov si,dot_msg ; Progress report call cwritestr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -