📄 runkernel.inc
字号:
call abort_check pop ecx ; Number of bytes in the initial portion pop si ; Restore file handle/cluster pointer mov eax,[KernelSize] sub eax,8000h ; Amount of kernel not yet loaded jbe high_load_done ; Zero left (tiny kernel) call load_high ; Copy the filehigh_load_done: mov ax,real_mode_seg ; Set to real mode seg mov es,ax mov si,dot_msg call cwritestr;; 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 [es:su_ramdisklen1],ax ; Ram disk length mov [es:su_ramdisklen2],dx mov edx,[HighMemSize] ; End of memory dec edx mov eax,[RamdiskMax] ; Highest address allowed by kernel cmp edx,eax jna memsize_ok mov edx,eax ; Adjust to fit inside limitmemsize_ok: inc edx 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 [es:su_ramdiskat],edx ; Load address call loadinitrd ; Load initial ramdisk jmp short initrd_endinitrd_notthere: mov si,err_noinitrd call cwritestr mov si,InitRDCName call cwritestr mov si,crlf_msg jmp abort_loadno_high_mem: mov si,err_nohighmem ; Error routine jmp abort_loadinitrd_end:nk_noinitrd:;; Abandon hope, ye that enter here! We do no longer permit aborts.; call abort_check ; Last chance!! mov si,ready_msg call cwritestr call vgaclearmode ; We can't trust ourselves after this 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 fs,ax;; Copy command line. Unfortunately, the kernel boot protocol requires; the command line to exist in the 9xxxxh range even if the rest of the; setup doesn't.; cli ; In case of hooked interrupts test byte [LoadFlags],LOAD_HIGH jz need_high_cmdline cmp word [fs:su_version],0202h ; Support new cmdline protocol? jb need_high_cmdline ; New cmdline protocol ; Store 32-bit (flat) pointer to command line mov dword [fs:su_cmd_line_ptr],(real_mode_seg << 4) + cmd_line_here jmp short in_proper_placeneed_high_cmdline:;; Copy command line up to 90000h; mov ax,9000h mov es,ax mov si,cmd_line_here mov di,si mov [fs:kern_cmd_magic],word CMD_MAGIC ; Store magic mov [fs:kern_cmd_offset],di ; Store pointer mov cx,[CmdLineLen] add cx,byte 3 shr cx,2 ; Convert to dwords fs rep movsd push fs pop es test byte [LoadFlags],LOAD_HIGH jnz in_proper_place ; If high load, we're done;; Loading low; we can't assume it's safe to run in place.;; Copy real_mode stuff up to 90000h; mov ax,9000h mov es,ax mov cx,[SetupSecs] inc cx ; Setup + boot sector shl cx,7 ; Sectors -> dwords xor si,si xor di,di fs rep movsd ; Copy setup + boot sector;; Some kernels in the 1.2 ballpark but pre-bzImage have more than 4; setup sectors, but the boot protocol had not yet been defined. They; rely on a signature to figure out if they need to copy stuff from; the "protected mode" kernel area. Unfortunately, we used that area; as a transfer buffer, so it's going to find the signature there.; Hence, zero the low 32K beyond the setup area.; mov di,[SetupSecs] inc di ; Setup + boot sector mov cx,32768/512 ; Sectors/32K sub cx,di ; Remaining sectors shl di,9 ; Sectors -> bytes shl cx,7 ; Sectors -> dwords xor eax,eax rep stosd ; Clear region;; Copy the kernel down to the "low" location; mov ecx,[KernelSize] mov esi,100000h mov edi,10000h call bcopy;; Now everything is where it needs to be...;; When we get here, es points to the final segment, either; 9000h or real_mode_seg;in_proper_place:;; 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],0200hroot_not_floppy:;; Copy the disk table to high memory, then re-initialize the floppy; controller;%if IS_SYSLINUX || IS_MDSLINUX lgs si,[cs:fdctab] mov di,linux_fdctab mov cx,6 ; 12 bytes gs rep movsw mov [cs:fdctab],word linux_fdctab ; Save new floppy tab pos mov [cs:fdctab+2],es%endif;; Linux wants the floppy motor shut off before starting the kernel,; at least bootsect.S seems to imply so.;kill_motor: xor ax,ax xor dx,dx int 13h;; If we're debugging, wait for a keypress so we can read any debug messages;%ifdef debug xor ax,ax int 16h%endif;; Set up segment registers and the Linux real-mode stack; Note: es == the real mode segment; cli mov bx,es mov ds,bx mov fs,bx mov gs,bx mov ss,bx mov sp,linux_stack;; 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 bx,020h push bx 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: test byte [initrd_flag],1 ; Old kernel can't have initrd jz load_old_kernel mov si,err_oldkernel jmp abort_loadload_old_kernel: mov word [SetupSecs],4 ; Always 4 setup sectors mov byte [LoadFlags],0 ; Always low jmp read_kernel;; Load RAM disk into high memory;; Need to be set:; su_ramdiskat - Where in memory to load; su_ramdisklen - Size of file; SI - initrd filehandle/cluster pointer;loadinitrd: push es ; Save ES on entry mov ax,real_mode_seg mov es,ax mov edi,[es:su_ramdiskat] ; initrd load address push si mov si,crlfloading_msg ; Write "Loading " call cwritestr mov si,InitRDCName ; Write ramdisk name call cwritestr mov si,dotdot_msg ; Write dots call cwritestr pop si mov eax,[es:su_ramdisklen] call load_high ; Load the file call crlf pop es ; Restore original ES ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -