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 111af28f636SEnrico Perla - Sun Microsystems . = EXT_C(main) + 0x60 112af28f636SEnrico Perla - Sun MicrosystemsVARIABLE(fake_mboot) 113af28f636SEnrico Perla - Sun Microsystems .long 0x1BADB002 114af28f636SEnrico Perla - Sun Microsystems .long 0x00010003 115af28f636SEnrico Perla - Sun Microsystems .long -0x1BAEB005 1167ce76caaSEnrico Perla - Sun Microsystems /* 117af28f636SEnrico Perla - Sun Microsystems * installgrub will place the rest of the fake 118af28f636SEnrico Perla - Sun Microsystems * multiboot header here. 1197ce76caaSEnrico Perla - Sun Microsystems */ 120af28f636SEnrico 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