📄 runkernel.inc
字号:
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 ; Note AL <- 0 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] cmp cx,255 jna .len_ok mov cx,255 ; Protocol < 0x202 has 255 as hard limit.len_ok: fs rep movsb stosb ; Final null, note AL == 0 already 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: cmp word [InitRDPtr],0 ; Old kernel can't have initrd je 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;; parse_load_initrd;; Parse an initrd= option and load the initrds. Note that we load; from the high end of memory first, so we parse this option from; left to right.;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 si,[cs:InitRDPtr].find_end: lodsb cmp al,' ' ja .find_end ; Now SI points to one character beyond the ; byte that ended this option..get_chunk: dec si ; DS:SI points to a termination byte xor ax,ax xchg al,[si] ; Zero-terminate push si ; Save ending byte address push ax ; Save ending byte.find_start: dec si cmp si,[cs:InitRDPtr] je .got_start cmp byte [si],',' jne .find_start ; It's a comma byte inc si.got_start: push si mov di,InitRD ; Target buffer for mangled name call mangle_name call loadinitrd pop si pop ax pop di mov [di],al ; Restore ending byte cmp si,[cs:InitRDPtr] ja .get_chunk pop ds pop es ret;; Load RAM disk into high memory;; Input: InitRD - set to the mangled name of the initrd;loadinitrd: push ds push es mov ax,cs ; CS == DS == ES mov ds,ax mov es,ax 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 jz .notthere mov cx,dx shl ecx,16 mov cx,ax ; ECX <- ram disk length mov ax,real_mode_seg mov es,ax push ecx ; Bytes to load cmp dword [es:su_ramdisklen],0 je .nopadding ; Don't pad the last initrd add ecx,4095 and cx,0F000h.nopadding: add [es:su_ramdisklen],ecx 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 limit.memsize_ok: inc edx and dx,0F000h ; Round down to 4K boundary sub edx,ecx ; Subtract size of ramdisk and dx,0F000h ; Round down to 4K boundary cmp edx,[KernelEnd] ; Are we hitting the kernel image? jb no_high_mem mov [es:su_ramdiskat],edx ; Load address mov [RamdiskMax],edx ; Next initrd loaded here mov edi,edx ; 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 pop eax ; Bytes to load mov dx,0FFFh ; Pad to page call load_high ; Load the file pop es pop ds jmp crlf ; Print carriage return and return.notthere: mov si,err_noinitrd call cwritestr mov si,InitRDCName call cwritestr mov si,crlf_msg jmp abort_loadno_high_mem: ; Error routine mov si,err_nohighmem jmp abort_load ret section .databoot_image db 'BOOT_IMAGE='boot_image_len equ $-boot_image section .bss alignb 4RamdiskMax resd 1 ; Highest address for ramdiskKernelSize resd 1 ; Size of kernel in bytesKernelSects resd 1 ; Size of kernel in sectorsKernelEnd resd 1 ; Ending address of the kernel imageCmdLineLen resw 1 ; Length of command line including nullSetupSecs resw 1 ; Number of setup sectorsInitRDPtr resw 1 ; Pointer to initrd= option in command lineLoadFlags resb 1 ; Loadflags from kernel
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -