17c478bd9Sstevel@tonic-gate/* 27c478bd9Sstevel@tonic-gate * GRUB -- GRand Unified Bootloader 37c478bd9Sstevel@tonic-gate * Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc. 47c478bd9Sstevel@tonic-gate * 57c478bd9Sstevel@tonic-gate * This program is free software; you can redistribute it and/or modify 67c478bd9Sstevel@tonic-gate * it under the terms of the GNU General Public License as published by 77c478bd9Sstevel@tonic-gate * the Free Software Foundation; either version 2 of the License, or 87c478bd9Sstevel@tonic-gate * (at your option) any later version. 97c478bd9Sstevel@tonic-gate * 107c478bd9Sstevel@tonic-gate * This program is distributed in the hope that it will be useful, 117c478bd9Sstevel@tonic-gate * but WITHOUT ANY WARRANTY; without even the implied warranty of 127c478bd9Sstevel@tonic-gate * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 137c478bd9Sstevel@tonic-gate * GNU General Public License for more details. 147c478bd9Sstevel@tonic-gate * 157c478bd9Sstevel@tonic-gate * You should have received a copy of the GNU General Public License 167c478bd9Sstevel@tonic-gate * along with this program; if not, write to the Free Software 177c478bd9Sstevel@tonic-gate * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 187c478bd9Sstevel@tonic-gate */ 197c478bd9Sstevel@tonic-gate 207c478bd9Sstevel@tonic-gate 217c478bd9Sstevel@tonic-gate/* 227c478bd9Sstevel@tonic-gate * Note: These functions defined in this file may be called from C. 237c478bd9Sstevel@tonic-gate * Be careful of that you must not modify some registers. Quote 247c478bd9Sstevel@tonic-gate * from gcc-2.95.2/gcc/config/i386/i386.h: 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate 1 for registers not available across function calls. 277c478bd9Sstevel@tonic-gate These must include the FIXED_REGISTERS and also any 287c478bd9Sstevel@tonic-gate registers that can be used without being saved. 297c478bd9Sstevel@tonic-gate The latter must include the registers where values are returned 307c478bd9Sstevel@tonic-gate and the register where structure-value addresses are passed. 317c478bd9Sstevel@tonic-gate Aside from that, you can include as many other registers as you like. 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg 347c478bd9Sstevel@tonic-gate{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate#define ASM_FILE 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate#include "shared.h" 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate#ifdef STAGE1_5 427c478bd9Sstevel@tonic-gate# define ABS(x) ((x) - EXT_C(main) + 0x2200) 437c478bd9Sstevel@tonic-gate#else 447c478bd9Sstevel@tonic-gate# define ABS(x) ((x) - EXT_C(main) + 0x8200) 457c478bd9Sstevel@tonic-gate#endif 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate .file "asm.S" 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate .text 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate /* Tell GAS to generate 16-bit instructions so that this code works 527c478bd9Sstevel@tonic-gate in real mode. */ 537c478bd9Sstevel@tonic-gate .code16 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate#ifndef STAGE1_5 567c478bd9Sstevel@tonic-gate /* 577c478bd9Sstevel@tonic-gate * In stage2, do not link start.S with the rest of the source 587c478bd9Sstevel@tonic-gate * files directly, so define the start symbols here just to 597c478bd9Sstevel@tonic-gate * force ld quiet. These are not referred anyway. 607c478bd9Sstevel@tonic-gate */ 617c478bd9Sstevel@tonic-gate .globl start, _start 627c478bd9Sstevel@tonic-gatestart: 637c478bd9Sstevel@tonic-gate_start: 647c478bd9Sstevel@tonic-gate#endif /* ! STAGE1_5 */ 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gateENTRY(main) 677c478bd9Sstevel@tonic-gate /* 687c478bd9Sstevel@tonic-gate * Guarantee that "main" is loaded at 0x0:0x8200 in stage2 and 697c478bd9Sstevel@tonic-gate * at 0x0:0x2200 in stage1.5. 707c478bd9Sstevel@tonic-gate */ 717c478bd9Sstevel@tonic-gate ljmp $0, $ABS(codestart) 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /* 747c478bd9Sstevel@tonic-gate * Compatibility version number 757c478bd9Sstevel@tonic-gate * 767c478bd9Sstevel@tonic-gate * These MUST be at byte offset 6 and 7 of the executable 777c478bd9Sstevel@tonic-gate * DO NOT MOVE !!! 787c478bd9Sstevel@tonic-gate */ 797c478bd9Sstevel@tonic-gate . = EXT_C(main) + 0x6 807c478bd9Sstevel@tonic-gate .byte COMPAT_VERSION_MAJOR, COMPAT_VERSION_MINOR 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate /* 837c478bd9Sstevel@tonic-gate * This is a special data area 8 bytes from the beginning. 847c478bd9Sstevel@tonic-gate */ 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate . = EXT_C(main) + 0x8 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gateVARIABLE(install_partition) 897c478bd9Sstevel@tonic-gate .long 0xFFFFFF 907c478bd9Sstevel@tonic-gate/* This variable is here only because of a historical reason. */ 917c478bd9Sstevel@tonic-gateVARIABLE(saved_entryno) 927c478bd9Sstevel@tonic-gate .long 0 937c478bd9Sstevel@tonic-gateVARIABLE(stage2_id) 947c478bd9Sstevel@tonic-gate .byte STAGE2_ID 957c478bd9Sstevel@tonic-gateVARIABLE(force_lba) 967c478bd9Sstevel@tonic-gate .byte 0 977c478bd9Sstevel@tonic-gateVARIABLE(version_string) 987c478bd9Sstevel@tonic-gate .string VERSION 997c478bd9Sstevel@tonic-gateVARIABLE(config_file) 1007c478bd9Sstevel@tonic-gate#ifndef STAGE1_5 1017c478bd9Sstevel@tonic-gate .string "/boot/grub/menu.lst" 1027c478bd9Sstevel@tonic-gate#else /* STAGE1_5 */ 1037c478bd9Sstevel@tonic-gate .long 0xffffffff 1047c478bd9Sstevel@tonic-gate .string "/boot/grub/stage2" 1057c478bd9Sstevel@tonic-gate#endif /* STAGE1_5 */ 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* 1087c478bd9Sstevel@tonic-gate * Leave some breathing room for the config file name. 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate 111*af28f636SEnrico Perla - Sun Microsystems . = EXT_C(main) + 0x60 112*af28f636SEnrico Perla - Sun MicrosystemsVARIABLE(fake_mboot) 113*af28f636SEnrico Perla - Sun Microsystems .long 0x1BADB002 114*af28f636SEnrico Perla - Sun Microsystems .long 0x00010003 115*af28f636SEnrico Perla - Sun Microsystems .long -0x1BAEB005 1167ce76caaSEnrico Perla - Sun Microsystems /* 117*af28f636SEnrico Perla - Sun Microsystems * installgrub will place the rest of the fake 118*af28f636SEnrico Perla - Sun Microsystems * multiboot header here. 1197ce76caaSEnrico Perla - Sun Microsystems */ 120*af28f636SEnrico Perla - Sun Microsystems .= EXT_C(main) + 0x140 1217c478bd9Sstevel@tonic-gate/* the real mode code continues... */ 1227c478bd9Sstevel@tonic-gatecodestart: 1237c478bd9Sstevel@tonic-gate cli /* we're not safe here! */ 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate /* set up %ds, %ss, and %es */ 1267c478bd9Sstevel@tonic-gate xorw %ax, %ax 1277c478bd9Sstevel@tonic-gate movw %ax, %ds 1287c478bd9Sstevel@tonic-gate movw %ax, %ss 1297c478bd9Sstevel@tonic-gate movw %ax, %es 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate#ifndef SUPPORT_DISKLESS 1327c478bd9Sstevel@tonic-gate /* 1337c478bd9Sstevel@tonic-gate * Save the sector number of the second sector (i.e. this sector) 1347c478bd9Sstevel@tonic-gate * in INSTALL_SECOND_SECTOR. See also "stage2/start.S". 1357c478bd9Sstevel@tonic-gate */ 1367c478bd9Sstevel@tonic-gate ADDR32 movl %ebp, EXT_C(install_second_sector) 1377c478bd9Sstevel@tonic-gate#endif 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate /* set up the real mode/BIOS stack */ 1407c478bd9Sstevel@tonic-gate movl $STACKOFF, %ebp 1417c478bd9Sstevel@tonic-gate movl %ebp, %esp 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate sti /* we're safe again */ 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate#ifndef SUPPORT_DISKLESS 1467c478bd9Sstevel@tonic-gate /* save boot drive reference */ 1477c478bd9Sstevel@tonic-gate ADDR32 movb %dl, EXT_C(boot_drive) 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* reset disk system (%ah = 0) */ 1507c478bd9Sstevel@tonic-gate int $0x13 1517c478bd9Sstevel@tonic-gate#endif 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate /* transition to protected mode */ 1547c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate /* The ".code32" directive takes GAS out of 16-bit mode. */ 1577c478bd9Sstevel@tonic-gate .code32 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate /* clean out the bss */ 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate /* set %edi to the bss starting address */ 1627c478bd9Sstevel@tonic-gate#if defined(HAVE_USCORE_USCORE_BSS_START_SYMBOL) 1637c478bd9Sstevel@tonic-gate movl $__bss_start, %edi 1647c478bd9Sstevel@tonic-gate#elif defined(HAVE_USCORE_EDATA_SYMBOL) 1657c478bd9Sstevel@tonic-gate movl $_edata, %edi 1667c478bd9Sstevel@tonic-gate#elif defined(HAVE_EDATA_SYMBOL) 1677c478bd9Sstevel@tonic-gate movl $edata, %edi 1687c478bd9Sstevel@tonic-gate#endif 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* set %ecx to the bss end */ 1717c478bd9Sstevel@tonic-gate#if defined(HAVE_END_SYMBOL) 1727c478bd9Sstevel@tonic-gate movl $end, %ecx 1737c478bd9Sstevel@tonic-gate#elif defined(HAVE_USCORE_END_SYMBOL) 1747c478bd9Sstevel@tonic-gate movl $_end, %ecx 1757c478bd9Sstevel@tonic-gate#endif 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate /* compute the bss length */ 1787c478bd9Sstevel@tonic-gate subl %edi, %ecx 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /* zero %al */ 1817c478bd9Sstevel@tonic-gate xorb %al, %al 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate /* set the direction */ 1847c478bd9Sstevel@tonic-gate cld 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* clean out */ 1877c478bd9Sstevel@tonic-gate rep 1887c478bd9Sstevel@tonic-gate stosb 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate /* 1917c478bd9Sstevel@tonic-gate * Call the start of main body of C code, which does some 1927c478bd9Sstevel@tonic-gate * of it's own initialization before transferring to "cmain". 1937c478bd9Sstevel@tonic-gate */ 1947c478bd9Sstevel@tonic-gate call EXT_C(init_bios_info) 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate/* 1987c478bd9Sstevel@tonic-gate * This call is special... it never returns... in fact it should simply 1997c478bd9Sstevel@tonic-gate * hang at this point! 2007c478bd9Sstevel@tonic-gate */ 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gateENTRY(stop) 2037c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate /* 2067c478bd9Sstevel@tonic-gate * This next part is sort of evil. It takes advantage of the 2077c478bd9Sstevel@tonic-gate * byte ordering on the x86 to work in either 16-bit or 32-bit 2087c478bd9Sstevel@tonic-gate * mode, so think about it before changing it. 2097c478bd9Sstevel@tonic-gate */ 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gateENTRY(hard_stop) 2127c478bd9Sstevel@tonic-gate hlt 2137c478bd9Sstevel@tonic-gate jmp EXT_C(hard_stop) 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate#ifndef STAGE1_5 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate/************************************************************************** 2187c478bd9Sstevel@tonic-gateUNDI_CALL - wrapper around real-mode UNDI API calls 2197c478bd9Sstevel@tonic-gate**************************************************************************/ 2207c478bd9Sstevel@tonic-gateENTRY(__undi_call) 2217c478bd9Sstevel@tonic-gate pushl %ebp 2227c478bd9Sstevel@tonic-gate movl %esp,%ebp 2237c478bd9Sstevel@tonic-gate pushl %esi 2247c478bd9Sstevel@tonic-gate pushl %edi 2257c478bd9Sstevel@tonic-gate pushl %ebx 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate movw 8(%ebp),%cx /* Seg:off addr of undi_call_info_t struct */ 2287c478bd9Sstevel@tonic-gate movw 12(%ebp),%dx /* Pass to 16-bit code in %cx:%dx */ 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 2317c478bd9Sstevel@tonic-gate .code16 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate movw %cx,%es /* Seg:off addr of undi_call_info_t struct */ 2347c478bd9Sstevel@tonic-gate movw %dx,%bx /* into %es:%bx */ 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate movw %es:8(%bx),%ax /* Transfer contents of undi_call_info_t */ 2377c478bd9Sstevel@tonic-gate pushw %ax /* structure to the real-mode stack */ 2387c478bd9Sstevel@tonic-gate movw %es:6(%bx),%ax 2397c478bd9Sstevel@tonic-gate pushw %ax 2407c478bd9Sstevel@tonic-gate movw %es:4(%bx),%ax 2417c478bd9Sstevel@tonic-gate pushw %ax 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate lcall *%es:0(%bx) /* Do the UNDI call */ 2447c478bd9Sstevel@tonic-gate cld /* Don't know whether or not we need this */ 2457c478bd9Sstevel@tonic-gate /* but pxelinux includes it for some reason, */ 2467c478bd9Sstevel@tonic-gate /* so we put it in just in case. */ 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate popw %cx /* Tidy up the stack */ 2497c478bd9Sstevel@tonic-gate popw %cx 2507c478bd9Sstevel@tonic-gate popw %cx 2517c478bd9Sstevel@tonic-gate movw %ax,%cx /* Return %ax via %cx */ 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 2547c478bd9Sstevel@tonic-gate .code32 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate xorl %eax,%eax /* %ax is returned via %cx */ 2577c478bd9Sstevel@tonic-gate movw %cx,%ax 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate popl %ebx 2607c478bd9Sstevel@tonic-gate popl %edi 2617c478bd9Sstevel@tonic-gate popl %esi 2627c478bd9Sstevel@tonic-gate popl %ebp 2637c478bd9Sstevel@tonic-gate ret 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate/************************************************************************** 2667c478bd9Sstevel@tonic-gateUNDI_IRQ_HANDLER - UNDI IRQ handler: calls PXENV_UNDI_ISR and send EOI 2677c478bd9Sstevel@tonic-gateNOTE: For some reason, this handler needs to be aligned. Else, the 2687c478bd9Sstevel@tonic-gate undi driver won't get the trigger count on some platforms. 2697c478bd9Sstevel@tonic-gate**************************************************************************/ 2707c478bd9Sstevel@tonic-gate .align 4 2717c478bd9Sstevel@tonic-gateENTRY(_undi_irq_handler) 2727c478bd9Sstevel@tonic-gate .code16 2737c478bd9Sstevel@tonic-gate pushw %ax 2747c478bd9Sstevel@tonic-gate pushw %bx 2757c478bd9Sstevel@tonic-gate pushw %cx 2767c478bd9Sstevel@tonic-gate call 1f /* Position-independent access to */ 2777c478bd9Sstevel@tonic-gate1: popw %bx /* various locations. */ 2787c478bd9Sstevel@tonic-gate pushw %bx /* save for after UNDI call */ 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate /* set funcflag to PXENV_UNDI_ISR_IN_START */ 2817c478bd9Sstevel@tonic-gate movw $1,%cs:(pxenv_undi_isr-1b+2)(%bx) 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate /* push pxenv_undi_isr struct on stack */ 2847c478bd9Sstevel@tonic-gate movl $(ABS(pxenv_undi_isr)),%eax 2857c478bd9Sstevel@tonic-gate movw %ax,%cx 2867c478bd9Sstevel@tonic-gate shrl $4,%eax /* get segment */ 2877c478bd9Sstevel@tonic-gate pushw %ax 2887c478bd9Sstevel@tonic-gate andw $0xf,%cx /* get offset */ 2897c478bd9Sstevel@tonic-gate pushw %cx 2907c478bd9Sstevel@tonic-gate movw $0x14,%ax /* opcode PXENV_UNDI_ISR */ 2917c478bd9Sstevel@tonic-gate pushw %ax 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate lcall *%cs:(pxenv_entrypointsp-1b)(%bx) /* Do the UNDI call */ 2947c478bd9Sstevel@tonic-gate cld /* Don't know whether or not we need this */ 2957c478bd9Sstevel@tonic-gate /* but pxelinux includes it for some reason, */ 2967c478bd9Sstevel@tonic-gate /* so we put it in just in case. */ 2977c478bd9Sstevel@tonic-gate popw %cx /* Tidy up the stack */ 2987c478bd9Sstevel@tonic-gate popw %cx 2997c478bd9Sstevel@tonic-gate popw %cx 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate popw %bx /* restore old position reg */ 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate cmpw $0,%ax /* did the UNDI call succeed? */ 3047c478bd9Sstevel@tonic-gate jne 3f 3057c478bd9Sstevel@tonic-gate movw %cs:(pxenv_undi_isr-1b+2)(%bx),%ax 3067c478bd9Sstevel@tonic-gate cmpw $0,%ax /* is this our interrupt? */ 3077c478bd9Sstevel@tonic-gate jne 3f 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate /* send EOI -- non specific for now */ 3107c478bd9Sstevel@tonic-gate movw $0x20,%ax /* ICR_EOI_NON_SPECIFIC */ 3117c478bd9Sstevel@tonic-gate movb %cs:(pxenv_undi_irq-1b),%cl 3127c478bd9Sstevel@tonic-gate cmpb $8,%cl 3137c478bd9Sstevel@tonic-gate jg 2f 3147c478bd9Sstevel@tonic-gate outb $0xa0 /* PIC2_ICR */ 3157c478bd9Sstevel@tonic-gate2: outb $0x20 /* PIC1_ICR */ 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* increment trigger count */ 3187c478bd9Sstevel@tonic-gate incw %cs:(EXT_C(_undi_irq_trigger_count)-1b)(%bx) 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* restore other registers */ 3217c478bd9Sstevel@tonic-gate3: popw %cx 3227c478bd9Sstevel@tonic-gate popw %bx 3237c478bd9Sstevel@tonic-gate popw %ax 3247c478bd9Sstevel@tonic-gate iret 3257c478bd9Sstevel@tonic-gateENTRY(_undi_irq_trigger_count) 3267c478bd9Sstevel@tonic-gateundi_irq_trigger_count: 3277c478bd9Sstevel@tonic-gate .word 0 3287c478bd9Sstevel@tonic-gateENTRY(_undi_irq_chain_to) 3297c478bd9Sstevel@tonic-gate .long 0 3307c478bd9Sstevel@tonic-gateENTRY(_undi_irq_chain) 3317c478bd9Sstevel@tonic-gate .byte 0 3327c478bd9Sstevel@tonic-gateENTRY(_pxenv_undi_irq) 3337c478bd9Sstevel@tonic-gatepxenv_undi_irq: 3347c478bd9Sstevel@tonic-gate .byte 0 3357c478bd9Sstevel@tonic-gateENTRY(_pxenv_undi_entrypointsp) 3367c478bd9Sstevel@tonic-gatepxenv_entrypointsp: 3377c478bd9Sstevel@tonic-gate .word 0 /* offset */ 3387c478bd9Sstevel@tonic-gate .word 0 /* segment */ 3397c478bd9Sstevel@tonic-gatepxenv_undi_isr: 3407c478bd9Sstevel@tonic-gate .word 0 /* status */ 3417c478bd9Sstevel@tonic-gate .word 0 /* funcflag */ 3427c478bd9Sstevel@tonic-gate .long 0 /* struct padding not used by ISR */ 3437c478bd9Sstevel@tonic-gate .long 0 3447c478bd9Sstevel@tonic-gate .long 0 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate .code32 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate/* 3497c478bd9Sstevel@tonic-gate * stop_floppy() 3507c478bd9Sstevel@tonic-gate * 3517c478bd9Sstevel@tonic-gate * Stops the floppy drive from spinning, so that other software is 3527c478bd9Sstevel@tonic-gate * jumped to with a known state. 3537c478bd9Sstevel@tonic-gate */ 3547c478bd9Sstevel@tonic-gateENTRY(stop_floppy) 3557c478bd9Sstevel@tonic-gate pusha 3567c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 3577c478bd9Sstevel@tonic-gate .code16 3587c478bd9Sstevel@tonic-gate xorb %dl, %dl 3597c478bd9Sstevel@tonic-gate int $0x13 3607c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 3617c478bd9Sstevel@tonic-gate .code32 3627c478bd9Sstevel@tonic-gate popa 3637c478bd9Sstevel@tonic-gate ret 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate/* 3667c478bd9Sstevel@tonic-gate * grub_reboot() 3677c478bd9Sstevel@tonic-gate * 3687c478bd9Sstevel@tonic-gate * Reboot the system. At the moment, rely on BIOS. 3697c478bd9Sstevel@tonic-gate */ 3707c478bd9Sstevel@tonic-gateENTRY(grub_reboot) 3717c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 3727c478bd9Sstevel@tonic-gate .code16 3737c478bd9Sstevel@tonic-gate /* cold boot */ 3747c478bd9Sstevel@tonic-gate movw $0x0472, %di 3757c478bd9Sstevel@tonic-gate movw %ax, (%di) 3767c478bd9Sstevel@tonic-gate ljmp $0xFFFF, $0x0000 3777c478bd9Sstevel@tonic-gate .code32 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate/* 3807c478bd9Sstevel@tonic-gate * grub_halt(int no_apm) 3817c478bd9Sstevel@tonic-gate * 3827c478bd9Sstevel@tonic-gate * Halt the system, using APM if possible. If NO_APM is true, don't use 3837c478bd9Sstevel@tonic-gate * APM even if it is available. 3847c478bd9Sstevel@tonic-gate */ 3857c478bd9Sstevel@tonic-gateENTRY(grub_halt) 3867c478bd9Sstevel@tonic-gate /* get the argument */ 3877c478bd9Sstevel@tonic-gate movl 4(%esp), %eax 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate /* see if zero */ 3907c478bd9Sstevel@tonic-gate testl %eax, %eax 3917c478bd9Sstevel@tonic-gate jnz EXT_C(stop) 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 3947c478bd9Sstevel@tonic-gate .code16 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate /* detect APM */ 3977c478bd9Sstevel@tonic-gate movw $0x5300, %ax 3987c478bd9Sstevel@tonic-gate xorw %bx, %bx 3997c478bd9Sstevel@tonic-gate int $0x15 4007c478bd9Sstevel@tonic-gate jc EXT_C(hard_stop) 4017c478bd9Sstevel@tonic-gate /* don't check %bx for buggy BIOSes... */ 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate /* disconnect APM first */ 4047c478bd9Sstevel@tonic-gate movw $0x5304, %ax 4057c478bd9Sstevel@tonic-gate xorw %bx, %bx 4067c478bd9Sstevel@tonic-gate int $0x15 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate /* connect APM */ 4097c478bd9Sstevel@tonic-gate movw $0x5301, %ax 4107c478bd9Sstevel@tonic-gate xorw %bx, %bx 4117c478bd9Sstevel@tonic-gate int $0x15 4127c478bd9Sstevel@tonic-gate jc EXT_C(hard_stop) 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate /* set APM protocol level - 1.1 or bust. (this covers APM 1.2 also) */ 4157c478bd9Sstevel@tonic-gate movw $0x530E, %ax 4167c478bd9Sstevel@tonic-gate xorw %bx, %bx 4177c478bd9Sstevel@tonic-gate movw $0x0101, %cx 4187c478bd9Sstevel@tonic-gate int $0x15 4197c478bd9Sstevel@tonic-gate jc EXT_C(hard_stop) 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* set the power state to off */ 4227c478bd9Sstevel@tonic-gate movw $0x5307, %ax 4237c478bd9Sstevel@tonic-gate movw $1, %bx 4247c478bd9Sstevel@tonic-gate movw $3, %cx 4257c478bd9Sstevel@tonic-gate int $0x15 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate /* shouldn't reach here */ 4287c478bd9Sstevel@tonic-gate jmp EXT_C(hard_stop) 4297c478bd9Sstevel@tonic-gate .code32 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate/* 4327c478bd9Sstevel@tonic-gate * track_int13(int drive) 4337c478bd9Sstevel@tonic-gate * 4347c478bd9Sstevel@tonic-gate * Track the int13 handler to probe I/O address space. 4357c478bd9Sstevel@tonic-gate */ 4367c478bd9Sstevel@tonic-gateENTRY(track_int13) 4377c478bd9Sstevel@tonic-gate pushl %ebp 4387c478bd9Sstevel@tonic-gate movl %esp, %ebp 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate pushl %ebx 4417c478bd9Sstevel@tonic-gate pushl %edi 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate /* copy the original int13 handler segment:offset */ 4447c478bd9Sstevel@tonic-gate movl $0x4c, %edi 4457c478bd9Sstevel@tonic-gate movl (%edi), %eax 4467c478bd9Sstevel@tonic-gate movl %eax, track_int13_addr 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate /* replace the int1 handler */ 4497c478bd9Sstevel@tonic-gate movl $0x4, %edi 4507c478bd9Sstevel@tonic-gate pushl (%edi) 4517c478bd9Sstevel@tonic-gate movl $ABS(int1_handler), %eax 4527c478bd9Sstevel@tonic-gate movl %eax, (%edi) 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate /* read the MBR to call int13 successfully */ 4557c478bd9Sstevel@tonic-gate movb 8(%ebp), %dl 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 4587c478bd9Sstevel@tonic-gate .code16 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate movw $SCRATCHSEG, %ax 4617c478bd9Sstevel@tonic-gate movw %ax, %es 4627c478bd9Sstevel@tonic-gate xorw %bx, %bx 4637c478bd9Sstevel@tonic-gate movw $1, %cx 4647c478bd9Sstevel@tonic-gate xorb %dh, %dh 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate /* save FLAGS on the stack to emulate int13 */ 4677c478bd9Sstevel@tonic-gate pushfw 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate /* set the TF flag */ 4707c478bd9Sstevel@tonic-gate /* FIXME: this can be simplified not to use AX */ 4717c478bd9Sstevel@tonic-gate pushfw 4727c478bd9Sstevel@tonic-gate popw %ax 4737c478bd9Sstevel@tonic-gate orw $0x100, %ax 4747c478bd9Sstevel@tonic-gate pushw %ax 4757c478bd9Sstevel@tonic-gate popfw 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate movw $0x0201, %ax 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate .byte 0x9a /* lcall */ 4807c478bd9Sstevel@tonic-gatetrack_int13_addr: 4817c478bd9Sstevel@tonic-gate .word 0 /* offset */ 4827c478bd9Sstevel@tonic-gate .word 0 /* segment */ 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate /* TF is cleared here automatically */ 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 4877c478bd9Sstevel@tonic-gate .code32 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate /* restore the int1 handler */ 4907c478bd9Sstevel@tonic-gate movl $0x4, %edi 4917c478bd9Sstevel@tonic-gate popl (%edi) 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate popl %edi 4947c478bd9Sstevel@tonic-gate popl %ebx 4957c478bd9Sstevel@tonic-gate popl %ebp 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate ret 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate/* 5017c478bd9Sstevel@tonic-gate * Check if the next instruction is I/O, and if this is true, add the 5027c478bd9Sstevel@tonic-gate * port into the io map. 5037c478bd9Sstevel@tonic-gate * 5047c478bd9Sstevel@tonic-gate * Note: Probably this will make the execution of int13 very slow. 5057c478bd9Sstevel@tonic-gate * 5067c478bd9Sstevel@tonic-gate * Note2: In this implementation, all we can know is I/O-mapped I/O. It 5077c478bd9Sstevel@tonic-gate * is impossible to detect memory-mapped I/O. 5087c478bd9Sstevel@tonic-gate */ 5097c478bd9Sstevel@tonic-gateint1_handler: 5107c478bd9Sstevel@tonic-gate .code16 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate pushw %bp 5137c478bd9Sstevel@tonic-gate movw %sp, %bp 5147c478bd9Sstevel@tonic-gate pushw %ds 5157c478bd9Sstevel@tonic-gate pushw %ax 5167c478bd9Sstevel@tonic-gate pushw %si 5177c478bd9Sstevel@tonic-gate pushw %dx 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate /* IP */ 5207c478bd9Sstevel@tonic-gate movw 2(%bp), %si 5217c478bd9Sstevel@tonic-gate /* CS */ 5227c478bd9Sstevel@tonic-gate movw 4(%bp), %ax 5237c478bd9Sstevel@tonic-gate movw %ax, %ds 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate /* examine the next instruction */ 5267c478bd9Sstevel@tonic-gate1: lodsb (%si), %al 5277c478bd9Sstevel@tonic-gate /* skip this code if it is a prefix */ 5287c478bd9Sstevel@tonic-gate cmpb $0x2E, %al 5297c478bd9Sstevel@tonic-gate je 1b 5307c478bd9Sstevel@tonic-gate cmpb $0x36, %al 5317c478bd9Sstevel@tonic-gate je 1b 5327c478bd9Sstevel@tonic-gate cmpb $0x3E, %al 5337c478bd9Sstevel@tonic-gate je 1b 5347c478bd9Sstevel@tonic-gate cmpb $0x26, %al 5357c478bd9Sstevel@tonic-gate je 1b 5367c478bd9Sstevel@tonic-gate cmpb $0x64, %al 5377c478bd9Sstevel@tonic-gate jl 2f 5387c478bd9Sstevel@tonic-gate cmpb $0x67, %al 5397c478bd9Sstevel@tonic-gate jle 1b 5407c478bd9Sstevel@tonic-gate2: cmpb $0xF0, %al 5417c478bd9Sstevel@tonic-gate jl 3f 5427c478bd9Sstevel@tonic-gate cmpb $0xF3, %al 5437c478bd9Sstevel@tonic-gate jle 1b 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate3: /* check if this code is out* or in* */ 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate /* ins? or outs? */ 5487c478bd9Sstevel@tonic-gate cmpb $0x6C, %al 5497c478bd9Sstevel@tonic-gate jl 4f 5507c478bd9Sstevel@tonic-gate cmpb $0x6F, %al 5517c478bd9Sstevel@tonic-gate jle 5f 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate4: /* in? or out? (register operand version) */ 5547c478bd9Sstevel@tonic-gate cmpb $0xEC, %al 5557c478bd9Sstevel@tonic-gate jl 6f 5567c478bd9Sstevel@tonic-gate cmpb $0xEF, %al 5577c478bd9Sstevel@tonic-gate jle 5f 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate6: /* in? or out? (immediate operand version) */ 5607c478bd9Sstevel@tonic-gate cmpb $0xE4, %al 5617c478bd9Sstevel@tonic-gate jl 8f 5627c478bd9Sstevel@tonic-gate cmpb $0xE7, %al 5637c478bd9Sstevel@tonic-gate jg 8f 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate7: /* immediate has a port */ 5667c478bd9Sstevel@tonic-gate lodsb (%si), %al 5677c478bd9Sstevel@tonic-gate movzbw %al, %dx 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate5: /* %dx has a port */ 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate /* set %ds to zero */ 5727c478bd9Sstevel@tonic-gate xorw %ax, %ax 5737c478bd9Sstevel@tonic-gate movw %ax, %ds 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate /* set %si to the io map */ 5767c478bd9Sstevel@tonic-gate movw $ABS(EXT_C(io_map)), %si 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate9: /* check if the io map already has the port */ 5807c478bd9Sstevel@tonic-gate lodsw (%si), %ax 5817c478bd9Sstevel@tonic-gate /* check if this is the end */ 5827c478bd9Sstevel@tonic-gate testw %ax, %ax 5837c478bd9Sstevel@tonic-gate jz 1f 5847c478bd9Sstevel@tonic-gate /* check if this matches the port */ 5857c478bd9Sstevel@tonic-gate cmpw %ax, %dx 5867c478bd9Sstevel@tonic-gate jne 9b 5877c478bd9Sstevel@tonic-gate /* if so, leave from this handler */ 5887c478bd9Sstevel@tonic-gate jmp 8f 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate1: /* check for the buffer overrun */ 5917c478bd9Sstevel@tonic-gate cmpw $(ABS(EXT_C(io_map)) + (IO_MAP_SIZE + 1) * 2), %si 5927c478bd9Sstevel@tonic-gate je 8f 5937c478bd9Sstevel@tonic-gate /* add the port into the io map */ 5947c478bd9Sstevel@tonic-gate movw %dx, -2(%si) 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate8: /* restore registers */ 5977c478bd9Sstevel@tonic-gate popw %dx 5987c478bd9Sstevel@tonic-gate popw %si 5997c478bd9Sstevel@tonic-gate popw %ax 6007c478bd9Sstevel@tonic-gate popw %ds 6017c478bd9Sstevel@tonic-gate popw %bp 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate iret 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate .code32 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gateENTRY(io_map) 6087c478bd9Sstevel@tonic-gate .space (IO_MAP_SIZE + 1) * 2 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate/* 6127c478bd9Sstevel@tonic-gate * set_int15_handler(void) 6137c478bd9Sstevel@tonic-gate * 6147c478bd9Sstevel@tonic-gate * Set up int15_handler. 6157c478bd9Sstevel@tonic-gate */ 6167c478bd9Sstevel@tonic-gateENTRY(set_int15_handler) 6177c478bd9Sstevel@tonic-gate pushl %edi 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate /* save the original int15 handler */ 6207c478bd9Sstevel@tonic-gate movl $0x54, %edi 6217c478bd9Sstevel@tonic-gate movw (%edi), %ax 6227c478bd9Sstevel@tonic-gate movw %ax, ABS(int15_offset) 6237c478bd9Sstevel@tonic-gate movw 2(%edi), %ax 6247c478bd9Sstevel@tonic-gate movw %ax, ABS(int15_segment) 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate /* save the new int15 handler */ 6277c478bd9Sstevel@tonic-gate movw $ABS(int15_handler), %ax 6287c478bd9Sstevel@tonic-gate movw %ax, (%edi) 6297c478bd9Sstevel@tonic-gate xorw %ax, %ax 6307c478bd9Sstevel@tonic-gate movw %ax, 2(%edi) 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate popl %edi 6337c478bd9Sstevel@tonic-gate ret 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate/* 6377c478bd9Sstevel@tonic-gate * unset_int15_handler(void) 6387c478bd9Sstevel@tonic-gate * 6397c478bd9Sstevel@tonic-gate * Restore the original int15 handler 6407c478bd9Sstevel@tonic-gate */ 6417c478bd9Sstevel@tonic-gateENTRY(unset_int15_handler) 6427c478bd9Sstevel@tonic-gate pushl %edi 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate /* check if int15_handler is set */ 6457c478bd9Sstevel@tonic-gate movl $0x54, %edi 6467c478bd9Sstevel@tonic-gate movw $ABS(int15_handler), %ax 6477c478bd9Sstevel@tonic-gate cmpw %ax, (%edi) 6487c478bd9Sstevel@tonic-gate jne 1f 6497c478bd9Sstevel@tonic-gate xorw %ax, %ax 6507c478bd9Sstevel@tonic-gate cmpw %ax, 2(%edi) 6517c478bd9Sstevel@tonic-gate jne 1f 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate /* restore the original */ 6547c478bd9Sstevel@tonic-gate movw ABS(int15_offset), %ax 6557c478bd9Sstevel@tonic-gate movw %ax, (%edi) 6567c478bd9Sstevel@tonic-gate movw ABS(int15_segment), %ax 6577c478bd9Sstevel@tonic-gate movw %ax, 2(%edi) 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate1: 6607c478bd9Sstevel@tonic-gate popl %edi 6617c478bd9Sstevel@tonic-gate ret 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate/* 6657c478bd9Sstevel@tonic-gate * Translate a key code to another. 6667c478bd9Sstevel@tonic-gate * 6677c478bd9Sstevel@tonic-gate * Note: This implementation cannot handle more than one length 6687c478bd9Sstevel@tonic-gate * scancodes (such as Right Ctrl). 6697c478bd9Sstevel@tonic-gate */ 6707c478bd9Sstevel@tonic-gate .code16 6717c478bd9Sstevel@tonic-gateint15_handler: 6727c478bd9Sstevel@tonic-gate /* if non-carrier, ignore it */ 6737c478bd9Sstevel@tonic-gate jnc 1f 6747c478bd9Sstevel@tonic-gate /* check if AH=4F */ 6757c478bd9Sstevel@tonic-gate cmpb $0x4F, %ah 6767c478bd9Sstevel@tonic-gate jne 1f 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate /* E0 and E1 are special */ 6797c478bd9Sstevel@tonic-gate cmpb $0xE1, %al 6807c478bd9Sstevel@tonic-gate je 4f 6817c478bd9Sstevel@tonic-gate cmpb $0xE0, %al 6827c478bd9Sstevel@tonic-gate /* this flag is actually the machine code (je or jmp) */ 6837c478bd9Sstevel@tonic-gateint15_skip_flag: 6847c478bd9Sstevel@tonic-gate je 4f 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate pushw %bp 6877c478bd9Sstevel@tonic-gate movw %sp, %bp 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate pushw %bx 6907c478bd9Sstevel@tonic-gate pushw %dx 6917c478bd9Sstevel@tonic-gate pushw %ds 6927c478bd9Sstevel@tonic-gate pushw %si 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate /* save bits 0-6 of %al in %dl */ 6957c478bd9Sstevel@tonic-gate movw %ax, %dx 6967c478bd9Sstevel@tonic-gate andb $0x7f, %dl 6977c478bd9Sstevel@tonic-gate /* save the highest bit in %bl */ 6987c478bd9Sstevel@tonic-gate movb %al, %bl 6997c478bd9Sstevel@tonic-gate xorb %dl, %bl 7007c478bd9Sstevel@tonic-gate /* set %ds to 0 */ 7017c478bd9Sstevel@tonic-gate xorw %ax, %ax 7027c478bd9Sstevel@tonic-gate movw %ax, %ds 7037c478bd9Sstevel@tonic-gate /* set %si to the key map */ 7047c478bd9Sstevel@tonic-gate movw $ABS(EXT_C(bios_key_map)), %si 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate /* find the key code from the key map */ 7077c478bd9Sstevel@tonic-gate2: 7087c478bd9Sstevel@tonic-gate lodsw 7097c478bd9Sstevel@tonic-gate /* check if this is the end */ 7107c478bd9Sstevel@tonic-gate testw %ax, %ax 7117c478bd9Sstevel@tonic-gate jz 3f 7127c478bd9Sstevel@tonic-gate /* check if this matches the key code */ 7137c478bd9Sstevel@tonic-gate cmpb %al, %dl 7147c478bd9Sstevel@tonic-gate jne 2b 7157c478bd9Sstevel@tonic-gate /* if so, perform the mapping */ 7167c478bd9Sstevel@tonic-gate movb %ah, %dl 7177c478bd9Sstevel@tonic-gate3: 7187c478bd9Sstevel@tonic-gate /* restore %ax */ 7197c478bd9Sstevel@tonic-gate movw %dx, %ax 7207c478bd9Sstevel@tonic-gate orb %bl, %al 7217c478bd9Sstevel@tonic-gate /* make sure that CF is set */ 7227c478bd9Sstevel@tonic-gate orw $1, 6(%bp) 7237c478bd9Sstevel@tonic-gate /* restore other registers */ 7247c478bd9Sstevel@tonic-gate popw %si 7257c478bd9Sstevel@tonic-gate popw %ds 7267c478bd9Sstevel@tonic-gate popw %dx 7277c478bd9Sstevel@tonic-gate popw %bx 7287c478bd9Sstevel@tonic-gate popw %bp 7297c478bd9Sstevel@tonic-gate iret 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate4: 7327c478bd9Sstevel@tonic-gate /* tricky: jmp (0x74) <-> je (0xeb) */ 7337c478bd9Sstevel@tonic-gate xorb $(0x74 ^ 0xeb), ABS(int15_skip_flag) 7347c478bd9Sstevel@tonic-gate1: 7357c478bd9Sstevel@tonic-gate /* just cascade to the original */ 7367c478bd9Sstevel@tonic-gate /* ljmp */ 7377c478bd9Sstevel@tonic-gate .byte 0xea 7387c478bd9Sstevel@tonic-gateint15_offset: .word 0 7397c478bd9Sstevel@tonic-gateint15_segment: .word 0 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate .code32 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate .align 4 7447c478bd9Sstevel@tonic-gateENTRY(bios_key_map) 7457c478bd9Sstevel@tonic-gate .space (KEY_MAP_SIZE + 1) * 2 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate/* 7497c478bd9Sstevel@tonic-gate * set_int13_handler(map) 7507c478bd9Sstevel@tonic-gate * 7517c478bd9Sstevel@tonic-gate * Copy MAP to the drive map and set up int13_handler. 7527c478bd9Sstevel@tonic-gate */ 7537c478bd9Sstevel@tonic-gateENTRY(set_int13_handler) 7547c478bd9Sstevel@tonic-gate pushl %ebp 7557c478bd9Sstevel@tonic-gate movl %esp, %ebp 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate pushl %edi 7587c478bd9Sstevel@tonic-gate pushl %esi 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate /* copy MAP to the drive map */ 7617c478bd9Sstevel@tonic-gate movl $(DRIVE_MAP_SIZE * 2), %ecx 7627c478bd9Sstevel@tonic-gate movl $ABS(drive_map), %edi 7637c478bd9Sstevel@tonic-gate movl 8(%ebp), %esi 7647c478bd9Sstevel@tonic-gate cld 7657c478bd9Sstevel@tonic-gate rep 7667c478bd9Sstevel@tonic-gate movsb 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate /* save the original int13 handler */ 7697c478bd9Sstevel@tonic-gate movl $0x4c, %edi 7707c478bd9Sstevel@tonic-gate movw (%edi), %ax 7717c478bd9Sstevel@tonic-gate movw %ax, ABS(int13_offset) 7727c478bd9Sstevel@tonic-gate movw 2(%edi), %ax 7737c478bd9Sstevel@tonic-gate movw %ax, ABS(int13_segment) 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate /* decrease the lower memory size and set it to the BIOS memory */ 7767c478bd9Sstevel@tonic-gate movl $0x413, %edi 7777c478bd9Sstevel@tonic-gate decw (%edi) 7787c478bd9Sstevel@tonic-gate xorl %eax, %eax 7797c478bd9Sstevel@tonic-gate movw (%edi), %ax 7807c478bd9Sstevel@tonic-gate 7817c478bd9Sstevel@tonic-gate /* compute the segment */ 7827c478bd9Sstevel@tonic-gate shll $6, %eax 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate /* save the new int13 handler */ 7857c478bd9Sstevel@tonic-gate movl $0x4c, %edi 7867c478bd9Sstevel@tonic-gate movw %ax, 2(%edi) 7877c478bd9Sstevel@tonic-gate xorw %cx, %cx 7887c478bd9Sstevel@tonic-gate movw %cx, (%edi) 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate /* copy int13_handler to the reserved area */ 7917c478bd9Sstevel@tonic-gate shll $4, %eax 7927c478bd9Sstevel@tonic-gate movl %eax, %edi 7937c478bd9Sstevel@tonic-gate movl $ABS(int13_handler), %esi 7947c478bd9Sstevel@tonic-gate movl $(int13_handler_end - int13_handler), %ecx 7957c478bd9Sstevel@tonic-gate rep 7967c478bd9Sstevel@tonic-gate movsb 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate popl %esi 7997c478bd9Sstevel@tonic-gate popl %edi 8007c478bd9Sstevel@tonic-gate popl %ebp 8017c478bd9Sstevel@tonic-gate ret 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate/* 8057c478bd9Sstevel@tonic-gate * Map a drive to another drive. 8067c478bd9Sstevel@tonic-gate */ 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate .code16 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gateint13_handler: 8117c478bd9Sstevel@tonic-gate pushw %ax 8127c478bd9Sstevel@tonic-gate pushw %bp 8137c478bd9Sstevel@tonic-gate movw %sp, %bp 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate pushw %si 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate /* set %si to the drive map */ 8187c478bd9Sstevel@tonic-gate movw $(drive_map - int13_handler), %si 8197c478bd9Sstevel@tonic-gate /* find the drive number from the drive map */ 8207c478bd9Sstevel@tonic-gate cld 8217c478bd9Sstevel@tonic-gate1: 8227c478bd9Sstevel@tonic-gate lodsw %cs:(%si), %ax 8237c478bd9Sstevel@tonic-gate /* check if this is the end */ 8247c478bd9Sstevel@tonic-gate testw %ax, %ax 8257c478bd9Sstevel@tonic-gate jz 2f 8267c478bd9Sstevel@tonic-gate /* check if this matches the drive number */ 8277c478bd9Sstevel@tonic-gate cmpb %al, %dl 8287c478bd9Sstevel@tonic-gate jne 1b 8297c478bd9Sstevel@tonic-gate /* if so, perform the mapping */ 8307c478bd9Sstevel@tonic-gate movb %ah, %dl 8317c478bd9Sstevel@tonic-gate2: 8327c478bd9Sstevel@tonic-gate /* restore %si */ 8337c478bd9Sstevel@tonic-gate popw %si 8347c478bd9Sstevel@tonic-gate /* save %ax in the stack */ 8357c478bd9Sstevel@tonic-gate pushw %ax 8367c478bd9Sstevel@tonic-gate /* simulate the interrupt call */ 8377c478bd9Sstevel@tonic-gate pushw 8(%bp) 8387c478bd9Sstevel@tonic-gate /* set %ax and %bp to the original values */ 8397c478bd9Sstevel@tonic-gate movw 2(%bp), %ax 8407c478bd9Sstevel@tonic-gate movw (%bp), %bp 8417c478bd9Sstevel@tonic-gate /* lcall */ 8427c478bd9Sstevel@tonic-gate .byte 0x9a 8437c478bd9Sstevel@tonic-gateint13_offset: .word 0 8447c478bd9Sstevel@tonic-gateint13_segment: .word 0 8457c478bd9Sstevel@tonic-gate /* save flags */ 8467c478bd9Sstevel@tonic-gate pushf 8477c478bd9Sstevel@tonic-gate /* restore %bp */ 8487c478bd9Sstevel@tonic-gate movw %sp, %bp 8497c478bd9Sstevel@tonic-gate /* save %ax */ 8507c478bd9Sstevel@tonic-gate pushw %ax 8517c478bd9Sstevel@tonic-gate /* set the flags in the stack to the value returned by int13 */ 8527c478bd9Sstevel@tonic-gate movw (%bp), %ax 8537c478bd9Sstevel@tonic-gate movw %ax, 0xc(%bp) 8547c478bd9Sstevel@tonic-gate /* check if should map the drive number */ 8557c478bd9Sstevel@tonic-gate movw 6(%bp), %ax 8567c478bd9Sstevel@tonic-gate cmpw $0x8, %ax 8577c478bd9Sstevel@tonic-gate jne 3f 8587c478bd9Sstevel@tonic-gate cmpw $0x15, %ax 8597c478bd9Sstevel@tonic-gate jne 3f 8607c478bd9Sstevel@tonic-gate /* check if the mapping was performed */ 8617c478bd9Sstevel@tonic-gate movw 2(%bp), %ax 8627c478bd9Sstevel@tonic-gate testw %ax, %ax 8637c478bd9Sstevel@tonic-gate jz 3f 8647c478bd9Sstevel@tonic-gate /* perform the mapping */ 8657c478bd9Sstevel@tonic-gate movb %al, %dl 8667c478bd9Sstevel@tonic-gate3: 8677c478bd9Sstevel@tonic-gate popw %ax 8687c478bd9Sstevel@tonic-gate movw 4(%bp), %bp 8697c478bd9Sstevel@tonic-gate addw $8, %sp 8707c478bd9Sstevel@tonic-gate iret 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate .align 4 8737c478bd9Sstevel@tonic-gatedrive_map: .space (DRIVE_MAP_SIZE + 1) * 2 8747c478bd9Sstevel@tonic-gateint13_handler_end: 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate .code32 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate/* 8807c478bd9Sstevel@tonic-gate * chain_stage1(segment, offset, part_table_addr) 8817c478bd9Sstevel@tonic-gate * 8827c478bd9Sstevel@tonic-gate * This starts another stage1 loader, at segment:offset. 8837c478bd9Sstevel@tonic-gate */ 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gateENTRY(chain_stage1) 8867c478bd9Sstevel@tonic-gate /* no need to save anything, just use %esp */ 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate /* store %ESI, presuming %ES is 0 */ 8897c478bd9Sstevel@tonic-gate movl 0xc(%esp), %esi 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate /* store new offset */ 8927c478bd9Sstevel@tonic-gate movl 0x8(%esp), %eax 8937c478bd9Sstevel@tonic-gate movl %eax, offset 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate /* store new segment */ 8967c478bd9Sstevel@tonic-gate movw 0x4(%esp), %ax 8977c478bd9Sstevel@tonic-gate movw %ax, segment 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate /* set up to pass boot drive */ 9007c478bd9Sstevel@tonic-gate movb EXT_C(boot_drive), %dl 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 9037c478bd9Sstevel@tonic-gate .code16 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate#ifdef ABSOLUTE_WITHOUT_ASTERISK 9067c478bd9Sstevel@tonic-gate DATA32 ADDR32 ljmp (offset) 9077c478bd9Sstevel@tonic-gate#else 9087c478bd9Sstevel@tonic-gate DATA32 ADDR32 ljmp *(offset) 9097c478bd9Sstevel@tonic-gate#endif 9107c478bd9Sstevel@tonic-gate .code32 9117c478bd9Sstevel@tonic-gate#endif /* STAGE1_5 */ 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate#ifdef STAGE1_5 9157c478bd9Sstevel@tonic-gate/* 9167c478bd9Sstevel@tonic-gate * chain_stage2(segment, offset, second_sector) 9177c478bd9Sstevel@tonic-gate * 9187c478bd9Sstevel@tonic-gate * This starts another stage2 loader, at segment:offset. It presumes 9197c478bd9Sstevel@tonic-gate * that the other one starts with this same "asm.S" file, and passes 9207c478bd9Sstevel@tonic-gate * parameters by writing the embedded install variables. 9217c478bd9Sstevel@tonic-gate */ 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gateENTRY(chain_stage2) 9247c478bd9Sstevel@tonic-gate /* no need to save anything, just use %esp */ 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate /* store new offset */ 9277c478bd9Sstevel@tonic-gate movl 0x8(%esp), %eax 9287c478bd9Sstevel@tonic-gate movl %eax, offset 9297c478bd9Sstevel@tonic-gate movl %eax, %ebx 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate /* store new segment */ 9327c478bd9Sstevel@tonic-gate movw 0x4(%esp), %ax 9337c478bd9Sstevel@tonic-gate movw %ax, segment 9347c478bd9Sstevel@tonic-gate shll $4, %eax 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate /* generate linear address */ 9377c478bd9Sstevel@tonic-gate addl %eax, %ebx 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate /* set up to pass the partition where stage2 is located in */ 9407c478bd9Sstevel@tonic-gate movl EXT_C(current_partition), %eax 9417c478bd9Sstevel@tonic-gate movl %eax, (EXT_C(install_partition)-EXT_C(main))(%ebx) 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate /* set up to pass the drive where stage2 is located in */ 9447c478bd9Sstevel@tonic-gate movb EXT_C(current_drive), %dl 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate /* set up to pass the second sector of stage2 */ 9477c478bd9Sstevel@tonic-gate movl 0xc(%esp), %ecx 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 9507c478bd9Sstevel@tonic-gate .code16 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate movl %ecx, %ebp 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate#ifdef ABSOLUTE_WITHOUT_ASTERISK 9557c478bd9Sstevel@tonic-gate DATA32 ADDR32 ljmp (offset) 9567c478bd9Sstevel@tonic-gate#else 9577c478bd9Sstevel@tonic-gate DATA32 ADDR32 ljmp *(offset) 9587c478bd9Sstevel@tonic-gate#endif 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate .code32 9617c478bd9Sstevel@tonic-gate#endif /* STAGE1_5 */ 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate/* 9647c478bd9Sstevel@tonic-gate * These next two routines, "real_to_prot" and "prot_to_real" are structured 9657c478bd9Sstevel@tonic-gate * in a very specific way. Be very careful when changing them. 9667c478bd9Sstevel@tonic-gate * 9677c478bd9Sstevel@tonic-gate * NOTE: Use of either one messes up %eax and %ebp. 9687c478bd9Sstevel@tonic-gate */ 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gateENTRY(real_to_prot) 9717c478bd9Sstevel@tonic-gate .code16 9727c478bd9Sstevel@tonic-gate cli 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate /* load the GDT register */ 9757c478bd9Sstevel@tonic-gate DATA32 ADDR32 lgdt gdtdesc 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate /* turn on protected mode */ 9787c478bd9Sstevel@tonic-gate movl %cr0, %eax 9797c478bd9Sstevel@tonic-gate orl $CR0_PE_ON, %eax 9807c478bd9Sstevel@tonic-gate movl %eax, %cr0 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate /* jump to relocation, flush prefetch queue, and reload %cs */ 9837c478bd9Sstevel@tonic-gate DATA32 ljmp $PROT_MODE_CSEG, $protcseg 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate /* 9867c478bd9Sstevel@tonic-gate * The ".code32" directive only works in GAS, the GNU assembler! 9877c478bd9Sstevel@tonic-gate * This gets out of "16-bit" mode. 9887c478bd9Sstevel@tonic-gate */ 9897c478bd9Sstevel@tonic-gate .code32 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gateprotcseg: 9927c478bd9Sstevel@tonic-gate /* reload other segment registers */ 9937c478bd9Sstevel@tonic-gate movw $PROT_MODE_DSEG, %ax 9947c478bd9Sstevel@tonic-gate movw %ax, %ds 9957c478bd9Sstevel@tonic-gate movw %ax, %es 9967c478bd9Sstevel@tonic-gate movw %ax, %fs 9977c478bd9Sstevel@tonic-gate movw %ax, %gs 9987c478bd9Sstevel@tonic-gate movw %ax, %ss 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate /* put the return address in a known safe location */ 10017c478bd9Sstevel@tonic-gate movl (%esp), %eax 10027c478bd9Sstevel@tonic-gate movl %eax, STACKOFF 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate /* get protected mode stack */ 10057c478bd9Sstevel@tonic-gate movl protstack, %eax 10067c478bd9Sstevel@tonic-gate movl %eax, %esp 10077c478bd9Sstevel@tonic-gate movl %eax, %ebp 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate /* get return address onto the right stack */ 10107c478bd9Sstevel@tonic-gate movl STACKOFF, %eax 10117c478bd9Sstevel@tonic-gate movl %eax, (%esp) 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate /* zero %eax */ 10147c478bd9Sstevel@tonic-gate xorl %eax, %eax 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate /* return on the old (or initialized) stack! */ 10177c478bd9Sstevel@tonic-gate ret 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gateENTRY(prot_to_real) 10217c478bd9Sstevel@tonic-gate /* just in case, set GDT */ 10227c478bd9Sstevel@tonic-gate lgdt gdtdesc 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate /* save the protected mode stack */ 10257c478bd9Sstevel@tonic-gate movl %esp, %eax 10267c478bd9Sstevel@tonic-gate movl %eax, protstack 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate /* get the return address */ 10297c478bd9Sstevel@tonic-gate movl (%esp), %eax 10307c478bd9Sstevel@tonic-gate movl %eax, STACKOFF 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate /* set up new stack */ 10337c478bd9Sstevel@tonic-gate movl $STACKOFF, %eax 10347c478bd9Sstevel@tonic-gate movl %eax, %esp 10357c478bd9Sstevel@tonic-gate movl %eax, %ebp 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate /* set up segment limits */ 10387c478bd9Sstevel@tonic-gate movw $PSEUDO_RM_DSEG, %ax 10397c478bd9Sstevel@tonic-gate movw %ax, %ds 10407c478bd9Sstevel@tonic-gate movw %ax, %es 10417c478bd9Sstevel@tonic-gate movw %ax, %fs 10427c478bd9Sstevel@tonic-gate movw %ax, %gs 10437c478bd9Sstevel@tonic-gate movw %ax, %ss 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate /* this might be an extra step */ 10467c478bd9Sstevel@tonic-gate ljmp $PSEUDO_RM_CSEG, $tmpcseg /* jump to a 16 bit segment */ 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gatetmpcseg: 10497c478bd9Sstevel@tonic-gate .code16 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate /* clear the PE bit of CR0 */ 10527c478bd9Sstevel@tonic-gate movl %cr0, %eax 10537c478bd9Sstevel@tonic-gate andl $CR0_PE_OFF, %eax 10547c478bd9Sstevel@tonic-gate movl %eax, %cr0 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate /* flush prefetch queue, reload %cs */ 10577c478bd9Sstevel@tonic-gate DATA32 ljmp $0, $realcseg 10587c478bd9Sstevel@tonic-gate 10597c478bd9Sstevel@tonic-gaterealcseg: 10607c478bd9Sstevel@tonic-gate /* we are in real mode now 10617c478bd9Sstevel@tonic-gate * set up the real mode segment registers : DS, SS, ES 10627c478bd9Sstevel@tonic-gate */ 10637c478bd9Sstevel@tonic-gate /* zero %eax */ 10647c478bd9Sstevel@tonic-gate xorl %eax, %eax 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate movw %ax, %ds 10677c478bd9Sstevel@tonic-gate movw %ax, %es 10687c478bd9Sstevel@tonic-gate movw %ax, %fs 10697c478bd9Sstevel@tonic-gate movw %ax, %gs 10707c478bd9Sstevel@tonic-gate movw %ax, %ss 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate /* restore interrupts */ 10737c478bd9Sstevel@tonic-gate sti 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate /* return on new stack! */ 10767c478bd9Sstevel@tonic-gate DATA32 ret 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate .code32 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate/* 10827c478bd9Sstevel@tonic-gate * int biosdisk_int13_extensions (int ax, int drive, void *dap) 10837c478bd9Sstevel@tonic-gate * 10847c478bd9Sstevel@tonic-gate * Call IBM/MS INT13 Extensions (int 13 %ax=AX) for DRIVE. DAP 10857c478bd9Sstevel@tonic-gate * is passed for disk address packet. If an error occurs, return 10867c478bd9Sstevel@tonic-gate * non-zero, otherwise zero. 10877c478bd9Sstevel@tonic-gate */ 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gateENTRY(biosdisk_int13_extensions) 10907c478bd9Sstevel@tonic-gate pushl %ebp 10917c478bd9Sstevel@tonic-gate movl %esp, %ebp 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate pushl %esi 10947c478bd9Sstevel@tonic-gate pushl %ebx 10957c478bd9Sstevel@tonic-gate 10967c478bd9Sstevel@tonic-gate /* compute the address of disk_address_packet */ 10977c478bd9Sstevel@tonic-gate movl 0x10(%ebp), %eax 10987c478bd9Sstevel@tonic-gate movw %ax, %si 10997c478bd9Sstevel@tonic-gate xorw %ax, %ax 11007c478bd9Sstevel@tonic-gate shrl $4, %eax 11017c478bd9Sstevel@tonic-gate movw %ax, %cx /* save the segment to cx */ 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate /* drive */ 11047c478bd9Sstevel@tonic-gate movb 0xc(%ebp), %dl 11057c478bd9Sstevel@tonic-gate /* ax */ 11067c478bd9Sstevel@tonic-gate movw 0x8(%ebp), %bx 11077c478bd9Sstevel@tonic-gate /* enter real mode */ 11087c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate .code16 11117c478bd9Sstevel@tonic-gate movw %bx, %ax 11127c478bd9Sstevel@tonic-gate movw %cx, %ds 11137c478bd9Sstevel@tonic-gate int $0x13 /* do the operation */ 11147c478bd9Sstevel@tonic-gate movb %ah, %dl /* save return value */ 11157c478bd9Sstevel@tonic-gate /* clear the data segment */ 11167c478bd9Sstevel@tonic-gate xorw %ax, %ax 11177c478bd9Sstevel@tonic-gate movw %ax, %ds 11187c478bd9Sstevel@tonic-gate /* back to protected mode */ 11197c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 11207c478bd9Sstevel@tonic-gate .code32 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate movb %dl, %al /* return value in %eax */ 11237c478bd9Sstevel@tonic-gate 11247c478bd9Sstevel@tonic-gate popl %ebx 11257c478bd9Sstevel@tonic-gate popl %esi 11267c478bd9Sstevel@tonic-gate popl %ebp 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate ret 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate/* 11317c478bd9Sstevel@tonic-gate * int biosdisk_standard (int ah, int drive, int coff, int hoff, int soff, 11327c478bd9Sstevel@tonic-gate * int nsec, int segment) 11337c478bd9Sstevel@tonic-gate * 11347c478bd9Sstevel@tonic-gate * Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write 11357c478bd9Sstevel@tonic-gate * NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs, 11367c478bd9Sstevel@tonic-gate * return non-zero, otherwise zero. 11377c478bd9Sstevel@tonic-gate */ 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gateENTRY(biosdisk_standard) 11407c478bd9Sstevel@tonic-gate pushl %ebp 11417c478bd9Sstevel@tonic-gate movl %esp, %ebp 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate pushl %ebx 11447c478bd9Sstevel@tonic-gate pushl %edi 11457c478bd9Sstevel@tonic-gate pushl %esi 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate /* set up CHS information */ 11487c478bd9Sstevel@tonic-gate movl 0x10(%ebp), %eax 11497c478bd9Sstevel@tonic-gate movb %al, %ch 11507c478bd9Sstevel@tonic-gate movb 0x18(%ebp), %al 11517c478bd9Sstevel@tonic-gate shlb $2, %al 11527c478bd9Sstevel@tonic-gate shrw $2, %ax 11537c478bd9Sstevel@tonic-gate movb %al, %cl 11547c478bd9Sstevel@tonic-gate movb 0x14(%ebp), %dh 11557c478bd9Sstevel@tonic-gate /* drive */ 11567c478bd9Sstevel@tonic-gate movb 0xc(%ebp), %dl 11577c478bd9Sstevel@tonic-gate /* segment */ 11587c478bd9Sstevel@tonic-gate movw 0x20(%ebp), %bx 11597c478bd9Sstevel@tonic-gate /* save nsec and ah to %di */ 11607c478bd9Sstevel@tonic-gate movb 0x8(%ebp), %ah 11617c478bd9Sstevel@tonic-gate movb 0x1c(%ebp), %al 11627c478bd9Sstevel@tonic-gate movw %ax, %di 11637c478bd9Sstevel@tonic-gate /* enter real mode */ 11647c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate .code16 11677c478bd9Sstevel@tonic-gate movw %bx, %es 11687c478bd9Sstevel@tonic-gate xorw %bx, %bx 11697c478bd9Sstevel@tonic-gate movw $3, %si /* attempt at least three times */ 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate1: 11727c478bd9Sstevel@tonic-gate movw %di, %ax 11737c478bd9Sstevel@tonic-gate int $0x13 /* do the operation */ 11747c478bd9Sstevel@tonic-gate jnc 2f /* check if successful */ 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate movb %ah, %bl /* save return value */ 11777c478bd9Sstevel@tonic-gate /* if fail, reset the disk system */ 11787c478bd9Sstevel@tonic-gate xorw %ax, %ax 11797c478bd9Sstevel@tonic-gate int $0x13 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate decw %si 11827c478bd9Sstevel@tonic-gate cmpw $0, %si 11837c478bd9Sstevel@tonic-gate je 2f 11847c478bd9Sstevel@tonic-gate xorb %bl, %bl 11857c478bd9Sstevel@tonic-gate jmp 1b /* retry */ 11867c478bd9Sstevel@tonic-gate2: 11877c478bd9Sstevel@tonic-gate /* back to protected mode */ 11887c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 11897c478bd9Sstevel@tonic-gate .code32 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate movb %bl, %al /* return value in %eax */ 11927c478bd9Sstevel@tonic-gate 11937c478bd9Sstevel@tonic-gate popl %esi 11947c478bd9Sstevel@tonic-gate popl %edi 11957c478bd9Sstevel@tonic-gate popl %ebx 11967c478bd9Sstevel@tonic-gate popl %ebp 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate ret 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate/* 12027c478bd9Sstevel@tonic-gate * int check_int13_extensions (int drive) 12037c478bd9Sstevel@tonic-gate * 12047c478bd9Sstevel@tonic-gate * Check if LBA is supported for DRIVE. If it is supported, then return 12057c478bd9Sstevel@tonic-gate * the major version of extensions, otherwise zero. 12067c478bd9Sstevel@tonic-gate */ 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gateENTRY(check_int13_extensions) 12097c478bd9Sstevel@tonic-gate pushl %ebp 12107c478bd9Sstevel@tonic-gate movl %esp, %ebp 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate pushl %ebx 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate /* drive */ 12157c478bd9Sstevel@tonic-gate movb 0x8(%ebp), %dl 12167c478bd9Sstevel@tonic-gate /* enter real mode */ 12177c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate .code16 12207c478bd9Sstevel@tonic-gate movb $0x41, %ah 12217c478bd9Sstevel@tonic-gate movw $0x55aa, %bx 12227c478bd9Sstevel@tonic-gate int $0x13 /* do the operation */ 12237c478bd9Sstevel@tonic-gate 12247c478bd9Sstevel@tonic-gate /* check the result */ 12257c478bd9Sstevel@tonic-gate jc 1f 12267c478bd9Sstevel@tonic-gate cmpw $0xaa55, %bx 12277c478bd9Sstevel@tonic-gate jne 1f 12287c478bd9Sstevel@tonic-gate 12297c478bd9Sstevel@tonic-gate movb %ah, %bl /* save the major version into %bl */ 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate /* check if AH=0x42 is supported if FORCE_LBA is zero */ 12327c478bd9Sstevel@tonic-gate movb EXT_C(force_lba), %al 12337c478bd9Sstevel@tonic-gate testb %al, %al 12347c478bd9Sstevel@tonic-gate jnz 2f 12357c478bd9Sstevel@tonic-gate andw $1, %cx 12367c478bd9Sstevel@tonic-gate jnz 2f 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate1: 12397c478bd9Sstevel@tonic-gate xorb %bl, %bl 12407c478bd9Sstevel@tonic-gate2: 12417c478bd9Sstevel@tonic-gate /* back to protected mode */ 12427c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 12437c478bd9Sstevel@tonic-gate .code32 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate movb %bl, %al /* return value in %eax */ 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate popl %ebx 12487c478bd9Sstevel@tonic-gate popl %ebp 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate ret 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate/* 12547c478bd9Sstevel@tonic-gate * int get_diskinfo_standard (int drive, unsigned long *cylinders, 12557c478bd9Sstevel@tonic-gate * unsigned long *heads, unsigned long *sectors) 12567c478bd9Sstevel@tonic-gate * 12577c478bd9Sstevel@tonic-gate * Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an 12587c478bd9Sstevel@tonic-gate * error occurs, then return non-zero, otherwise zero. 12597c478bd9Sstevel@tonic-gate */ 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gateENTRY(get_diskinfo_standard) 12627c478bd9Sstevel@tonic-gate pushl %ebp 12637c478bd9Sstevel@tonic-gate movl %esp, %ebp 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate pushl %ebx 12667c478bd9Sstevel@tonic-gate pushl %edi 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate /* drive */ 12697c478bd9Sstevel@tonic-gate movb 0x8(%ebp), %dl 12707c478bd9Sstevel@tonic-gate /* enter real mode */ 12717c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate .code16 12747c478bd9Sstevel@tonic-gate movb $0x8, %ah 12757c478bd9Sstevel@tonic-gate int $0x13 /* do the operation */ 12767c478bd9Sstevel@tonic-gate /* check if successful */ 12777c478bd9Sstevel@tonic-gate testb %ah, %ah 12787c478bd9Sstevel@tonic-gate jnz 1f 12797c478bd9Sstevel@tonic-gate /* bogus BIOSes may not return an error number */ 12807c478bd9Sstevel@tonic-gate testb $0x3f, %cl /* 0 sectors means no disk */ 12817c478bd9Sstevel@tonic-gate jnz 1f /* if non-zero, then succeed */ 12827c478bd9Sstevel@tonic-gate /* XXX 0x60 is one of the unused error numbers */ 12837c478bd9Sstevel@tonic-gate movb $0x60, %ah 12847c478bd9Sstevel@tonic-gate1: 12857c478bd9Sstevel@tonic-gate movb %ah, %bl /* save return value in %bl */ 12867c478bd9Sstevel@tonic-gate /* back to protected mode */ 12877c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 12887c478bd9Sstevel@tonic-gate .code32 12897c478bd9Sstevel@tonic-gate 12907c478bd9Sstevel@tonic-gate /* restore %ebp */ 12917c478bd9Sstevel@tonic-gate leal 0x8(%esp), %ebp 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate /* heads */ 12947c478bd9Sstevel@tonic-gate movb %dh, %al 12957c478bd9Sstevel@tonic-gate incl %eax /* the number of heads is counted from zero */ 12967c478bd9Sstevel@tonic-gate movl 0x10(%ebp), %edi 12977c478bd9Sstevel@tonic-gate movl %eax, (%edi) 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate /* sectors */ 13007c478bd9Sstevel@tonic-gate xorl %eax, %eax 13017c478bd9Sstevel@tonic-gate movb %cl, %al 13027c478bd9Sstevel@tonic-gate andb $0x3f, %al 13037c478bd9Sstevel@tonic-gate movl 0x14(%ebp), %edi 13047c478bd9Sstevel@tonic-gate movl %eax, (%edi) 13057c478bd9Sstevel@tonic-gate 13067c478bd9Sstevel@tonic-gate /* cylinders */ 13077c478bd9Sstevel@tonic-gate shrb $6, %cl 13087c478bd9Sstevel@tonic-gate movb %cl, %ah 13097c478bd9Sstevel@tonic-gate movb %ch, %al 13107c478bd9Sstevel@tonic-gate incl %eax /* the number of cylinders is 13117c478bd9Sstevel@tonic-gate counted from zero */ 13127c478bd9Sstevel@tonic-gate movl 0xc(%ebp), %edi 13137c478bd9Sstevel@tonic-gate movl %eax, (%edi) 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate xorl %eax, %eax 13167c478bd9Sstevel@tonic-gate movb %bl, %al /* return value in %eax */ 13177c478bd9Sstevel@tonic-gate 13187c478bd9Sstevel@tonic-gate popl %edi 13197c478bd9Sstevel@tonic-gate popl %ebx 13207c478bd9Sstevel@tonic-gate popl %ebp 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate ret 13237c478bd9Sstevel@tonic-gate 13247c478bd9Sstevel@tonic-gate 13257c478bd9Sstevel@tonic-gate#if 0 13267c478bd9Sstevel@tonic-gate/* 13277c478bd9Sstevel@tonic-gate * int get_diskinfo_floppy (int drive, unsigned long *cylinders, 13287c478bd9Sstevel@tonic-gate * unsigned long *heads, unsigned long *sectors) 13297c478bd9Sstevel@tonic-gate * 13307c478bd9Sstevel@tonic-gate * Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an 13317c478bd9Sstevel@tonic-gate * error occurs, then return non-zero, otherwise zero. 13327c478bd9Sstevel@tonic-gate */ 13337c478bd9Sstevel@tonic-gate 13347c478bd9Sstevel@tonic-gateENTRY(get_diskinfo_floppy) 13357c478bd9Sstevel@tonic-gate pushl %ebp 13367c478bd9Sstevel@tonic-gate movl %esp, %ebp 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate pushl %ebx 13397c478bd9Sstevel@tonic-gate pushl %esi 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate /* drive */ 13427c478bd9Sstevel@tonic-gate movb 0x8(%ebp), %dl 13437c478bd9Sstevel@tonic-gate /* enter real mode */ 13447c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate .code16 13477c478bd9Sstevel@tonic-gate /* init probe value */ 13487c478bd9Sstevel@tonic-gate movl $probe_values-1, %esi 13497c478bd9Sstevel@tonic-gate1: 13507c478bd9Sstevel@tonic-gate xorw %ax, %ax 13517c478bd9Sstevel@tonic-gate int $0x13 /* reset floppy controller */ 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate incw %si 13547c478bd9Sstevel@tonic-gate movb (%si), %cl 13557c478bd9Sstevel@tonic-gate cmpb $0, %cl /* probe failed if zero */ 13567c478bd9Sstevel@tonic-gate je 2f 13577c478bd9Sstevel@tonic-gate 13587c478bd9Sstevel@tonic-gate /* perform read */ 13597c478bd9Sstevel@tonic-gate movw $SCRATCHSEG, %ax 13607c478bd9Sstevel@tonic-gate movw %ax, %es 13617c478bd9Sstevel@tonic-gate xorw %bx, %bx 13627c478bd9Sstevel@tonic-gate movw $0x0201, %ax 13637c478bd9Sstevel@tonic-gate movb $0, %ch 13647c478bd9Sstevel@tonic-gate movb $0, %dh 13657c478bd9Sstevel@tonic-gate int $0x13 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate /* FIXME: Read from floppy may fail even if the geometry is correct. 13687c478bd9Sstevel@tonic-gate So should retry at least three times. */ 13697c478bd9Sstevel@tonic-gate jc 1b /* next value */ 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate /* succeed */ 13727c478bd9Sstevel@tonic-gate jmp 2f 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gateprobe_values: 13757c478bd9Sstevel@tonic-gate .byte 36, 18, 15, 9, 0 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate2: 13787c478bd9Sstevel@tonic-gate /* back to protected mode */ 13797c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 13807c478bd9Sstevel@tonic-gate .code32 13817c478bd9Sstevel@tonic-gate 13827c478bd9Sstevel@tonic-gate /* restore %ebp */ 13837c478bd9Sstevel@tonic-gate leal 0x8(%esp), %ebp 13847c478bd9Sstevel@tonic-gate 13857c478bd9Sstevel@tonic-gate /* cylinders */ 13867c478bd9Sstevel@tonic-gate movl 0xc(%ebp), %eax 13877c478bd9Sstevel@tonic-gate movl $80, %ebx 13887c478bd9Sstevel@tonic-gate movl %ebx, (%eax) 13897c478bd9Sstevel@tonic-gate /* heads */ 13907c478bd9Sstevel@tonic-gate movl 0x10(%ebp), %eax 13917c478bd9Sstevel@tonic-gate movl $2, %ebx 13927c478bd9Sstevel@tonic-gate movl %ebx, (%eax) 13937c478bd9Sstevel@tonic-gate /* sectors */ 13947c478bd9Sstevel@tonic-gate movl 0x14(%ebp), %eax 13957c478bd9Sstevel@tonic-gate movzbl %cl, %ebx 13967c478bd9Sstevel@tonic-gate movl %ebx, (%eax) 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate /* return value in %eax */ 13997c478bd9Sstevel@tonic-gate xorl %eax, %eax 14007c478bd9Sstevel@tonic-gate cmpb $0, %cl 14017c478bd9Sstevel@tonic-gate jne 3f 14027c478bd9Sstevel@tonic-gate incl %eax /* %eax = 1 (non-zero) */ 14037c478bd9Sstevel@tonic-gate3: 14047c478bd9Sstevel@tonic-gate popl %esi 14057c478bd9Sstevel@tonic-gate popl %ebx 14067c478bd9Sstevel@tonic-gate popl %ebp 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate ret 14097c478bd9Sstevel@tonic-gate#endif 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate/* Source files are splitted, as they have different copyrights. */ 14137c478bd9Sstevel@tonic-gate#ifndef STAGE1_5 14147c478bd9Sstevel@tonic-gate# include "setjmp.S" 14157c478bd9Sstevel@tonic-gate# include "apm.S" 14167c478bd9Sstevel@tonic-gate#endif /* ! STAGE1_5 */ 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate#ifndef STAGE1_5 14217c478bd9Sstevel@tonic-gate/* get_code_end() : return the address of the end of the code 14227c478bd9Sstevel@tonic-gate * This is here so that it can be replaced by asmstub.c. 14237c478bd9Sstevel@tonic-gate */ 14247c478bd9Sstevel@tonic-gateENTRY(get_code_end) 14257c478bd9Sstevel@tonic-gate /* will be the end of the bss */ 14267c478bd9Sstevel@tonic-gate# if defined(HAVE_END_SYMBOL) 14277c478bd9Sstevel@tonic-gate movl $end, %eax 14287c478bd9Sstevel@tonic-gate# elif defined(HAVE_USCORE_END_SYMBOL) 14297c478bd9Sstevel@tonic-gate movl $_end, %eax 14307c478bd9Sstevel@tonic-gate# endif 14317c478bd9Sstevel@tonic-gate shrl $2, %eax /* Round up to the next word. */ 14327c478bd9Sstevel@tonic-gate incl %eax 14337c478bd9Sstevel@tonic-gate shll $2, %eax 14347c478bd9Sstevel@tonic-gate ret 14357c478bd9Sstevel@tonic-gate#endif /* ! STAGE1_5 */ 14367c478bd9Sstevel@tonic-gate 14377c478bd9Sstevel@tonic-gate/* 14387c478bd9Sstevel@tonic-gate * 14397c478bd9Sstevel@tonic-gate * get_memsize(i) : return the memory size in KB. i == 0 for conventional 14407c478bd9Sstevel@tonic-gate * memory, i == 1 for extended memory 14417c478bd9Sstevel@tonic-gate * BIOS call "INT 12H" to get conventional memory size 14427c478bd9Sstevel@tonic-gate * BIOS call "INT 15H, AH=88H" to get extended memory size 14437c478bd9Sstevel@tonic-gate * Both have the return value in AX. 14447c478bd9Sstevel@tonic-gate * 14457c478bd9Sstevel@tonic-gate */ 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gateENTRY(get_memsize) 14487c478bd9Sstevel@tonic-gate push %ebp 14497c478bd9Sstevel@tonic-gate push %ebx 14507c478bd9Sstevel@tonic-gate 14517c478bd9Sstevel@tonic-gate mov 0xc(%esp), %ebx 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) /* enter real mode */ 14547c478bd9Sstevel@tonic-gate .code16 14557c478bd9Sstevel@tonic-gate 14567c478bd9Sstevel@tonic-gate cmpb $0x1, %bl 14577c478bd9Sstevel@tonic-gate DATA32 je xext 14587c478bd9Sstevel@tonic-gate 14597c478bd9Sstevel@tonic-gate int $0x12 14607c478bd9Sstevel@tonic-gate DATA32 jmp xdone 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gatexext: 14637c478bd9Sstevel@tonic-gate movb $0x88, %ah 14647c478bd9Sstevel@tonic-gate int $0x15 14657c478bd9Sstevel@tonic-gate 14667c478bd9Sstevel@tonic-gatexdone: 14677c478bd9Sstevel@tonic-gate movw %ax, %bx 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 14707c478bd9Sstevel@tonic-gate .code32 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate movw %bx, %ax 14737c478bd9Sstevel@tonic-gate pop %ebx 14747c478bd9Sstevel@tonic-gate pop %ebp 14757c478bd9Sstevel@tonic-gate ret 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate 14787c478bd9Sstevel@tonic-gate#ifndef STAGE1_5 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate/* 14817c478bd9Sstevel@tonic-gate * 14827c478bd9Sstevel@tonic-gate * get_eisamemsize() : return packed EISA memory map, lower 16 bits is 14837c478bd9Sstevel@tonic-gate * memory between 1M and 16M in 1K parts, upper 16 bits is 14847c478bd9Sstevel@tonic-gate * memory above 16M in 64K parts. If error, return -1. 14857c478bd9Sstevel@tonic-gate * BIOS call "INT 15H, AH=E801H" to get EISA memory map, 14867c478bd9Sstevel@tonic-gate * AX = memory between 1M and 16M in 1K parts. 14877c478bd9Sstevel@tonic-gate * BX = memory above 16M in 64K parts. 14887c478bd9Sstevel@tonic-gate * 14897c478bd9Sstevel@tonic-gate */ 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gateENTRY(get_eisamemsize) 14927c478bd9Sstevel@tonic-gate push %ebp 14937c478bd9Sstevel@tonic-gate push %ebx 14947c478bd9Sstevel@tonic-gate 14957c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) /* enter real mode */ 14967c478bd9Sstevel@tonic-gate .code16 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate movw $0xe801, %ax 14997c478bd9Sstevel@tonic-gate int $0x15 15007c478bd9Sstevel@tonic-gate 15017c478bd9Sstevel@tonic-gate shll $16, %ebx 15027c478bd9Sstevel@tonic-gate movw %ax, %bx 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 15057c478bd9Sstevel@tonic-gate .code32 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate movl $0xFFFFFFFF, %eax 15087c478bd9Sstevel@tonic-gate cmpb $0x86, %bh 15097c478bd9Sstevel@tonic-gate je xnoteisa 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate movl %ebx, %eax 15127c478bd9Sstevel@tonic-gate 15137c478bd9Sstevel@tonic-gatexnoteisa: 15147c478bd9Sstevel@tonic-gate pop %ebx 15157c478bd9Sstevel@tonic-gate pop %ebp 15167c478bd9Sstevel@tonic-gate ret 15177c478bd9Sstevel@tonic-gate 15187c478bd9Sstevel@tonic-gate/* 15197c478bd9Sstevel@tonic-gate * 15207c478bd9Sstevel@tonic-gate * get_mmap_entry(addr, cont) : address and old continuation value (zero to 15217c478bd9Sstevel@tonic-gate * start), for the Query System Address Map BIOS call. 15227c478bd9Sstevel@tonic-gate * 15237c478bd9Sstevel@tonic-gate * Sets the first 4-byte int value of "addr" to the size returned by 15247c478bd9Sstevel@tonic-gate * the call. If the call fails, sets it to zero. 15257c478bd9Sstevel@tonic-gate * 15267c478bd9Sstevel@tonic-gate * Returns: new (non-zero) continuation value, 0 if done. 15277c478bd9Sstevel@tonic-gate * 15287c478bd9Sstevel@tonic-gate * NOTE: Currently hard-coded for a maximum buffer length of 1024. 15297c478bd9Sstevel@tonic-gate */ 15307c478bd9Sstevel@tonic-gate 15317c478bd9Sstevel@tonic-gateENTRY(get_mmap_entry) 15327c478bd9Sstevel@tonic-gate push %ebp 15337c478bd9Sstevel@tonic-gate push %ebx 15347c478bd9Sstevel@tonic-gate push %edi 15357c478bd9Sstevel@tonic-gate push %esi 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate /* place address (+4) in ES:DI */ 15387c478bd9Sstevel@tonic-gate movl 0x14(%esp), %eax 15397c478bd9Sstevel@tonic-gate addl $4, %eax 15407c478bd9Sstevel@tonic-gate movl %eax, %edi 15417c478bd9Sstevel@tonic-gate andl $0xf, %edi 15427c478bd9Sstevel@tonic-gate shrl $4, %eax 15437c478bd9Sstevel@tonic-gate movl %eax, %esi 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate /* set continuation value */ 15467c478bd9Sstevel@tonic-gate movl 0x18(%esp), %ebx 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate /* set default maximum buffer size */ 15497c478bd9Sstevel@tonic-gate movl $0x14, %ecx 15507c478bd9Sstevel@tonic-gate 15517c478bd9Sstevel@tonic-gate /* set EDX to 'SMAP' */ 15527c478bd9Sstevel@tonic-gate movl $0x534d4150, %edx 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) /* enter real mode */ 15557c478bd9Sstevel@tonic-gate .code16 15567c478bd9Sstevel@tonic-gate 15577c478bd9Sstevel@tonic-gate movw %si, %es 15587c478bd9Sstevel@tonic-gate movl $0xe820, %eax 15597c478bd9Sstevel@tonic-gate int $0x15 15607c478bd9Sstevel@tonic-gate 15617c478bd9Sstevel@tonic-gate DATA32 jc xnosmap 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate cmpl $0x534d4150, %eax 15647c478bd9Sstevel@tonic-gate DATA32 jne xnosmap 15657c478bd9Sstevel@tonic-gate 15667c478bd9Sstevel@tonic-gate cmpl $0x14, %ecx 15677c478bd9Sstevel@tonic-gate DATA32 jl xnosmap 15687c478bd9Sstevel@tonic-gate 15697c478bd9Sstevel@tonic-gate cmpl $0x400, %ecx 15707c478bd9Sstevel@tonic-gate DATA32 jg xnosmap 15717c478bd9Sstevel@tonic-gate 15727c478bd9Sstevel@tonic-gate DATA32 jmp xsmap 15737c478bd9Sstevel@tonic-gate 15747c478bd9Sstevel@tonic-gatexnosmap: 15757c478bd9Sstevel@tonic-gate movl $0, %ecx 15767c478bd9Sstevel@tonic-gate 15777c478bd9Sstevel@tonic-gatexsmap: 15787c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 15797c478bd9Sstevel@tonic-gate .code32 15807c478bd9Sstevel@tonic-gate 15817c478bd9Sstevel@tonic-gate /* write length of buffer (zero if error) into "addr" */ 15827c478bd9Sstevel@tonic-gate movl 0x14(%esp), %eax 15837c478bd9Sstevel@tonic-gate movl %ecx, (%eax) 15847c478bd9Sstevel@tonic-gate 15857c478bd9Sstevel@tonic-gate /* set return value to continuation */ 15867c478bd9Sstevel@tonic-gate movl %ebx, %eax 15877c478bd9Sstevel@tonic-gate 15887c478bd9Sstevel@tonic-gate pop %esi 15897c478bd9Sstevel@tonic-gate pop %edi 15907c478bd9Sstevel@tonic-gate pop %ebx 15917c478bd9Sstevel@tonic-gate pop %ebp 15927c478bd9Sstevel@tonic-gate ret 15937c478bd9Sstevel@tonic-gate 15947c478bd9Sstevel@tonic-gate/* 15957c478bd9Sstevel@tonic-gate * get_rom_config_table() 15967c478bd9Sstevel@tonic-gate * 15977c478bd9Sstevel@tonic-gate * Get the linear address of a ROM configuration table. Return zero, 15987c478bd9Sstevel@tonic-gate * if fails. 15997c478bd9Sstevel@tonic-gate */ 16007c478bd9Sstevel@tonic-gate 16017c478bd9Sstevel@tonic-gateENTRY(get_rom_config_table) 16027c478bd9Sstevel@tonic-gate pushl %ebp 16037c478bd9Sstevel@tonic-gate pushl %ebx 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate /* zero %ebx for simplicity */ 16067c478bd9Sstevel@tonic-gate xorl %ebx, %ebx 16077c478bd9Sstevel@tonic-gate 16087c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 16097c478bd9Sstevel@tonic-gate .code16 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate movw $0xc0, %ax 16127c478bd9Sstevel@tonic-gate int $0x15 16137c478bd9Sstevel@tonic-gate 16147c478bd9Sstevel@tonic-gate jc no_rom_table 16157c478bd9Sstevel@tonic-gate testb %ah, %ah 16167c478bd9Sstevel@tonic-gate jnz no_rom_table 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate movw %es, %dx 16197c478bd9Sstevel@tonic-gate jmp found_rom_table 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gateno_rom_table: 16227c478bd9Sstevel@tonic-gate xorw %dx, %dx 16237c478bd9Sstevel@tonic-gate xorw %bx, %bx 16247c478bd9Sstevel@tonic-gate 16257c478bd9Sstevel@tonic-gatefound_rom_table: 16267c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 16277c478bd9Sstevel@tonic-gate .code32 16287c478bd9Sstevel@tonic-gate 16297c478bd9Sstevel@tonic-gate /* compute the linear address */ 16307c478bd9Sstevel@tonic-gate movw %dx, %ax 16317c478bd9Sstevel@tonic-gate shll $4, %eax 16327c478bd9Sstevel@tonic-gate addl %ebx, %eax 16337c478bd9Sstevel@tonic-gate 16347c478bd9Sstevel@tonic-gate popl %ebx 16357c478bd9Sstevel@tonic-gate popl %ebp 16367c478bd9Sstevel@tonic-gate ret 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate/* 16407c478bd9Sstevel@tonic-gate * int get_vbe_controller_info (struct vbe_controller *controller_ptr) 16417c478bd9Sstevel@tonic-gate * 16427c478bd9Sstevel@tonic-gate * Get VBE controller information. 16437c478bd9Sstevel@tonic-gate */ 16447c478bd9Sstevel@tonic-gate 16457c478bd9Sstevel@tonic-gateENTRY(get_vbe_controller_info) 16467c478bd9Sstevel@tonic-gate pushl %ebp 16477c478bd9Sstevel@tonic-gate movl %esp, %ebp 16487c478bd9Sstevel@tonic-gate 16497c478bd9Sstevel@tonic-gate pushl %edi 16507c478bd9Sstevel@tonic-gate pushl %ebx 16517c478bd9Sstevel@tonic-gate 16527c478bd9Sstevel@tonic-gate /* Convert the linear address to segment:offset */ 16537c478bd9Sstevel@tonic-gate movl 8(%ebp), %eax 16547c478bd9Sstevel@tonic-gate movl %eax, %edi 16557c478bd9Sstevel@tonic-gate andl $0x0000000f, %edi 16567c478bd9Sstevel@tonic-gate shrl $4, %eax 16577c478bd9Sstevel@tonic-gate movl %eax, %ebx 16587c478bd9Sstevel@tonic-gate 16597c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 16607c478bd9Sstevel@tonic-gate .code16 16617c478bd9Sstevel@tonic-gate 16627c478bd9Sstevel@tonic-gate movw %bx, %es 16637c478bd9Sstevel@tonic-gate movw $0x4F00, %ax 16647c478bd9Sstevel@tonic-gate int $0x10 16657c478bd9Sstevel@tonic-gate 16667c478bd9Sstevel@tonic-gate movw %ax, %bx 16677c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 16687c478bd9Sstevel@tonic-gate .code32 16697c478bd9Sstevel@tonic-gate 16707c478bd9Sstevel@tonic-gate movzwl %bx, %eax 16717c478bd9Sstevel@tonic-gate 16727c478bd9Sstevel@tonic-gate popl %ebx 16737c478bd9Sstevel@tonic-gate popl %edi 16747c478bd9Sstevel@tonic-gate popl %ebp 16757c478bd9Sstevel@tonic-gate ret 16767c478bd9Sstevel@tonic-gate 16777c478bd9Sstevel@tonic-gate 16787c478bd9Sstevel@tonic-gate/* 16797c478bd9Sstevel@tonic-gate * int get_vbe_mode_info (int mode_number, struct vbe_mode *mode_ptr) 16807c478bd9Sstevel@tonic-gate * 16817c478bd9Sstevel@tonic-gate * Get VBE mode information. 16827c478bd9Sstevel@tonic-gate */ 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gateENTRY(get_vbe_mode_info) 16857c478bd9Sstevel@tonic-gate pushl %ebp 16867c478bd9Sstevel@tonic-gate movl %esp, %ebp 16877c478bd9Sstevel@tonic-gate 16887c478bd9Sstevel@tonic-gate pushl %edi 16897c478bd9Sstevel@tonic-gate pushl %ebx 16907c478bd9Sstevel@tonic-gate 16917c478bd9Sstevel@tonic-gate /* Convert the linear address to segment:offset */ 16927c478bd9Sstevel@tonic-gate movl 0xc(%ebp), %eax 16937c478bd9Sstevel@tonic-gate movl %eax, %edi 16947c478bd9Sstevel@tonic-gate andl $0x0000000f, %edi 16957c478bd9Sstevel@tonic-gate shrl $4, %eax 16967c478bd9Sstevel@tonic-gate movl %eax, %ebx 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate /* Save the mode number in %cx */ 16997c478bd9Sstevel@tonic-gate movl 0x8(%ebp), %ecx 17007c478bd9Sstevel@tonic-gate 17017c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 17027c478bd9Sstevel@tonic-gate .code16 17037c478bd9Sstevel@tonic-gate 17047c478bd9Sstevel@tonic-gate movw %bx, %es 17057c478bd9Sstevel@tonic-gate movw $0x4F01, %ax 17067c478bd9Sstevel@tonic-gate int $0x10 17077c478bd9Sstevel@tonic-gate 17087c478bd9Sstevel@tonic-gate movw %ax, %bx 17097c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 17107c478bd9Sstevel@tonic-gate .code32 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate movzwl %bx, %eax 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate popl %ebx 17157c478bd9Sstevel@tonic-gate popl %edi 17167c478bd9Sstevel@tonic-gate popl %ebp 17177c478bd9Sstevel@tonic-gate ret 17187c478bd9Sstevel@tonic-gate 17197c478bd9Sstevel@tonic-gate 17207c478bd9Sstevel@tonic-gate/* 17217c478bd9Sstevel@tonic-gate * int set_vbe_mode (int mode_number) 17227c478bd9Sstevel@tonic-gate * 17237c478bd9Sstevel@tonic-gate * Set VBE mode. Don't support user-specified CRTC information. 17247c478bd9Sstevel@tonic-gate */ 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gateENTRY(set_vbe_mode) 17277c478bd9Sstevel@tonic-gate pushl %ebp 17287c478bd9Sstevel@tonic-gate movl %esp, %ebp 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate pushl %ebx 17317c478bd9Sstevel@tonic-gate 17327c478bd9Sstevel@tonic-gate /* Save the mode number in %bx */ 17337c478bd9Sstevel@tonic-gate movl 0x8(%ebp), %ebx 17347c478bd9Sstevel@tonic-gate /* Clear bit D11 */ 17357c478bd9Sstevel@tonic-gate andl $0xF7FF, %ebx 17367c478bd9Sstevel@tonic-gate 17377c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 17387c478bd9Sstevel@tonic-gate .code16 17397c478bd9Sstevel@tonic-gate 17407c478bd9Sstevel@tonic-gate movw $0x4F02, %ax 17417c478bd9Sstevel@tonic-gate int $0x10 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate movw %ax, %bx 17447c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 17457c478bd9Sstevel@tonic-gate .code32 17467c478bd9Sstevel@tonic-gate 17477c478bd9Sstevel@tonic-gate movzwl %bx, %eax 17487c478bd9Sstevel@tonic-gate 17497c478bd9Sstevel@tonic-gate popl %ebx 17507c478bd9Sstevel@tonic-gate popl %ebp 17517c478bd9Sstevel@tonic-gate ret 17527c478bd9Sstevel@tonic-gate 17537c478bd9Sstevel@tonic-gate 17547c478bd9Sstevel@tonic-gate/* 17557c478bd9Sstevel@tonic-gate * gateA20(int linear) 17567c478bd9Sstevel@tonic-gate * 17577c478bd9Sstevel@tonic-gate * Gate address-line 20 for high memory. 17587c478bd9Sstevel@tonic-gate * 17597c478bd9Sstevel@tonic-gate * This routine is probably overconservative in what it does, but so what? 17607c478bd9Sstevel@tonic-gate * 17617c478bd9Sstevel@tonic-gate * It also eats any keystrokes in the keyboard buffer. :-( 17627c478bd9Sstevel@tonic-gate */ 17637c478bd9Sstevel@tonic-gate 17647c478bd9Sstevel@tonic-gateENTRY(gateA20) 17657c478bd9Sstevel@tonic-gate /* first, try a BIOS call */ 17667c478bd9Sstevel@tonic-gate pushl %ebp 17677c478bd9Sstevel@tonic-gate movl 8(%esp), %edx 17687c478bd9Sstevel@tonic-gate 17697c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 17707c478bd9Sstevel@tonic-gate 17717c478bd9Sstevel@tonic-gate .code16 17727c478bd9Sstevel@tonic-gate movw $0x2400, %ax 17737c478bd9Sstevel@tonic-gate testw %dx, %dx 17747c478bd9Sstevel@tonic-gate jz 1f 17757c478bd9Sstevel@tonic-gate incw %ax 17767c478bd9Sstevel@tonic-gate1: stc 17777c478bd9Sstevel@tonic-gate int $0x15 17787c478bd9Sstevel@tonic-gate jnc 2f 17797c478bd9Sstevel@tonic-gate 17807c478bd9Sstevel@tonic-gate /* set non-zero if failed */ 17817c478bd9Sstevel@tonic-gate movb $1, %ah 17827c478bd9Sstevel@tonic-gate 17837c478bd9Sstevel@tonic-gate /* save the status */ 17847c478bd9Sstevel@tonic-gate2: movb %ah, %dl 17857c478bd9Sstevel@tonic-gate 17867c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 17877c478bd9Sstevel@tonic-gate .code32 17887c478bd9Sstevel@tonic-gate 17897c478bd9Sstevel@tonic-gate popl %ebp 17907c478bd9Sstevel@tonic-gate testb %dl, %dl 17917c478bd9Sstevel@tonic-gate jnz 3f 17927c478bd9Sstevel@tonic-gate ret 17937c478bd9Sstevel@tonic-gate 17946ee4b8d7Ssetje3: /* 17956ee4b8d7Ssetje * try to switch gateA20 using PORT92, the "Fast A20 and Init" 17966ee4b8d7Ssetje * register 17976ee4b8d7Ssetje */ 17986ee4b8d7Ssetje mov $0x92, %dx 17996ee4b8d7Ssetje inb %dx, %al 18006ee4b8d7Ssetje /* skip the port92 code if it's unimplemented (read returns 0xff) */ 18016ee4b8d7Ssetje cmpb $0xff, %al 18026ee4b8d7Ssetje jz 6f 18036ee4b8d7Ssetje 18046ee4b8d7Ssetje /* set or clear bit1, the ALT_A20_GATE bit */ 18056ee4b8d7Ssetje movb 4(%esp), %ah 18066ee4b8d7Ssetje testb %ah, %ah 18076ee4b8d7Ssetje jz 4f 18086ee4b8d7Ssetje orb $2, %al 18096ee4b8d7Ssetje jmp 5f 18106ee4b8d7Ssetje4: and $0xfd, %al 18116ee4b8d7Ssetje 18126ee4b8d7Ssetje /* clear the INIT_NOW bit; don't accidently reset the machine */ 18136ee4b8d7Ssetje5: and $0xfe, %al 18146ee4b8d7Ssetje outb %al, %dx 18156ee4b8d7Ssetje 18166ee4b8d7Ssetje6: /* use keyboard controller */ 18177c478bd9Sstevel@tonic-gate pushl %eax 18187c478bd9Sstevel@tonic-gate 18197c478bd9Sstevel@tonic-gate call gloop1 18207c478bd9Sstevel@tonic-gate 18217c478bd9Sstevel@tonic-gate movb $KC_CMD_WOUT, %al 18227c478bd9Sstevel@tonic-gate outb $K_CMD 18237c478bd9Sstevel@tonic-gate 18247c478bd9Sstevel@tonic-gategloopint1: 18257c478bd9Sstevel@tonic-gate inb $K_STATUS 18266ee4b8d7Ssetje cmpb $0xff, %al 18276ee4b8d7Ssetje jz gloopint1_done 18287c478bd9Sstevel@tonic-gate andb $K_IBUF_FUL, %al 18297c478bd9Sstevel@tonic-gate jnz gloopint1 18307c478bd9Sstevel@tonic-gate 18316ee4b8d7Ssetjegloopint1_done: 18327c478bd9Sstevel@tonic-gate movb $KB_OUTPUT_MASK, %al 18337c478bd9Sstevel@tonic-gate cmpb $0, 0x8(%esp) 18347c478bd9Sstevel@tonic-gate jz gdoit 18357c478bd9Sstevel@tonic-gate 18367c478bd9Sstevel@tonic-gate orb $KB_A20_ENABLE, %al 18377c478bd9Sstevel@tonic-gategdoit: 18387c478bd9Sstevel@tonic-gate outb $K_RDWR 18397c478bd9Sstevel@tonic-gate 18407c478bd9Sstevel@tonic-gate call gloop1 18417c478bd9Sstevel@tonic-gate 18427c478bd9Sstevel@tonic-gate /* output a dummy command (USB keyboard hack) */ 18437c478bd9Sstevel@tonic-gate movb $0xff, %al 18447c478bd9Sstevel@tonic-gate outb $K_CMD 18457c478bd9Sstevel@tonic-gate call gloop1 18467c478bd9Sstevel@tonic-gate 18477c478bd9Sstevel@tonic-gate popl %eax 18487c478bd9Sstevel@tonic-gate ret 18497c478bd9Sstevel@tonic-gate 18507c478bd9Sstevel@tonic-gategloop1: 18517c478bd9Sstevel@tonic-gate inb $K_STATUS 18526ee4b8d7Ssetje cmpb $0xff, %al 18536ee4b8d7Ssetje jz gloop2ret 18547c478bd9Sstevel@tonic-gate andb $K_IBUF_FUL, %al 18557c478bd9Sstevel@tonic-gate jnz gloop1 18567c478bd9Sstevel@tonic-gate 18577c478bd9Sstevel@tonic-gategloop2: 18587c478bd9Sstevel@tonic-gate inb $K_STATUS 18597c478bd9Sstevel@tonic-gate andb $K_OBUF_FUL, %al 18607c478bd9Sstevel@tonic-gate jz gloop2ret 18617c478bd9Sstevel@tonic-gate inb $K_RDWR 18627c478bd9Sstevel@tonic-gate jmp gloop2 18637c478bd9Sstevel@tonic-gate 18647c478bd9Sstevel@tonic-gategloop2ret: 18657c478bd9Sstevel@tonic-gate ret 18667c478bd9Sstevel@tonic-gate 18677c478bd9Sstevel@tonic-gate 18687c478bd9Sstevel@tonic-gateENTRY(patch_code) /* labels start with "pc_" */ 18697c478bd9Sstevel@tonic-gate .code16 18707c478bd9Sstevel@tonic-gate 18717c478bd9Sstevel@tonic-gate mov %cs, %ax 18727c478bd9Sstevel@tonic-gate mov %ax, %ds 18737c478bd9Sstevel@tonic-gate mov %ax, %es 18747c478bd9Sstevel@tonic-gate mov %ax, %fs 18757c478bd9Sstevel@tonic-gate mov %ax, %gs 18767c478bd9Sstevel@tonic-gate ADDR32 movl $0, 0 18777c478bd9Sstevel@tonic-gatepc_stop: 18787c478bd9Sstevel@tonic-gate hlt 18797c478bd9Sstevel@tonic-gate DATA32 jmp pc_stop 18807c478bd9Sstevel@tonic-gateENTRY(patch_code_end) 18817c478bd9Sstevel@tonic-gate 18827c478bd9Sstevel@tonic-gate .code32 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate 18857c478bd9Sstevel@tonic-gate/* 18867c478bd9Sstevel@tonic-gate * linux_boot() 18877c478bd9Sstevel@tonic-gate * 18887c478bd9Sstevel@tonic-gate * Does some funky things (including on the stack!), then jumps to the 18897c478bd9Sstevel@tonic-gate * entry point of the Linux setup code. 18907c478bd9Sstevel@tonic-gate */ 18917c478bd9Sstevel@tonic-gate 18927c478bd9Sstevel@tonic-gateVARIABLE(linux_text_len) 18937c478bd9Sstevel@tonic-gate .long 0 18947c478bd9Sstevel@tonic-gate 18957c478bd9Sstevel@tonic-gateVARIABLE(linux_data_tmp_addr) 18967c478bd9Sstevel@tonic-gate .long 0 18977c478bd9Sstevel@tonic-gate 18987c478bd9Sstevel@tonic-gateVARIABLE(linux_data_real_addr) 18997c478bd9Sstevel@tonic-gate .long 0 19007c478bd9Sstevel@tonic-gate 19017c478bd9Sstevel@tonic-gateENTRY(linux_boot) 19027c478bd9Sstevel@tonic-gate /* don't worry about saving anything, we're committed at this point */ 19037c478bd9Sstevel@tonic-gate cld /* forward copying */ 19047c478bd9Sstevel@tonic-gate 19057c478bd9Sstevel@tonic-gate /* copy kernel */ 19067c478bd9Sstevel@tonic-gate movl EXT_C(linux_text_len), %ecx 19077c478bd9Sstevel@tonic-gate addl $3, %ecx 19087c478bd9Sstevel@tonic-gate shrl $2, %ecx 19097c478bd9Sstevel@tonic-gate movl $LINUX_BZIMAGE_ADDR, %esi 19107c478bd9Sstevel@tonic-gate movl $LINUX_ZIMAGE_ADDR, %edi 19117c478bd9Sstevel@tonic-gate 19127c478bd9Sstevel@tonic-gate rep 19137c478bd9Sstevel@tonic-gate movsl 19147c478bd9Sstevel@tonic-gate 19157c478bd9Sstevel@tonic-gateENTRY(big_linux_boot) 19167c478bd9Sstevel@tonic-gate movl EXT_C(linux_data_real_addr), %ebx 19177c478bd9Sstevel@tonic-gate 19187c478bd9Sstevel@tonic-gate /* copy the real mode part */ 19197c478bd9Sstevel@tonic-gate movl EXT_C(linux_data_tmp_addr), %esi 19207c478bd9Sstevel@tonic-gate movl %ebx, %edi 19217c478bd9Sstevel@tonic-gate movl $LINUX_SETUP_MOVE_SIZE, %ecx 19227c478bd9Sstevel@tonic-gate cld 19237c478bd9Sstevel@tonic-gate rep 19247c478bd9Sstevel@tonic-gate movsb 19257c478bd9Sstevel@tonic-gate 19267c478bd9Sstevel@tonic-gate /* change %ebx to the segment address */ 19277c478bd9Sstevel@tonic-gate shrl $4, %ebx 19287c478bd9Sstevel@tonic-gate movl %ebx, %eax 19297c478bd9Sstevel@tonic-gate addl $0x20, %eax 19307c478bd9Sstevel@tonic-gate movl %eax, linux_setup_seg 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate /* XXX new stack pointer in safe area for calling functions */ 19337c478bd9Sstevel@tonic-gate movl $0x4000, %esp 19347c478bd9Sstevel@tonic-gate call EXT_C(stop_floppy) 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate /* final setup for linux boot */ 19377c478bd9Sstevel@tonic-gate 19387c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 19397c478bd9Sstevel@tonic-gate .code16 19407c478bd9Sstevel@tonic-gate 19417c478bd9Sstevel@tonic-gate /* final setup for linux boot */ 19427c478bd9Sstevel@tonic-gate cli 19437c478bd9Sstevel@tonic-gate movw %bx, %ss 19447c478bd9Sstevel@tonic-gate movw $LINUX_SETUP_STACK, %sp 19457c478bd9Sstevel@tonic-gate 19467c478bd9Sstevel@tonic-gate movw %bx, %ds 19477c478bd9Sstevel@tonic-gate movw %bx, %es 19487c478bd9Sstevel@tonic-gate movw %bx, %fs 19497c478bd9Sstevel@tonic-gate movw %bx, %gs 19507c478bd9Sstevel@tonic-gate 19517c478bd9Sstevel@tonic-gate /* jump to start */ 19527c478bd9Sstevel@tonic-gate /* ljmp */ 19537c478bd9Sstevel@tonic-gate .byte 0xea 19547c478bd9Sstevel@tonic-gate .word 0 19557c478bd9Sstevel@tonic-gatelinux_setup_seg: 19567c478bd9Sstevel@tonic-gate .word 0 19577c478bd9Sstevel@tonic-gate .code32 19587c478bd9Sstevel@tonic-gate 19597c478bd9Sstevel@tonic-gate 19607c478bd9Sstevel@tonic-gate/* 19617c478bd9Sstevel@tonic-gate * multi_boot(int start, int mb_info) 19627c478bd9Sstevel@tonic-gate * 19637c478bd9Sstevel@tonic-gate * This starts a kernel in the manner expected of the multiboot standard. 19647c478bd9Sstevel@tonic-gate */ 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gateENTRY(multi_boot) 19677c478bd9Sstevel@tonic-gate /* no need to save anything */ 19687c478bd9Sstevel@tonic-gate call EXT_C(stop_floppy) 19697c478bd9Sstevel@tonic-gate 19707c478bd9Sstevel@tonic-gate movl $0x2BADB002, %eax 19717c478bd9Sstevel@tonic-gate movl 0x8(%esp), %ebx 19727c478bd9Sstevel@tonic-gate 19737c478bd9Sstevel@tonic-gate /* boot kernel here (absolute address call) */ 19747c478bd9Sstevel@tonic-gate call *0x4(%esp) 19757c478bd9Sstevel@tonic-gate 19767c478bd9Sstevel@tonic-gate /* error */ 19777c478bd9Sstevel@tonic-gate call EXT_C(stop) 19787c478bd9Sstevel@tonic-gate 19797c478bd9Sstevel@tonic-gate#endif /* ! STAGE1_5 */ 19807c478bd9Sstevel@tonic-gate 19817c478bd9Sstevel@tonic-gate/* 19827c478bd9Sstevel@tonic-gate * void console_putchar (int c) 19837c478bd9Sstevel@tonic-gate * 19847c478bd9Sstevel@tonic-gate * Put the character C on the console. Because GRUB wants to write a 19857c478bd9Sstevel@tonic-gate * character with an attribute, this implementation is a bit tricky. 19867c478bd9Sstevel@tonic-gate * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh 19877c478bd9Sstevel@tonic-gate * (TELETYPE OUTPUT). Otherwise, save the original position, put a space, 19887c478bd9Sstevel@tonic-gate * save the current position, restore the original position, write the 19897c478bd9Sstevel@tonic-gate * character and the attribute, and restore the current position. 19907c478bd9Sstevel@tonic-gate * 19917c478bd9Sstevel@tonic-gate * The reason why this is so complicated is that there is no easy way to 19927c478bd9Sstevel@tonic-gate * get the height of the screen, and the TELETYPE OUPUT BIOS call doesn't 19937c478bd9Sstevel@tonic-gate * support setting a background attribute. 19947c478bd9Sstevel@tonic-gate */ 19957c478bd9Sstevel@tonic-gateENTRY(console_putchar) 19967c478bd9Sstevel@tonic-gate movl 0x4(%esp), %edx 19977c478bd9Sstevel@tonic-gate pusha 19987c478bd9Sstevel@tonic-gate#ifdef STAGE1_5 19997c478bd9Sstevel@tonic-gate movb $0x07, %bl 20007c478bd9Sstevel@tonic-gate#else 20017c478bd9Sstevel@tonic-gate movl EXT_C(console_current_color), %ebx 20027c478bd9Sstevel@tonic-gate#endif 20037c478bd9Sstevel@tonic-gate 20047c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 20057c478bd9Sstevel@tonic-gate .code16 20067c478bd9Sstevel@tonic-gate movb %dl, %al 20077c478bd9Sstevel@tonic-gate xorb %bh, %bh 20087c478bd9Sstevel@tonic-gate 20097c478bd9Sstevel@tonic-gate#ifndef STAGE1_5 20107c478bd9Sstevel@tonic-gate /* use teletype output if control character */ 20117c478bd9Sstevel@tonic-gate cmpb $0x7, %al 20127c478bd9Sstevel@tonic-gate je 1f 20137c478bd9Sstevel@tonic-gate cmpb $0x8, %al 20147c478bd9Sstevel@tonic-gate je 1f 20157c478bd9Sstevel@tonic-gate cmpb $0xa, %al 20167c478bd9Sstevel@tonic-gate je 1f 20177c478bd9Sstevel@tonic-gate cmpb $0xd, %al 20187c478bd9Sstevel@tonic-gate je 1f 20197c478bd9Sstevel@tonic-gate 20207c478bd9Sstevel@tonic-gate /* save the character and the attribute on the stack */ 20217c478bd9Sstevel@tonic-gate pushw %ax 20227c478bd9Sstevel@tonic-gate pushw %bx 20237c478bd9Sstevel@tonic-gate 20247c478bd9Sstevel@tonic-gate /* get the current position */ 20257c478bd9Sstevel@tonic-gate movb $0x3, %ah 20267c478bd9Sstevel@tonic-gate int $0x10 20277c478bd9Sstevel@tonic-gate 20287c478bd9Sstevel@tonic-gate /* check the column with the width */ 20297c478bd9Sstevel@tonic-gate cmpb $79, %dl 20307c478bd9Sstevel@tonic-gate jl 2f 20317c478bd9Sstevel@tonic-gate 20327c478bd9Sstevel@tonic-gate /* print CR and LF, if next write will exceed the width */ 20337c478bd9Sstevel@tonic-gate movw $0x0e0d, %ax 20347c478bd9Sstevel@tonic-gate int $0x10 20357c478bd9Sstevel@tonic-gate movb $0x0a, %al 20367c478bd9Sstevel@tonic-gate int $0x10 20377c478bd9Sstevel@tonic-gate 20387c478bd9Sstevel@tonic-gate /* get the current position */ 20397c478bd9Sstevel@tonic-gate movb $0x3, %ah 20407c478bd9Sstevel@tonic-gate int $0x10 20417c478bd9Sstevel@tonic-gate 20427c478bd9Sstevel@tonic-gate2: 20437c478bd9Sstevel@tonic-gate /* restore the character and the attribute */ 20447c478bd9Sstevel@tonic-gate popw %bx 20457c478bd9Sstevel@tonic-gate popw %ax 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate /* write the character with the attribute */ 20487c478bd9Sstevel@tonic-gate movb $0x9, %ah 20497c478bd9Sstevel@tonic-gate movw $1, %cx 20507c478bd9Sstevel@tonic-gate int $0x10 20517c478bd9Sstevel@tonic-gate 20527c478bd9Sstevel@tonic-gate /* move the cursor forward */ 20537c478bd9Sstevel@tonic-gate incb %dl 20547c478bd9Sstevel@tonic-gate movb $0x2, %ah 20557c478bd9Sstevel@tonic-gate int $0x10 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate jmp 3f 20587c478bd9Sstevel@tonic-gate#endif /* ! STAGE1_5 */ 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate1: movb $0xe, %ah 20617c478bd9Sstevel@tonic-gate int $0x10 20627c478bd9Sstevel@tonic-gate 20637c478bd9Sstevel@tonic-gate3: DATA32 call EXT_C(real_to_prot) 20647c478bd9Sstevel@tonic-gate .code32 20657c478bd9Sstevel@tonic-gate 20667c478bd9Sstevel@tonic-gate popa 20677c478bd9Sstevel@tonic-gate ret 20687c478bd9Sstevel@tonic-gate 20697c478bd9Sstevel@tonic-gate 20707c478bd9Sstevel@tonic-gate#ifndef STAGE1_5 20717c478bd9Sstevel@tonic-gate 20727c478bd9Sstevel@tonic-gate/* this table is used in translate_keycode below */ 20737c478bd9Sstevel@tonic-gatetranslation_table: 20747c478bd9Sstevel@tonic-gate .word KEY_LEFT, 2 20757c478bd9Sstevel@tonic-gate .word KEY_RIGHT, 6 20767c478bd9Sstevel@tonic-gate .word KEY_UP, 16 20777c478bd9Sstevel@tonic-gate .word KEY_DOWN, 14 20787c478bd9Sstevel@tonic-gate .word KEY_HOME, 1 20797c478bd9Sstevel@tonic-gate .word KEY_END, 5 20807c478bd9Sstevel@tonic-gate .word KEY_DC, 4 20817c478bd9Sstevel@tonic-gate .word KEY_BACKSPACE, 8 20827c478bd9Sstevel@tonic-gate .word KEY_PPAGE, 7 20837c478bd9Sstevel@tonic-gate .word KEY_NPAGE, 3 20847c478bd9Sstevel@tonic-gate .word 0 20857c478bd9Sstevel@tonic-gate 20867c478bd9Sstevel@tonic-gate/* 20877c478bd9Sstevel@tonic-gate * translate_keycode translates the key code %dx to an ascii code. 20887c478bd9Sstevel@tonic-gate */ 20897c478bd9Sstevel@tonic-gate .code16 20907c478bd9Sstevel@tonic-gate 20917c478bd9Sstevel@tonic-gatetranslate_keycode: 20927c478bd9Sstevel@tonic-gate pushw %bx 20937c478bd9Sstevel@tonic-gate pushw %si 20947c478bd9Sstevel@tonic-gate 20957c478bd9Sstevel@tonic-gate movw $ABS(translation_table), %si 20967c478bd9Sstevel@tonic-gate 20977c478bd9Sstevel@tonic-gate1: lodsw 20987c478bd9Sstevel@tonic-gate /* check if this is the end */ 20997c478bd9Sstevel@tonic-gate testw %ax, %ax 21007c478bd9Sstevel@tonic-gate jz 2f 21017c478bd9Sstevel@tonic-gate /* load the ascii code into %ax */ 21027c478bd9Sstevel@tonic-gate movw %ax, %bx 21037c478bd9Sstevel@tonic-gate lodsw 21047c478bd9Sstevel@tonic-gate /* check if this matches the key code */ 21057c478bd9Sstevel@tonic-gate cmpw %bx, %dx 21067c478bd9Sstevel@tonic-gate jne 1b 21077c478bd9Sstevel@tonic-gate /* translate %dx, if successful */ 21087c478bd9Sstevel@tonic-gate movw %ax, %dx 21097c478bd9Sstevel@tonic-gate 21107c478bd9Sstevel@tonic-gate2: popw %si 21117c478bd9Sstevel@tonic-gate popw %bx 21127c478bd9Sstevel@tonic-gate ret 21137c478bd9Sstevel@tonic-gate 21147c478bd9Sstevel@tonic-gate .code32 21157c478bd9Sstevel@tonic-gate 21167c478bd9Sstevel@tonic-gate 21177c478bd9Sstevel@tonic-gate/* 21187c478bd9Sstevel@tonic-gate * remap_ascii_char remaps the ascii code %dl to another if the code is 21197c478bd9Sstevel@tonic-gate * contained in ASCII_KEY_MAP. 21207c478bd9Sstevel@tonic-gate */ 21217c478bd9Sstevel@tonic-gate .code16 21227c478bd9Sstevel@tonic-gate 21237c478bd9Sstevel@tonic-gateremap_ascii_char: 21247c478bd9Sstevel@tonic-gate pushw %si 21257c478bd9Sstevel@tonic-gate 21267c478bd9Sstevel@tonic-gate movw $ABS(EXT_C(ascii_key_map)), %si 21277c478bd9Sstevel@tonic-gate1: 21287c478bd9Sstevel@tonic-gate lodsw 21297c478bd9Sstevel@tonic-gate /* check if this is the end */ 21307c478bd9Sstevel@tonic-gate testw %ax, %ax 21317c478bd9Sstevel@tonic-gate jz 2f 21327c478bd9Sstevel@tonic-gate /* check if this matches the ascii code */ 21337c478bd9Sstevel@tonic-gate cmpb %al, %dl 21347c478bd9Sstevel@tonic-gate jne 1b 21357c478bd9Sstevel@tonic-gate /* if so, perform the mapping */ 21367c478bd9Sstevel@tonic-gate movb %ah, %dl 21377c478bd9Sstevel@tonic-gate2: 21387c478bd9Sstevel@tonic-gate /* restore %si */ 21397c478bd9Sstevel@tonic-gate popw %si 21407c478bd9Sstevel@tonic-gate 21417c478bd9Sstevel@tonic-gate ret 21427c478bd9Sstevel@tonic-gate 21437c478bd9Sstevel@tonic-gate .code32 21447c478bd9Sstevel@tonic-gate 21457c478bd9Sstevel@tonic-gate .align 4 21467c478bd9Sstevel@tonic-gateENTRY(ascii_key_map) 21477c478bd9Sstevel@tonic-gate .space (KEY_MAP_SIZE + 1) * 2 21487c478bd9Sstevel@tonic-gate 21497c478bd9Sstevel@tonic-gate 21507c478bd9Sstevel@tonic-gate/* 21517c478bd9Sstevel@tonic-gate * int console_getkey (void) 21527c478bd9Sstevel@tonic-gate * BIOS call "INT 16H Function 00H" to read character from keyboard 21537c478bd9Sstevel@tonic-gate * Call with %ah = 0x0 21547c478bd9Sstevel@tonic-gate * Return: %ah = keyboard scan code 21557c478bd9Sstevel@tonic-gate * %al = ASCII character 21567c478bd9Sstevel@tonic-gate */ 21577c478bd9Sstevel@tonic-gate 21587c478bd9Sstevel@tonic-gateENTRY(console_getkey) 21597c478bd9Sstevel@tonic-gate push %ebp 21607c478bd9Sstevel@tonic-gate 21616ee4b8d7Ssetjewait_for_key: 21626ee4b8d7Ssetje call EXT_C(console_checkkey) 2163c99350c4Ssetje incl %eax 2164c99350c4Ssetje jz wait_for_key 21656ee4b8d7Ssetje 21667c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 21677c478bd9Sstevel@tonic-gate .code16 21687c478bd9Sstevel@tonic-gate 21697c478bd9Sstevel@tonic-gate int $0x16 21707c478bd9Sstevel@tonic-gate 21717c478bd9Sstevel@tonic-gate movw %ax, %dx /* real_to_prot uses %eax */ 21727c478bd9Sstevel@tonic-gate call translate_keycode 21737c478bd9Sstevel@tonic-gate call remap_ascii_char 21747c478bd9Sstevel@tonic-gate 21757c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 21767c478bd9Sstevel@tonic-gate .code32 21777c478bd9Sstevel@tonic-gate 21787c478bd9Sstevel@tonic-gate movw %dx, %ax 21797c478bd9Sstevel@tonic-gate 21807c478bd9Sstevel@tonic-gate pop %ebp 21817c478bd9Sstevel@tonic-gate ret 21827c478bd9Sstevel@tonic-gate 21837c478bd9Sstevel@tonic-gate 21847c478bd9Sstevel@tonic-gate/* 21857c478bd9Sstevel@tonic-gate * int console_checkkey (void) 21867c478bd9Sstevel@tonic-gate * if there is a character pending, return it; otherwise return -1 21877c478bd9Sstevel@tonic-gate * BIOS call "INT 16H Function 01H" to check whether a character is pending 21887c478bd9Sstevel@tonic-gate * Call with %ah = 0x1 21897c478bd9Sstevel@tonic-gate * Return: 21907c478bd9Sstevel@tonic-gate * If key waiting to be input: 21917c478bd9Sstevel@tonic-gate * %ah = keyboard scan code 21927c478bd9Sstevel@tonic-gate * %al = ASCII character 21937c478bd9Sstevel@tonic-gate * Zero flag = clear 21947c478bd9Sstevel@tonic-gate * else 21957c478bd9Sstevel@tonic-gate * Zero flag = set 21967c478bd9Sstevel@tonic-gate */ 21977c478bd9Sstevel@tonic-gateENTRY(console_checkkey) 21987c478bd9Sstevel@tonic-gate push %ebp 21997c478bd9Sstevel@tonic-gate xorl %edx, %edx 22007c478bd9Sstevel@tonic-gate 22017c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) /* enter real mode */ 22027c478bd9Sstevel@tonic-gate .code16 22037c478bd9Sstevel@tonic-gate 22047c478bd9Sstevel@tonic-gate movb $0x1, %ah 22057c478bd9Sstevel@tonic-gate int $0x16 22067c478bd9Sstevel@tonic-gate 22077c478bd9Sstevel@tonic-gate DATA32 jz notpending 22087c478bd9Sstevel@tonic-gate 22097c478bd9Sstevel@tonic-gate movw %ax, %dx 22107c478bd9Sstevel@tonic-gate call translate_keycode 22117c478bd9Sstevel@tonic-gate call remap_ascii_char 22127c478bd9Sstevel@tonic-gate DATA32 jmp pending 22137c478bd9Sstevel@tonic-gate 22147c478bd9Sstevel@tonic-gatenotpending: 22157c478bd9Sstevel@tonic-gate movl $0xFFFFFFFF, %edx 22167c478bd9Sstevel@tonic-gate 22177c478bd9Sstevel@tonic-gatepending: 22187c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 22197c478bd9Sstevel@tonic-gate .code32 22207c478bd9Sstevel@tonic-gate 22217c478bd9Sstevel@tonic-gate mov %edx, %eax 22227c478bd9Sstevel@tonic-gate 22237c478bd9Sstevel@tonic-gate pop %ebp 22247c478bd9Sstevel@tonic-gate ret 22257c478bd9Sstevel@tonic-gate 22267c478bd9Sstevel@tonic-gate 22277c478bd9Sstevel@tonic-gate/* 22287c478bd9Sstevel@tonic-gate * int console_getxy (void) 22297c478bd9Sstevel@tonic-gate * BIOS call "INT 10H Function 03h" to get cursor position 22307c478bd9Sstevel@tonic-gate * Call with %ah = 0x03 22317c478bd9Sstevel@tonic-gate * %bh = page 22327c478bd9Sstevel@tonic-gate * Returns %ch = starting scan line 22337c478bd9Sstevel@tonic-gate * %cl = ending scan line 22347c478bd9Sstevel@tonic-gate * %dh = row (0 is top) 22357c478bd9Sstevel@tonic-gate * %dl = column (0 is left) 22367c478bd9Sstevel@tonic-gate */ 22377c478bd9Sstevel@tonic-gate 22387c478bd9Sstevel@tonic-gate 22397c478bd9Sstevel@tonic-gateENTRY(console_getxy) 22407c478bd9Sstevel@tonic-gate push %ebp 22417c478bd9Sstevel@tonic-gate push %ebx /* save EBX */ 22427c478bd9Sstevel@tonic-gate 22437c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 22447c478bd9Sstevel@tonic-gate .code16 22457c478bd9Sstevel@tonic-gate 22467c478bd9Sstevel@tonic-gate xorb %bh, %bh /* set page to 0 */ 22477c478bd9Sstevel@tonic-gate movb $0x3, %ah 22487c478bd9Sstevel@tonic-gate int $0x10 /* get cursor position */ 22497c478bd9Sstevel@tonic-gate 22507c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 22517c478bd9Sstevel@tonic-gate .code32 22527c478bd9Sstevel@tonic-gate 22537c478bd9Sstevel@tonic-gate movb %dl, %ah 22547c478bd9Sstevel@tonic-gate movb %dh, %al 22557c478bd9Sstevel@tonic-gate 22567c478bd9Sstevel@tonic-gate pop %ebx 22577c478bd9Sstevel@tonic-gate pop %ebp 22587c478bd9Sstevel@tonic-gate ret 22597c478bd9Sstevel@tonic-gate 22607c478bd9Sstevel@tonic-gate 22617c478bd9Sstevel@tonic-gate/* 22627c478bd9Sstevel@tonic-gate * void console_gotoxy(int x, int y) 22637c478bd9Sstevel@tonic-gate * BIOS call "INT 10H Function 02h" to set cursor position 22647c478bd9Sstevel@tonic-gate * Call with %ah = 0x02 22657c478bd9Sstevel@tonic-gate * %bh = page 22667c478bd9Sstevel@tonic-gate * %dh = row (0 is top) 22677c478bd9Sstevel@tonic-gate * %dl = column (0 is left) 22687c478bd9Sstevel@tonic-gate */ 22697c478bd9Sstevel@tonic-gate 22707c478bd9Sstevel@tonic-gate 22717c478bd9Sstevel@tonic-gateENTRY(console_gotoxy) 22727c478bd9Sstevel@tonic-gate push %ebp 22737c478bd9Sstevel@tonic-gate push %ebx /* save EBX */ 22747c478bd9Sstevel@tonic-gate 22757c478bd9Sstevel@tonic-gate movb 0xc(%esp), %dl /* %dl = x */ 22767c478bd9Sstevel@tonic-gate movb 0x10(%esp), %dh /* %dh = y */ 22777c478bd9Sstevel@tonic-gate 22787c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 22797c478bd9Sstevel@tonic-gate .code16 22807c478bd9Sstevel@tonic-gate 22817c478bd9Sstevel@tonic-gate xorb %bh, %bh /* set page to 0 */ 22827c478bd9Sstevel@tonic-gate movb $0x2, %ah 22837c478bd9Sstevel@tonic-gate int $0x10 /* set cursor position */ 22847c478bd9Sstevel@tonic-gate 22857c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 22867c478bd9Sstevel@tonic-gate .code32 22877c478bd9Sstevel@tonic-gate 22887c478bd9Sstevel@tonic-gate pop %ebx 22897c478bd9Sstevel@tonic-gate pop %ebp 22907c478bd9Sstevel@tonic-gate ret 22917c478bd9Sstevel@tonic-gate 22927c478bd9Sstevel@tonic-gate 22937c478bd9Sstevel@tonic-gate/* 22947c478bd9Sstevel@tonic-gate * void console_cls (void) 22957c478bd9Sstevel@tonic-gate * BIOS call "INT 10H Function 09h" to write character and attribute 22967c478bd9Sstevel@tonic-gate * Call with %ah = 0x09 22977c478bd9Sstevel@tonic-gate * %al = (character) 22987c478bd9Sstevel@tonic-gate * %bh = (page number) 22997c478bd9Sstevel@tonic-gate * %bl = (attribute) 23007c478bd9Sstevel@tonic-gate * %cx = (number of times) 23017c478bd9Sstevel@tonic-gate */ 23027c478bd9Sstevel@tonic-gate 23037c478bd9Sstevel@tonic-gate 23047c478bd9Sstevel@tonic-gateENTRY(console_cls) 23057c478bd9Sstevel@tonic-gate push %ebp 23067c478bd9Sstevel@tonic-gate push %ebx /* save EBX */ 23077c478bd9Sstevel@tonic-gate 23087c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 23097c478bd9Sstevel@tonic-gate .code16 23107c478bd9Sstevel@tonic-gate 23117c478bd9Sstevel@tonic-gate /* move the cursor to the beginning */ 23127c478bd9Sstevel@tonic-gate movb $0x02, %ah 23137c478bd9Sstevel@tonic-gate xorb %bh, %bh 23147c478bd9Sstevel@tonic-gate xorw %dx, %dx 23157c478bd9Sstevel@tonic-gate int $0x10 23167c478bd9Sstevel@tonic-gate 23177c478bd9Sstevel@tonic-gate /* write spaces to the entire screen */ 23187c478bd9Sstevel@tonic-gate movw $0x0920, %ax 23197c478bd9Sstevel@tonic-gate movw $0x07, %bx 23207c478bd9Sstevel@tonic-gate movw $(80 * 25), %cx 23217c478bd9Sstevel@tonic-gate int $0x10 23227c478bd9Sstevel@tonic-gate 23237c478bd9Sstevel@tonic-gate /* move back the cursor */ 23247c478bd9Sstevel@tonic-gate movb $0x02, %ah 23257c478bd9Sstevel@tonic-gate int $0x10 23267c478bd9Sstevel@tonic-gate 23277c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 23287c478bd9Sstevel@tonic-gate .code32 23297c478bd9Sstevel@tonic-gate 23307c478bd9Sstevel@tonic-gate pop %ebx 23317c478bd9Sstevel@tonic-gate pop %ebp 23327c478bd9Sstevel@tonic-gate ret 23337c478bd9Sstevel@tonic-gate 23347c478bd9Sstevel@tonic-gate 23357c478bd9Sstevel@tonic-gate/* 23367c478bd9Sstevel@tonic-gate * int console_setcursor (int on) 23377c478bd9Sstevel@tonic-gate * BIOS call "INT 10H Function 01h" to set cursor type 23387c478bd9Sstevel@tonic-gate * Call with %ah = 0x01 23397c478bd9Sstevel@tonic-gate * %ch = cursor starting scanline 23407c478bd9Sstevel@tonic-gate * %cl = cursor ending scanline 23417c478bd9Sstevel@tonic-gate */ 23427c478bd9Sstevel@tonic-gate 23437c478bd9Sstevel@tonic-gateconsole_cursor_state: 23447c478bd9Sstevel@tonic-gate .byte 1 23457c478bd9Sstevel@tonic-gateconsole_cursor_shape: 23467c478bd9Sstevel@tonic-gate .word 0 23477c478bd9Sstevel@tonic-gate 23487c478bd9Sstevel@tonic-gateENTRY(console_setcursor) 23497c478bd9Sstevel@tonic-gate push %ebp 23507c478bd9Sstevel@tonic-gate push %ebx 23517c478bd9Sstevel@tonic-gate 23527c478bd9Sstevel@tonic-gate /* check if the standard cursor shape has already been saved */ 23537c478bd9Sstevel@tonic-gate movw console_cursor_shape, %ax 23547c478bd9Sstevel@tonic-gate testw %ax, %ax 23557c478bd9Sstevel@tonic-gate jne 1f 23567c478bd9Sstevel@tonic-gate 23577c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 23587c478bd9Sstevel@tonic-gate .code16 23597c478bd9Sstevel@tonic-gate 23607c478bd9Sstevel@tonic-gate movb $0x03, %ah 23617c478bd9Sstevel@tonic-gate xorb %bh, %bh 23627c478bd9Sstevel@tonic-gate int $0x10 23637c478bd9Sstevel@tonic-gate 23647c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 23657c478bd9Sstevel@tonic-gate .code32 23667c478bd9Sstevel@tonic-gate 23677c478bd9Sstevel@tonic-gate movw %cx, console_cursor_shape 23687c478bd9Sstevel@tonic-gate1: 23697c478bd9Sstevel@tonic-gate /* set %cx to the designated cursor shape */ 23707c478bd9Sstevel@tonic-gate movw $0x2000, %cx 23717c478bd9Sstevel@tonic-gate movl 0xc(%esp), %ebx 23727c478bd9Sstevel@tonic-gate testl %ebx, %ebx 23737c478bd9Sstevel@tonic-gate jz 2f 23747c478bd9Sstevel@tonic-gate movw console_cursor_shape, %cx 23757c478bd9Sstevel@tonic-gate2: 23767c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 23777c478bd9Sstevel@tonic-gate .code16 23787c478bd9Sstevel@tonic-gate 23797c478bd9Sstevel@tonic-gate movb $0x1, %ah 23807c478bd9Sstevel@tonic-gate int $0x10 23817c478bd9Sstevel@tonic-gate 23827c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 23837c478bd9Sstevel@tonic-gate .code32 23847c478bd9Sstevel@tonic-gate 23857c478bd9Sstevel@tonic-gate movzbl console_cursor_state, %eax 23867c478bd9Sstevel@tonic-gate movb %bl, console_cursor_state 23877c478bd9Sstevel@tonic-gate 23887c478bd9Sstevel@tonic-gate pop %ebx 23897c478bd9Sstevel@tonic-gate pop %ebp 23907c478bd9Sstevel@tonic-gate ret 23917c478bd9Sstevel@tonic-gate 23927c478bd9Sstevel@tonic-gate/* graphics mode functions */ 23937c478bd9Sstevel@tonic-gate#ifdef SUPPORT_GRAPHICS 23947c478bd9Sstevel@tonic-gateVARIABLE(cursorX) 23957c478bd9Sstevel@tonic-gate.word 0 23967c478bd9Sstevel@tonic-gateVARIABLE(cursorY) 23977c478bd9Sstevel@tonic-gate.word 0 23987c478bd9Sstevel@tonic-gateVARIABLE(cursorCount) 23997c478bd9Sstevel@tonic-gate.word 0 24007c478bd9Sstevel@tonic-gateVARIABLE(cursorBuf) 24017c478bd9Sstevel@tonic-gate.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 24027c478bd9Sstevel@tonic-gate 24037c478bd9Sstevel@tonic-gate 24047c478bd9Sstevel@tonic-gate/* 24057c478bd9Sstevel@tonic-gate * int set_videomode(mode) 24067c478bd9Sstevel@tonic-gate * BIOS call "INT 10H Function 0h" to set video mode 24077c478bd9Sstevel@tonic-gate * Call with %ah = 0x0 24087c478bd9Sstevel@tonic-gate * %al = video mode 24097c478bd9Sstevel@tonic-gate * Returns old videomode. 24107c478bd9Sstevel@tonic-gate */ 24117c478bd9Sstevel@tonic-gateENTRY(set_videomode) 24127c478bd9Sstevel@tonic-gate push %ebp 24137c478bd9Sstevel@tonic-gate push %ebx 24147c478bd9Sstevel@tonic-gate push %ecx 24157c478bd9Sstevel@tonic-gate 24167c478bd9Sstevel@tonic-gate movb 0x10(%esp), %cl 24177c478bd9Sstevel@tonic-gate 24187c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 24197c478bd9Sstevel@tonic-gate .code16 24207c478bd9Sstevel@tonic-gate 24217c478bd9Sstevel@tonic-gate xorw %bx, %bx 24227c478bd9Sstevel@tonic-gate movb $0xf, %ah 24237c478bd9Sstevel@tonic-gate int $0x10 /* Get Current Video mode */ 24247c478bd9Sstevel@tonic-gate movb %al, %ch 24257c478bd9Sstevel@tonic-gate xorb %ah, %ah 24267c478bd9Sstevel@tonic-gate movb %cl, %al 24277c478bd9Sstevel@tonic-gate int $0x10 /* Set Video mode */ 24287c478bd9Sstevel@tonic-gate 24297c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 24307c478bd9Sstevel@tonic-gate .code32 24317c478bd9Sstevel@tonic-gate 24327c478bd9Sstevel@tonic-gate xorb %ah, %ah 24337c478bd9Sstevel@tonic-gate movb %ch, %al 24347c478bd9Sstevel@tonic-gate 24357c478bd9Sstevel@tonic-gate pop %ecx 24367c478bd9Sstevel@tonic-gate pop %ebx 24377c478bd9Sstevel@tonic-gate pop %ebp 24387c478bd9Sstevel@tonic-gate ret 24397c478bd9Sstevel@tonic-gate 24407c478bd9Sstevel@tonic-gate 24417c478bd9Sstevel@tonic-gate/* 24427c478bd9Sstevel@tonic-gate * unsigned char * graphics_get_font() 24437c478bd9Sstevel@tonic-gate * BIOS call "INT 10H Function 11h" to set font 24447c478bd9Sstevel@tonic-gate * Call with %ah = 0x11 24457c478bd9Sstevel@tonic-gate */ 24467c478bd9Sstevel@tonic-gateENTRY(graphics_get_font) 24477c478bd9Sstevel@tonic-gate push %ebp 24487c478bd9Sstevel@tonic-gate push %ebx 24497c478bd9Sstevel@tonic-gate push %ecx 24507c478bd9Sstevel@tonic-gate push %edx 24517c478bd9Sstevel@tonic-gate 24527c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 24537c478bd9Sstevel@tonic-gate .code16 24547c478bd9Sstevel@tonic-gate 24557c478bd9Sstevel@tonic-gate movw $0x1130, %ax 24567c478bd9Sstevel@tonic-gate movb $6, %bh /* font 8x16 */ 24577c478bd9Sstevel@tonic-gate int $0x10 24587c478bd9Sstevel@tonic-gate movw %bp, %dx 24597c478bd9Sstevel@tonic-gate movw %es, %cx 24607c478bd9Sstevel@tonic-gate 24617c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 24627c478bd9Sstevel@tonic-gate .code32 24637c478bd9Sstevel@tonic-gate 24647c478bd9Sstevel@tonic-gate xorl %eax, %eax 24657c478bd9Sstevel@tonic-gate movw %cx, %ax 24667c478bd9Sstevel@tonic-gate shll $4, %eax 24677c478bd9Sstevel@tonic-gate movw %dx, %ax 24687c478bd9Sstevel@tonic-gate 24697c478bd9Sstevel@tonic-gate pop %edx 24707c478bd9Sstevel@tonic-gate pop %ecx 24717c478bd9Sstevel@tonic-gate pop %ebx 24727c478bd9Sstevel@tonic-gate pop %ebp 24737c478bd9Sstevel@tonic-gate ret 24747c478bd9Sstevel@tonic-gate 24757c478bd9Sstevel@tonic-gate 24767c478bd9Sstevel@tonic-gate 24777c478bd9Sstevel@tonic-gate/* 24787c478bd9Sstevel@tonic-gate * graphics_set_palette(index, red, green, blue) 24797c478bd9Sstevel@tonic-gate * BIOS call "INT 10H Function 10h" to set individual dac register 24807c478bd9Sstevel@tonic-gate * Call with %ah = 0x10 24817c478bd9Sstevel@tonic-gate * %bx = register number 24827c478bd9Sstevel@tonic-gate * %ch = new value for green (0-63) 24837c478bd9Sstevel@tonic-gate * %cl = new value for blue (0-63) 24847c478bd9Sstevel@tonic-gate * %dh = new value for red (0-63) 24857c478bd9Sstevel@tonic-gate */ 24867c478bd9Sstevel@tonic-gate 24877c478bd9Sstevel@tonic-gateENTRY(graphics_set_palette) 24887c478bd9Sstevel@tonic-gate push %ebp 24897c478bd9Sstevel@tonic-gate push %eax 24907c478bd9Sstevel@tonic-gate push %ebx 24917c478bd9Sstevel@tonic-gate push %ecx 24927c478bd9Sstevel@tonic-gate push %edx 24937c478bd9Sstevel@tonic-gate 24947c478bd9Sstevel@tonic-gate movw $0x3c8, %bx /* address write mode register */ 24957c478bd9Sstevel@tonic-gate 24967c478bd9Sstevel@tonic-gate /* wait vertical retrace */ 24977c478bd9Sstevel@tonic-gate 24987c478bd9Sstevel@tonic-gate movw $0x3da, %dx 24997c478bd9Sstevel@tonic-gatel1b: inb %dx, %al /* wait vertical active display */ 25007c478bd9Sstevel@tonic-gate test $8, %al 25017c478bd9Sstevel@tonic-gate jnz l1b 25027c478bd9Sstevel@tonic-gate 25037c478bd9Sstevel@tonic-gatel2b: inb %dx, %al /* wait vertical retrace */ 25047c478bd9Sstevel@tonic-gate test $8, %al 25057c478bd9Sstevel@tonic-gate jnz l2b 25067c478bd9Sstevel@tonic-gate 25077c478bd9Sstevel@tonic-gate mov %bx, %dx 25087c478bd9Sstevel@tonic-gate movb 0x18(%esp), %al /* index */ 25097c478bd9Sstevel@tonic-gate outb %al, %dx 25107c478bd9Sstevel@tonic-gate inc %dx 25117c478bd9Sstevel@tonic-gate 25127c478bd9Sstevel@tonic-gate movb 0x1c(%esp), %al /* red */ 25137c478bd9Sstevel@tonic-gate outb %al, %dx 25147c478bd9Sstevel@tonic-gate 25157c478bd9Sstevel@tonic-gate movb 0x20(%esp), %al /* green */ 25167c478bd9Sstevel@tonic-gate outb %al, %dx 25177c478bd9Sstevel@tonic-gate 25187c478bd9Sstevel@tonic-gate movb 0x24(%esp), %al /* blue */ 25197c478bd9Sstevel@tonic-gate outb %al, %dx 25207c478bd9Sstevel@tonic-gate 25217c478bd9Sstevel@tonic-gate movw 0x18(%esp), %bx 25227c478bd9Sstevel@tonic-gate 25237c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) 25247c478bd9Sstevel@tonic-gate .code16 25257c478bd9Sstevel@tonic-gate 25267c478bd9Sstevel@tonic-gate movb %bl, %bh 25277c478bd9Sstevel@tonic-gate movw $0x1000, %ax 25287c478bd9Sstevel@tonic-gate int $0x10 25297c478bd9Sstevel@tonic-gate 25307c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 25317c478bd9Sstevel@tonic-gate .code32 25327c478bd9Sstevel@tonic-gate 25337c478bd9Sstevel@tonic-gate pop %edx 25347c478bd9Sstevel@tonic-gate pop %ecx 25357c478bd9Sstevel@tonic-gate pop %ebx 25367c478bd9Sstevel@tonic-gate pop %eax 25377c478bd9Sstevel@tonic-gate pop %ebp 25387c478bd9Sstevel@tonic-gate ret 25397c478bd9Sstevel@tonic-gate 25407c478bd9Sstevel@tonic-gate#endif /* SUPPORT_GRAPHICS */ 25417c478bd9Sstevel@tonic-gate 25427c478bd9Sstevel@tonic-gate/* 25437c478bd9Sstevel@tonic-gate * getrtsecs() 25447c478bd9Sstevel@tonic-gate * if a seconds value can be read, read it and return it (BCD), 25457c478bd9Sstevel@tonic-gate * otherwise return 0xFF 25467c478bd9Sstevel@tonic-gate * BIOS call "INT 1AH Function 02H" to check whether a character is pending 25477c478bd9Sstevel@tonic-gate * Call with %ah = 0x2 25487c478bd9Sstevel@tonic-gate * Return: 25497c478bd9Sstevel@tonic-gate * If RT Clock can give correct values 25507c478bd9Sstevel@tonic-gate * %ch = hour (BCD) 25517c478bd9Sstevel@tonic-gate * %cl = minutes (BCD) 25527c478bd9Sstevel@tonic-gate * %dh = seconds (BCD) 25537c478bd9Sstevel@tonic-gate * %dl = daylight savings time (00h std, 01h daylight) 25547c478bd9Sstevel@tonic-gate * Carry flag = clear 25557c478bd9Sstevel@tonic-gate * else 25567c478bd9Sstevel@tonic-gate * Carry flag = set 25577c478bd9Sstevel@tonic-gate * (this indicates that the clock is updating, or 25587c478bd9Sstevel@tonic-gate * that it isn't running) 25597c478bd9Sstevel@tonic-gate */ 25607c478bd9Sstevel@tonic-gateENTRY(getrtsecs) 25617c478bd9Sstevel@tonic-gate push %ebp 25627c478bd9Sstevel@tonic-gate 25637c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) /* enter real mode */ 25647c478bd9Sstevel@tonic-gate .code16 25657c478bd9Sstevel@tonic-gate 25667c478bd9Sstevel@tonic-gate movb $0x2, %ah 25677c478bd9Sstevel@tonic-gate int $0x1a 25687c478bd9Sstevel@tonic-gate 25697c478bd9Sstevel@tonic-gate DATA32 jnc gottime 25707c478bd9Sstevel@tonic-gate movb $0xff, %dh 25717c478bd9Sstevel@tonic-gate 25727c478bd9Sstevel@tonic-gategottime: 25737c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 25747c478bd9Sstevel@tonic-gate .code32 25757c478bd9Sstevel@tonic-gate 25767c478bd9Sstevel@tonic-gate movb %dh, %al 25777c478bd9Sstevel@tonic-gate 25787c478bd9Sstevel@tonic-gate pop %ebp 25797c478bd9Sstevel@tonic-gate ret 25807c478bd9Sstevel@tonic-gate 25817c478bd9Sstevel@tonic-gate 25827c478bd9Sstevel@tonic-gate/* 25837c478bd9Sstevel@tonic-gate * currticks() 25847c478bd9Sstevel@tonic-gate * return the real time in ticks, of which there are about 25857c478bd9Sstevel@tonic-gate * 18-20 per second 25867c478bd9Sstevel@tonic-gate */ 25877c478bd9Sstevel@tonic-gateENTRY(currticks) 25887c478bd9Sstevel@tonic-gate pushl %ebp 25897c478bd9Sstevel@tonic-gate 25907c478bd9Sstevel@tonic-gate call EXT_C(prot_to_real) /* enter real mode */ 25917c478bd9Sstevel@tonic-gate .code16 25927c478bd9Sstevel@tonic-gate 25937c478bd9Sstevel@tonic-gate /* %ax is already zero */ 25947c478bd9Sstevel@tonic-gate int $0x1a 25957c478bd9Sstevel@tonic-gate 25967c478bd9Sstevel@tonic-gate DATA32 call EXT_C(real_to_prot) 25977c478bd9Sstevel@tonic-gate .code32 25987c478bd9Sstevel@tonic-gate 25997c478bd9Sstevel@tonic-gate movl %ecx, %eax 26007c478bd9Sstevel@tonic-gate shll $16, %eax 26017c478bd9Sstevel@tonic-gate movw %dx, %ax 26027c478bd9Sstevel@tonic-gate 26037c478bd9Sstevel@tonic-gate popl %ebp 26047c478bd9Sstevel@tonic-gate ret 26057c478bd9Sstevel@tonic-gate 2606ae115bc7SmrjENTRY(amd64_rdmsr) 2607ae115bc7Smrj movl 4(%esp), %ecx 2608ae115bc7Smrj rdmsr 2609ae115bc7Smrj movl 8(%esp), %ecx 2610ae115bc7Smrj movl %eax, (%ecx) 2611ae115bc7Smrj movl %edx, 4(%ecx) 2612ae115bc7Smrj ret 2613ae115bc7Smrj 2614ae115bc7SmrjENTRY(amd64_wrmsr) 2615ae115bc7Smrj movl 8(%esp), %ecx 2616ae115bc7Smrj movl (%ecx), %eax 2617ae115bc7Smrj movl 4(%ecx), %edx 2618ae115bc7Smrj movl 4(%esp), %ecx 2619ae115bc7Smrj wrmsr 2620ae115bc7Smrj ret 2621ae115bc7Smrj 2622ae115bc7SmrjENTRY(amd64_cpuid_insn) 2623ae115bc7Smrj pushl %ebp 2624ae115bc7Smrj movl %esp, %ebp 2625ae115bc7Smrj pushl %ebx 2626ae115bc7Smrj pushl %esi 2627ae115bc7Smrj movl 0x8(%ebp), %eax 2628ae115bc7Smrj movl 0xc(%ebp), %esi 2629ae115bc7Smrj cpuid 2630ae115bc7Smrj movl %eax, 0x0(%esi) 2631ae115bc7Smrj movl %ebx, 0x4(%esi) 2632ae115bc7Smrj movl %ecx, 0x8(%esi) 2633ae115bc7Smrj movl %edx, 0xc(%esi) 2634ae115bc7Smrj popl %esi 2635ae115bc7Smrj popl %ebx 2636ae115bc7Smrj popl %ebp 2637ae115bc7Smrj ret 2638ae115bc7Smrj 2639ae115bc7Smrj /* 2640ae115bc7Smrj * Based on code from AMD64 Volume 3 2641ae115bc7Smrj */ 2642ae115bc7SmrjENTRY(amd64_cpuid_supported) 2643ae115bc7Smrj pushf 2644ae115bc7Smrj popl %eax 2645ae115bc7Smrj mov %eax, %edx /* save %eax for later */ 2646ae115bc7Smrj xorl %eax, 0x200000 /* toggle bit 21 */ 2647ae115bc7Smrj pushl %eax 2648ae115bc7Smrj popf /* save new %eax to EFLAGS */ 2649ae115bc7Smrj pushf /* save new EFLAGS */ 2650ae115bc7Smrj popl %ecx /* copy EFLAGS to %eax */ 2651ae115bc7Smrj xorl %eax, %eax 2652ae115bc7Smrj cmpl %ecx, %edx /* see if bit 21 has changes */ 2653ae115bc7Smrj jne 1f 2654ae115bc7Smrj incl %eax 2655ae115bc7Smrj1: 2656ae115bc7Smrj ret 2657ae115bc7Smrj 2658ae115bc7SmrjENTRY(get_target_operating_mode) 2659ae115bc7Smrj pusha 2660ae115bc7Smrj 2661ae115bc7Smrj call EXT_C(prot_to_real) 2662ae115bc7Smrj .code16 2663ae115bc7Smrj 2664ae115bc7Smrj movw $0xec00, %ax 2665ae115bc7Smrj movw $0x03, %bx 2666ae115bc7Smrj int $0x15 2667ae115bc7Smrj/* XXX still need to pass back return */ 2668ae115bc7Smrj 2669ae115bc7Smrj movw %ax, %cx 2670ae115bc7Smrj 2671ae115bc7Smrj DATA32 call EXT_C(real_to_prot) 2672ae115bc7Smrj .code32 2673ae115bc7Smrj 2674ae115bc7Smrj xorl %eax, %eax 2675ae115bc7Smrj movw %cx, %ax 2676ae115bc7Smrj 2677ae115bc7Smrj popa 2678ae115bc7Smrj ret 2679ae115bc7Smrj 2680ae115bc7Smrj#endif /* ! STAGE1_5 */ 26817c478bd9Sstevel@tonic-gate 26827c478bd9Sstevel@tonic-gate/* 26837c478bd9Sstevel@tonic-gate * This is the area for all of the special variables. 26847c478bd9Sstevel@tonic-gate */ 26857c478bd9Sstevel@tonic-gate 26867c478bd9Sstevel@tonic-gate .p2align 2 /* force 4-byte alignment */ 26877c478bd9Sstevel@tonic-gate 26887c478bd9Sstevel@tonic-gateprotstack: 26897c478bd9Sstevel@tonic-gate .long PROTSTACKINIT 26907c478bd9Sstevel@tonic-gate 26917c478bd9Sstevel@tonic-gateVARIABLE(boot_drive) 26927c478bd9Sstevel@tonic-gate#ifdef SUPPORT_DISKLESS 26937c478bd9Sstevel@tonic-gate .long NETWORK_DRIVE 26947c478bd9Sstevel@tonic-gate#else 26957c478bd9Sstevel@tonic-gate .long 0 26967c478bd9Sstevel@tonic-gate#endif 26977c478bd9Sstevel@tonic-gate 26987c478bd9Sstevel@tonic-gateVARIABLE(install_second_sector) 26997c478bd9Sstevel@tonic-gate .long 0 27007c478bd9Sstevel@tonic-gate 27017c478bd9Sstevel@tonic-gate /* an address can only be long-jumped to if it is in memory, this 27027c478bd9Sstevel@tonic-gate is used by multiple routines */ 27037c478bd9Sstevel@tonic-gateoffset: 27047c478bd9Sstevel@tonic-gate .long 0x8000 27057c478bd9Sstevel@tonic-gatesegment: 27067c478bd9Sstevel@tonic-gate .word 0 27077c478bd9Sstevel@tonic-gate 27087c478bd9Sstevel@tonic-gateVARIABLE(apm_bios_info) 27097c478bd9Sstevel@tonic-gate .word 0 /* version */ 27107c478bd9Sstevel@tonic-gate .word 0 /* cseg */ 27117c478bd9Sstevel@tonic-gate .long 0 /* offset */ 27127c478bd9Sstevel@tonic-gate .word 0 /* cseg_16 */ 27137c478bd9Sstevel@tonic-gate .word 0 /* dseg_16 */ 27147c478bd9Sstevel@tonic-gate .word 0 /* cseg_len */ 27157c478bd9Sstevel@tonic-gate .word 0 /* cseg_16_len */ 27167c478bd9Sstevel@tonic-gate .word 0 /* dseg_16_len */ 27177c478bd9Sstevel@tonic-gate 27187c478bd9Sstevel@tonic-gate/* 27197c478bd9Sstevel@tonic-gate * This is the Global Descriptor Table 27207c478bd9Sstevel@tonic-gate * 27217c478bd9Sstevel@tonic-gate * An entry, a "Segment Descriptor", looks like this: 27227c478bd9Sstevel@tonic-gate * 27237c478bd9Sstevel@tonic-gate * 31 24 19 16 7 0 27247c478bd9Sstevel@tonic-gate * ------------------------------------------------------------ 27257c478bd9Sstevel@tonic-gate * | | |B| |A| | | |1|0|E|W|A| | 27267c478bd9Sstevel@tonic-gate * | BASE 31..24 |G|/|0|V| LIMIT |P|DPL| TYPE | BASE 23:16 | 27277c478bd9Sstevel@tonic-gate * | | |D| |L| 19..16| | |1|1|C|R|A| | 27287c478bd9Sstevel@tonic-gate * ------------------------------------------------------------ 27297c478bd9Sstevel@tonic-gate * | | | 27307c478bd9Sstevel@tonic-gate * | BASE 15..0 | LIMIT 15..0 | 27317c478bd9Sstevel@tonic-gate * | | | 27327c478bd9Sstevel@tonic-gate * ------------------------------------------------------------ 27337c478bd9Sstevel@tonic-gate * 27347c478bd9Sstevel@tonic-gate * Note the ordering of the data items is reversed from the above 27357c478bd9Sstevel@tonic-gate * description. 27367c478bd9Sstevel@tonic-gate */ 27377c478bd9Sstevel@tonic-gate 27387c478bd9Sstevel@tonic-gate .p2align 2 /* force 4-byte alignment */ 27397c478bd9Sstevel@tonic-gategdt: 27407c478bd9Sstevel@tonic-gate .word 0, 0 27417c478bd9Sstevel@tonic-gate .byte 0, 0, 0, 0 27427c478bd9Sstevel@tonic-gate 27437c478bd9Sstevel@tonic-gate /* code segment */ 27447c478bd9Sstevel@tonic-gate .word 0xFFFF, 0 27457c478bd9Sstevel@tonic-gate .byte 0, 0x9A, 0xCF, 0 27467c478bd9Sstevel@tonic-gate 27477c478bd9Sstevel@tonic-gate /* data segment */ 27487c478bd9Sstevel@tonic-gate .word 0xFFFF, 0 27497c478bd9Sstevel@tonic-gate .byte 0, 0x92, 0xCF, 0 27507c478bd9Sstevel@tonic-gate 27517c478bd9Sstevel@tonic-gate /* 16 bit real mode CS */ 27527c478bd9Sstevel@tonic-gate .word 0xFFFF, 0 27537c478bd9Sstevel@tonic-gate .byte 0, 0x9E, 0, 0 27547c478bd9Sstevel@tonic-gate 27557c478bd9Sstevel@tonic-gate /* 16 bit real mode DS */ 27567c478bd9Sstevel@tonic-gate .word 0xFFFF, 0 27577c478bd9Sstevel@tonic-gate .byte 0, 0x92, 0, 0 27587c478bd9Sstevel@tonic-gate 27597c478bd9Sstevel@tonic-gate 27607c478bd9Sstevel@tonic-gate/* this is the GDT descriptor */ 27617c478bd9Sstevel@tonic-gategdtdesc: 27627c478bd9Sstevel@tonic-gate .word 0x27 /* limit */ 27637c478bd9Sstevel@tonic-gate .long gdt /* addr */ 2764