pcbios.s
来自「linux下从网卡远程启动」· S 代码 · 共 636 行
S
636 行
#ifdef PCBIOS#ifdef GAS291#define DATA32 data32;#else#define DATA32 data32#endif .section ".text" .section ".text16", "ax", @progbits .previous .code32 .arch i386#if defined(CONFIG_TSC_CURRTICKS)#undef CONFIG_BIOS_CURRTICKS#else#define CONFIG_BIOS_CURRTICKS 1#endif#if defined(CONFIG_BIOS_CURRTICKS)/**************************************************************************CURRTICKS - Get TimeUse direct memory access to BIOS variables, longword 0040:006C (tickstoday) and byte 0040:0070 (midnight crossover flag) instead of callingtimeofday BIOS interrupt.**************************************************************************/ .globl currtickscurrticks: pushl %ebp pushl %ebx pushl %esi pushl %edi#ifdef FREEBSD_PXEEMU cmpb $0, pxeemu_nbp_active jne currticks_postswitch#endif pushl $ 10f pushl $ 20f - 10f call _real_call .section ".text16"10: .code16 ret20: .code32 .previous#ifdef FREEBSD_PXEEMUcurrticks_postswitch:#endif movl virt_offset, %ebp negl %ebp /* Physical address 0 */ movl 0x46C(%ebp), %eax movb 0x470(%ebp), %bl cmpb $0, %bl je notmidnite movb $0, 0x470(%ebp) /* clear the flag */ addl $0x1800b0,days /* 0x1800b0 ticks per day */notmidnite: addl days,%eax popl %edi popl %esi popl %ebx popl %ebp ret#endif /* CONFIG_BIOS_CURRTICKS *//**************************************************************************CONSOLE_PUTC - Print a character on console**************************************************************************/ .globl console_putcconsole_putc:#ifdef FREEBSD_PXEEMU .globl pxeemu_console_putc cmpb $0, pxeemu_nbp_active je console_putc_switch movb $0x0e, %ah movb %cl, %al pushl %eax call pxeemu_console_putc addl $4, %esp retconsole_putc_switch:#endif pushl %ebp movl %esp,%ebp pushl %ebx pushl %esi pushl %edi movb 8(%ebp),%cl pushl $ 10f pushl $ 20f - 10f call _real_call .section ".text16"10: .code16 movl $1,%ebx movb $0x0e,%ah movb %cl,%al int $0x10 ret20: .code32 .previous#ifdef FREEBSD_PXEEMUconsole_putc_exit:#endif popl %edi popl %esi popl %ebx popl %ebp ret/**************************************************************************CONSOLE_GETC - Get a character from console**************************************************************************/ .globl console_getcconsole_getc: pushl %ebx pushl %esi pushl %edi pushl $ 10f pushl $ 20f - 10f call _real_call .section ".text16"10: .code16 movb $0x0,%ah int $0x16 movb %al,%bl ret20: .code32 .previous xor %eax,%eax movzbl %bl,%eax popl %edi popl %esi popl %ebx ret/**************************************************************************CONSOLE_ISCHAR - Check for keyboard interrupt**************************************************************************/ .globl console_ischarconsole_ischar: pushl %ebx pushl %esi pushl %edi pushl $ 10f pushl $ 20f - 10f call _real_call .section ".text16"10: .code16 xorw %bx,%bx movb $0x1,%ah int $0x16 jz 2f movb %al,%bl2: ret20: .code32 .previous movzbl %bl,%eax popl %edi popl %esi popl %ebx ret/**************************************************************************GETSHIFT - Get keyboard shift state**************************************************************************/ .globl getshiftgetshift: pushl %ebx pushl %esi pushl %edi pushl $ 10f pushl $ 20f - 10f .section ".text16"10: .code16 movb $2,%ah int $0x16 andb $0xdf,%al movw %ax,%bx ret20: .code32 .previous movzbl %bl,%eax popl %edi popl %esi popl %ebx ret/**************************************************************************INT15 - Call Interrupt 0x15**************************************************************************/ .globl int15int15: pushl %ebp movl %esp,%ebp pushl %ebx pushl %esi pushl %edi movl 8(%ebp),%ecx /* _real_call destroys %eax */ pushl $ 10f pushl $ 20f - 10f call _real_call .section ".text16"10: .code16 movw %cx,%ax stc /* in case function not supported */ int $0x15 jc int15status movb $0,%ahint15status: movb %ah,%bl /* _real_call destroys %eax */ ret20: .code32 .previous movzbl %bl,%eax popl %edi popl %esi popl %ebx popl %ebp ret#ifdef POWERSAVE/**************************************************************************CPU_NAP - Save power by halting the CPU until the next interrupt**************************************************************************/ .globl cpu_napcpu_nap: pushl %ebx pushl %esi pushl %edi pushl $ 10f pushl $ 20f - 10f call _real_call .section ".text16"10: .code16 hlt ret20: .code32 .previous popl %edi popl %esi popl %ebx ret#endif /* POWERSAVE *//**************************************************************************E820_MEMSIZE - Get a listing of memory regions**************************************************************************/ .globl meme820#define SMAP 0x534d4150meme820: pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi movl 8(%ebp), %edi /* Address to return e820 structures at */ movl 12(%ebp), %esi /* Maximum number of e820 structurs to return */ pushl %esi /* Multiply %esi by 20 */ movl %esi, %eax movl %esi, %ebx shll $2, %eax shll $4, %ebx addl %eax, %ebx pushl %ebx pushl $ 10f pushl $ 20f - 10f call _real_call .section ".text16"10: .code16 /* Allocate space on the stack for the maximum # of e820 structures */ popw %ax subw %bx, %sp movw %sp, %di /* point to the e820 array list */ pushw %ax xorl %ebx, %ebx /* continuation pointer */jmpe820: movl $0xe820, %eax /* e820, upper word zeroed */ movl $SMAP, %edx /* ascii `SMAP' */ movl $20, %ecx /* size of e820rec */ pushw %ss popw %es /* %di was setup earlier */ int $0x15 /* Make the call */ jc bail820 cmpl $SMAP, %eax /* check the return is `SMAP' */ jne bail820good820: /* If this is useable memory, we save it by simply advancing %di by * sizeof(e820rec) */ decl %esi /* up to 32 entries */ testl %esi,%esi jz bail820 addw $20, %diagain820: cmpl $0, %ebx /* check to see if %ebx is set to EOF */ jne jmpe820bail820: ret20: .code32 .previous popl %ecx /* Get the maximum return size */ pushl %esi /* Save the structure count */ /* Copy the structures to the return buffer */ movl %eax, %esi movl 8(%ebp), %edi rep movsb popl %esi popl %eax subl %esi, %eax /* Compute how many structure we read */ /* Restore everything else */ popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /**************************************************************************MEMSIZE - Determine size of extended memory**************************************************************************/ .globl memsizememsize: pushl %ebx pushl %esi pushl %edi pushl $ 10f pushl $ 20f - 10f call _real_call .section ".text16"10: .code16 stc # fix to work around buggy xorw %cx,%cx # BIOSes which dont clear/set xorw %dx,%dx # carry on pass/error of # e801h memory size call # or merely pass cx,dx though # without changing them. movw $0xe801,%ax int $0x15 jc 3f cmpw $0,%cx # Kludge to handle BIOSes jne 1f # which report their extended cmpw $0,%dx # memory in AX/BX rather than je 2f # CX/DX. The spec I have read1: movw %cx,%ax # seems to indicate AX/BX movw %dx,%bx # are more reasonable anyway...2: andl $0xffff,%eax andl $0xffff,%ebx shll $6,%ebx addl %ebx,%eax jmp 4f3: movw $0x8800,%ax int $0x15 andl $0xffff,%eax4: movl %eax,%esi ret20: .code32 .previous movl %esi,%eax popl %edi popl %esi popl %ebx ret/**************************************************************************BASEMEMSIZE - Get size of the conventional (base) memory**************************************************************************/ .globl basememsizebasememsize: pushl %ebx pushl %esi pushl %edi pushl $ 10f pushl $ 20f - 10f call _real_call .section ".text16"10: .code16 int $0x12 movw %ax,%cx ret20: .code32 .previous movw %cx,%ax popl %edi popl %esi popl %ebx ret/**************************************************************************DISK_INIT - Initialize the disk system**************************************************************************/#ifdef CAN_BOOT_DISK .globl disk_initdisk_init: pushl %ebx pushl %esi pushl %edi pushl $ 10f pushl $ 20f - 10f call _real_call .section ".text16"10: .code16 xorw %ax,%ax movb $0x80,%dl int $0x13 ret20: .code32 .previous popl %edi popl %esi popl %ebx ret#endif/**************************************************************************DISK_READ - Read a sector from disk**************************************************************************/#ifdef CAN_BOOT_DISK .globl pcbios_disk_readpcbios_disk_read: pushl %ebp movl %esp,%ebp pushl %ebx pushl %esi pushl %edi movb 8(%ebp),%dl /* drive number */ movb 16(%ebp),%dh /* head number */ movb 12(%ebp),%ch /* cylinder number */ movb 13(%ebp),%cl /* cylinder number */ shl $6,%cl orb 20(%ebp),%cl /* sector number */ movw 26(%ebp),%si rorw $4,%si movw 24(%ebp),%bx /* buffer */ pushl $ 10f pushl $ 20f - 10f call _real_call .section ".text16"10: .code16 movw $0x0201,%ax movw %si,%es int $0x13 jc 1f xorw %ax,%ax1: movw %ax,%bx ret20: .code32 .previous movzwl %bx,%eax popl %edi popl %esi popl %ebx popl %ebp ret#endif#ifdef FREEBSD_PXEEMU.globl initsp.globl pxeemu_nbp_activepxeemu_nbp_active: .byte 0#endifdays: .long 0#ifndef CONFIG_PCI_DIRECT .globl bios32_callbios32_call: pushl %ebp pushl %eax call _virt_to_phys pushl %ebp movl 8(%esp), %ebp movl 4(%esp), %eax pushl %cs call %esi cli cld movl %ebp, 8(%esp) movl %eax, 4(%esp) popl %ebp pushfl call _phys_to_virt popfl popl %eax popl %ebp ret#endif /* CONFIG_PCI_DIRECT *//**************************************************************************UNDI_CALL - wrapper around real-mode UNDI API calls**************************************************************************/ .globl __undi_call__undi_call: pushl %ebp movl %esp,%ebp pushl %esi pushl %edi pushl %ebx movw 8(%ebp),%cx /* Seg:off addr of undi_call_info_t struct */ movw 12(%ebp),%dx /* Pass to 16-bit code in %cx:%dx */ pushl $ 10f pushl $ 20f - 10f call _real_call .section ".text16"10: .code16 movw %cx,%es /* Seg:off addr of undi_call_info_t struct */ movw %dx,%bx /* into %es:%bx */ movw %es:8(%bx),%ax /* Transfer contents of undi_call_info_t */ pushw %ax /* structure to the real-mode stack */ movw %es:6(%bx),%ax pushw %ax movw %es:4(%bx),%ax pushw %ax lcall *%es:0(%bx) /* Do the UNDI call */ cld /* Don't know whether or not we need this */ /* but pxelinux includes it for some reason, */ /* so we put it in just in case. */ popw %cx /* Tidy up the stack */ popw %cx popw %cx movw %ax,%cx /* Return %ax via %cx */ ret 20: .code32 .previous xorl %eax,%eax /* %ax is returned via %cx */ movw %cx,%ax popl %ebx popl %edi popl %esi popl %ebp ret/**************************************************************************TRIVIAL_IRQ_HANDLER - simple IRQ handler that just increments a counter**************************************************************************/ .globl _trivial_irq_handler_start .globl _trivial_irq_handler .globl _trivial_irq_trigger_count .globl _trivial_irq_chain_to .globl _trivial_irq_chain .globl _trivial_irq_handler_end .code16_trivial_irq_handler_start:_trivial_irq_handler: pushw %bx call 1f /* Position-independent access to */1: popw %bx /* irq_triggered. */ incw %cs:(_trivial_irq_trigger_count-1b)(%bx) popw %bx iret_trivial_irq_trigger_count: .word 0_trivial_irq_chain_to: .long 0_trivial_irq_chain: .byte 0_trivial_irq_handler_end: .code32/**************************************************************************FAKE_IRQ - fake a hardware IRQ**************************************************************************/ .globl fake_irqfake_irq: pushl %ebp movl %esp,%ebp pushl %esi pushl %edi pushl %ebx movb 8(%ebp),%cl /* Convert IRQ number to INT number: */ subb $0x08,%cl /* Invert bit 3, set bits 4-7 iff irq < 8*/ xorb $0x70,%cl /* Invert bits 4-6 */ andb $0x7f,%cl /* Clear bit 7 */ movb %cl,fake_irq_int_instruction+1 /* Store in int instruction */ pushl $ 10f pushl $ 20f - 10f call _real_call .section ".text16"10: .code16fake_irq_int_instruction: int $0x00 /* Int no. gets replaced */ ret20: .code32 .previous popl %ebx popl %edi popl %esi popl %ebp ret #endif /* PCBIOS */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?