]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/boot/pc/l.s
9boot: replace strrchr() call with a loop and strchr() for ignoring bang path prefixes
[plan9front.git] / sys / src / boot / pc / l.s
old mode 100755 (executable)
new mode 100644 (file)
index 4216bfe..0858288
 #include "x16.h"
 #include "mem.h"
 
-#define WRMSR          BYTE $0x0F; BYTE $0x30  /* WRMSR, argument in AX/DX (lo/hi) */
-#define RDTSC          BYTE $0x0F; BYTE $0x31  /* RDTSC, result in AX/DX (lo/hi) */
-#define RDMSR          BYTE $0x0F; BYTE $0x32  /* RDMSR, result in AX/DX (lo/hi) */
+#undef ORB
 
-#ifdef PXE
-#define PDB            0x90000         /* temporary page tables (24KB) */
-#else
-#define PDB            0x08000
-#endif PXE
+#define DATA32SEL SELECTOR(1, SELGDT, 0)
+#define EXEC32SEL SELECTOR(2, SELGDT, 0)
+#define DATA16SEL SELECTOR(3, SELGDT, 0)
+#define EXEC16SEL SELECTOR(4, SELGDT, 0)
 
-/*#define VGA          1 */
-#define NoScreenBlank  1
-/*#define ResetDiscs   1*/
+#define SEGSS BYTE $0x36
+#define SEGES BYTE $0x26
+#define FARRET BYTE $0xCB
 
 TEXT origin(SB), $0
-       /*
-        * This part of l.s is used only in the boot kernel.
-        * It assumes that we are in real address mode, i.e.,
-        * that we look like an 8086.
-        *
-        * Make sure the segments are reasonable.
-        * If we were started directly from the BIOS
-        * (i.e. no MS-DOS) then DS may not be
-        * right.
-        */
-       MOVW    CS, AX
-       MOVW    AX, DS
-
-#ifdef VGA
-#ifdef NoScreenBlank
-       /*
-        * Get the current video mode. If it isn't mode 3,
-        * set text mode 3.
-        * Well, no. Windows95 won't co-operate here so we have
-        * to explicitly set mode 3.
-        */
-       XORL    AX, AX
-       MOVB    $0x0F, AH
-       INT     $0x10                   /* get current video mode in AL */
-       CMPB    AL, $03
-       JEQ     sayhello
-#endif /* NoScreenBlank */
-       XORL    AX, AX
-       MOVB    $0x03, AL
-       INT     $0x10                   /* set video mode in AL */
-
-sayhello:
-       LWI(hello(SB), rSI)
-       CALL16(biosputs(SB))
-#endif /* VGA */
-#ifdef ResetDiscs
-       XORL    AX, AX                  /* reset disc system */
-       XORL    DX, DX
-       MOVB    $0x80, DL
-       INT     $0x13
-#endif /* ResetDiscs */
-
-#ifdef DOTCOM
-/*
- *     relocate everything to a half meg and jump there
- *     - looks weird because it is being assembled by a 32 bit
- *       assembler for a 16 bit world
- *
- *     only b.com does this - not 9load
- */
-       MOVL    $0,BX
-       INCL    BX
-       SHLL    $15,BX
-       MOVL    BX,CX
-       MOVW    BX,ES
-       MOVL    $0,SI
-       MOVL    SI,DI
-       CLD
-       REP
-       MOVSL
-
-       /*
-        * Jump to the copied image;
-        * fix up the DS for the new location.
-        */
-       FARJUMP16(0x8000, _start8000(SB))
-
-TEXT _start8000(SB), $0
-       MFSR(rCS, rAX)                  /* fix up DS, ES (0x8000) */
-       MTSR(rAX, rDS)
-       MTSR(rAX, rES)
-
-       /*
-        * If we are already in protected mode, have to get back
-        * to real mode before trying any privileged operations
-        * (like going into protected mode...).
-        * Try to reset with a restart vector.
-        */
-       MFCR(rCR0, rAX)                 /* are we in protected mode? */
-       ANDI(0x0001, rAX)
-       JEQ     _real
-
-       CLR(rBX)
-       MTSR(rBX, rES)
-
-       LWI(0x0467, rBX)                /* reset entry point */
-       LWI(_start8000(SB), rAX)        /* offset within segment */
-       BYTE    $0x26
-       BYTE    $0x89
-       BYTE    $0x07                   /* MOVW AX, ES:[BX] */
-       LBI(0x69, rBL)
-       MFSR(rCS, rAX)                  /* segment */
-       BYTE    $0x26
-       BYTE    $0x89
-       BYTE    $0x07                   /* MOVW AX, ES:[BX] */
-
-       CLR(rDX)
-       OUTPORTB(0x70, 0x8F)
-       OUTPORTB(0x71, 0x0A)
-
-       FARJUMP16(0xFFFF, 0x0000)               /* reset */
-#endif /* DOTCOM */
-
-_real:
-
-/*
- *     do things that need to be done in real mode.
- *     the results get written to CONFADDR (0x1200)
- *     in a series of <4-byte-magic-number><block-of-data>
- *     the data length is dependent on the magic number.
- *
- *     this gets parsed by conf.c:/^readlsconf
- *
- *     N.B. CALL16 kills rDI, so we can't call anything.
- */
-       LWI(0x0000, rAX)
-       MTSR(rAX, rES)
-       LWI(0x1200, rDI)
-
-/*
- *     turn off interrupts
- */
        CLI
+       CLR(rCX)
+       MTSR(rCX, rSS)
+       OPSIZE; MOVL $origin(SB), SP
+       PUSHA
+       OPSIZE; ADSIZE; PUSHL SP
+       OPSIZE; ADSIZE; PUSHL CX
+       PUSHI(start(SB))
 
-/*
- *     detect APM1.2 bios support
- */
-       /* save DI */
-       SW(rDI, rock(SB))
-
-       /* disconnect anyone else */
-       LWI(0x5304, rAX)
-       LWI(0x0000, rBX)
-       INT $0x15
+TEXT pmode32(SB), $0
+       CLI
 
-       /* connect */
-       CLC
-       LWI(0x5303, rAX)
-       LWI(0x0000, rBX)
-       INT $0x15
-       CLI     /* apm put interrupts back? */
+       /* get return pc */
+       POPR(rDI)
 
-       JC noapm
+       /* make sure stack is at 0000: */
+       CLR(rCX)
+       MTSR(rCX, rSS)
+       OPSIZE; ANDL $0xFFFF, SP
 
-       OPSIZE; PUSHR(rSI)
-       OPSIZE; PUSHR(rBX)
+       /* convert 16-bit return pc to far pointer */
+       PUSHI(EXEC32SEL)
        PUSHR(rDI)
-       PUSHR(rDX)
-       PUSHR(rCX)
-       PUSHR(rAX)
-
-       /* put DI, ES back */
-       LW(rock(SB), rDI)
-       LWI(0x0000, rAX)
-       MTSR(rAX, rES)
-
-       /*
-        * write APM data.  first four bytes are APM\0.
-        */
-       LWI(0x5041, rAX)
-       STOSW
-
-       LWI(0x004d, rAX)
-       STOSW
-
-       LWI(8, rCX)
-apmmove:
-       POPR(rAX)
-       STOSW
-       LOOP apmmove
-
-noapm:
-
-/*
- *     end of real mode hacks: write terminator, put ES back.
- */
-       LWI(0x0000, rAX)
-       STOSW
-       STOSW
-
-       MFSR(rCS, rAX)                  /* fix up ES (0x8000) */
-       MTSR(rAX, rES)
-
-/*
- *     goto protected mode
- */
-/*     MOVL    tgdtptr(SB),GDTR /**/
-        BYTE   $0x0f
-        BYTE   $0x01
-        BYTE   $0x16
-        WORD   $tgdtptr(SB)
-
-       LWI(1, rAX)
-       /* MOV AX,MSW */
-       BYTE $0x0F; BYTE $0x01; BYTE $0xF0
-
-/*
- *     clear prefetch queue (weird code to avoid optimizations)
- */
-       /* JMP .+2 */
-       BYTE $0xEB
-       BYTE $0x00
-
-/*
- *     set all segs
- */
-/*     MOVW    $SELECTOR(1, SELGDT, 0),AX      /**/
-        BYTE   $0xc7
-        BYTE   $0xc0
-        WORD   $SELECTOR(1, SELGDT, 0)
-       MOVW    AX,DS
-       MOVW    AX,SS
-       MOVW    AX,ES
-       MOVW    AX,FS
-       MOVW    AX,GS
-
-/*     JMPFAR  SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/
-        BYTE   $0x66
-        BYTE   $0xEA
-        LONG   $mode32bit-KZERO(SB)
-        WORD   $SELECTOR(2, SELGDT, 0)
-
-TEXT   mode32bit(SB),$0
-       /*
-        *  make a bottom level page table page that maps the first
-        *  16 meg of physical memory
-        */
-       MOVL    $PDB, DI                        /* clear 6 pages for the tables etc. */
-       XORL    AX, AX
-       MOVL    $(6*BY2PG), CX
-       SHRL    $2, CX
-
-       CLD
-       REP;    STOSL
-
-       MOVL    $PDB, AX                /* phys addr of temporary page table */
-       MOVL    $(4*1024),CX            /* pte's per page */
-       MOVL    $((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
-setpte:
-       MOVL    BX,-4(AX)(CX*4)
-       SUBL    $(1<<PGSHIFT),BX
-       LOOP    setpte
-
-       /*
-        *  make a top level page table page that maps the first
-        *  16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg
-        */
-       MOVL    AX,BX
-       ADDL    $(4*BY2PG),AX
-       ADDL    $(PTEVALID|PTEKERNEL|PTEWRITE),BX
-       MOVL    BX,0(AX)
-       MOVL    BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)
-       ADDL    $BY2PG,BX
-       MOVL    BX,4(AX)
-       MOVL    BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX)
-       ADDL    $BY2PG,BX
-       MOVL    BX,8(AX)
-       MOVL    BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX)
-       ADDL    $BY2PG,BX
-       MOVL    BX,12(AX)
-       MOVL    BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX)
-
-       /*
-        *  point processor to top level page & turn on paging
-        *
-        *  this produces the apparently harmless "VMX|F(125):468 Dis 0x0:0x0"
-        *  message in the VMware log.
-        */
-       MOVL    AX,CR3
-       MOVL    CR0,AX
-       ORL     $0X80000000,AX
-       MOVL    AX,CR0
-
-       /*
-        *  use a jump to an absolute location to get the PC into
-        *  KZERO.
-        */
-       LEAL    tokzero(SB),AX
-       JMP*    AX
-
-/*
- * When we load 9load from DOS, the bootstrap jumps
- * to the instruction right after `JUMP', which gets
- * us into kzero.
- *
- * The name prevents it from being optimized away.
- */
-TEXT jumplabel(SB), $0
-       BYTE $'J'; BYTE $'U'; BYTE $'M'; BYTE $'P'
 
-       LEAL    tokzero(SB),AX
-       JMP*    AX
+       /* load gdt */
+       SEGSS; LGDT(tgdtptr(SB))
+
+       /* enable protected mode */
+       MFCR(rCR0, rCX)
+       ORB $1, CL
+       MTCR(rCX, rCR0)
+
+       /* flush */
+       FARJUMP16(EXEC16SEL, pmode32flush(SB));
+TEXT pmode32flush(SB), $0
+
+       /* load 32-bit protected mode data selector */
+       LWI(DATA32SEL, rCX)
+
+_segret:
+       /* load all data segments */
+       MTSR(rCX, rDS)
+       MTSR(rCX, rES)
+       MTSR(rCX, rFS)
+       MTSR(rCX, rGS)
+       MTSR(rCX, rSS)
+       FARRET
+
+TEXT rmode16(SB), $0
+       /* setup farret to rmode16x */
+       PUSHL $EXEC16SEL
+       PUSHL $rmode16x(SB)
+
+       /* load 16-bit protected mode data selector */
+       MOVL $DATA16SEL, CX
+       JMP _segret
+
+TEXT rmode16x(SB), $0
+       /* disable protected mode */
+       MFCR(rCR0, rCX)
+       ANDB $0xfe, CL
+       MTCR(rCX, rCR0)
+
+       /* flush */
+       FARJUMP16(0, rmode16flush(SB));
+TEXT rmode16flush(SB), $0
 
-TEXT   tokzero(SB),$0
        /*
-        * Clear BSS
+        * load 16-bit realmode data segment 0000: and
+        * return to 32 bit return pc interpreted
+        * as 16 bit far pointer.
         */
-       LEAL    edata(SB),SI
-       MOVL    SI,DI
-       ADDL    $4,DI
-       MOVL    $0,AX
-       MOVL    AX,(SI)
-       LEAL    end(SB),CX
-       SUBL    DI,CX
-       SHRL    $2,CX
-       CLD
-       REP
-       MOVSL
-
-       /*
-        *  stack and mach
-        */
-       MOVL    $mach0(SB),SP
-       MOVL    SP,m(SB)
-       MOVL    $0,0(SP)
-       ADDL    $(MACHSIZE-4),SP        /* start stack above machine struct */
-
-       CALL    main(SB)
-
-loop:
-       JMP     loop
-
-GLOBL  mach0+0(SB), $MACHSIZE
-GLOBL  m(SB), $4
-
-/*
- *  gdt to get us to 32-bit/segmented/unpaged mode
- */
-TEXT   tgdt(SB),$0
+       CLR(rCX)
+       JMP _segret
 
+TEXT tgdt(SB), $0 
        /* null descriptor */
-       LONG    $0
-       LONG    $0
+       LONG $0
+       LONG $0
 
        /* data segment descriptor for 4 gigabytes (PL 0) */
-       LONG    $(0xFFFF)
-       LONG    $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
+       LONG $(0xFFFF)
+       LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
 
        /* exec segment descriptor for 4 gigabytes (PL 0) */
-       LONG    $(0xFFFF)
-       LONG    $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
-
-       /* exec segment descriptor for 4 gigabytes (PL 0) 16-bit */
-       LONG    $(0xFFFF)
-       LONG    $(SEGG|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
-
-/*
- *  pointer to initial gdt
- */
-TEXT   tgdtptr(SB),$0
-       WORD    $(4*8)
-       LONG    $tgdt-KZERO(SB)
-
-/*
- * Output a string to the display.
- * String argument is in rSI.
- */
-TEXT biosputs(SB), $0
-       PUSHA
-       CLR(rBX)
-_BIOSputs:
-       LODSB
-       ORB(rAL, rAL)
-       JEQ _BIOSputsret
-
-       LBI(0x0E, rAH)
-       BIOSCALL(0x10)
-       JMP _BIOSputs
-
-_BIOSputsret:
-       POPA
-       RET
-
-/*
- *  input a byte
- */
-TEXT   inb(SB),$0
-
-       MOVL    p+0(FP),DX
-       XORL    AX,AX
-       INB
-       RET
-
-/*
- * input a short from a port
- */
-TEXT   ins(SB), $0
-
-       MOVL    p+0(FP), DX
-       XORL    AX, AX
-       OPSIZE; INL
-       RET
-
-/*
- * input a long from a port
- */
-TEXT   inl(SB), $0
-
-       MOVL    p+0(FP), DX
-       XORL    AX, AX
-       INL
-       RET
-
-/*
- *  output a byte
- */
-TEXT   outb(SB),$0
-
-       MOVL    p+0(FP),DX
-       MOVL    b+4(FP),AX
-       OUTB
-       RET
-
-/*
- * output a short to a port
- */
-TEXT   outs(SB), $0
-       MOVL    p+0(FP), DX
-       MOVL    s+4(FP), AX
-       OPSIZE; OUTL
-       RET
-
-/*
- * output a long to a port
- */
-TEXT   outl(SB), $0
-       MOVL    p+0(FP), DX
-       MOVL    s+4(FP), AX
-       OUTL
-       RET
+       LONG $(0xFFFF)
+       LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
 
-/*
- *  input a string of bytes from a port
- */
-TEXT   insb(SB),$0
+       /* data segment descriptor for (PL 0) 16-bit */
+       LONG $(0xFFFF)
+       LONG $((0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
 
-       MOVL    p+0(FP),DX
-       MOVL    a+4(FP),DI
-       MOVL    c+8(FP),CX
-       CLD; REP; INSB
-       RET
+       /* exec segment descriptor for (PL 0) 16-bit */
+       LONG $(0xFFFF)
+       LONG $((0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
 
-/*
- *  input a string of shorts from a port
- */
-TEXT   inss(SB),$0
-       MOVL    p+0(FP),DX
-       MOVL    a+4(FP),DI
-       MOVL    c+8(FP),CX
-       CLD
-       REP; OPSIZE; INSL
-       RET
+TEXT tgdtptr(SB), $0 
+         WORD $(5*8) 
+         LONG $tgdt(SB)
 
-/*
- *  output a string of bytes to a port
- */
-TEXT   outsb(SB),$0
+TEXT jump(SB), $0
+       MOVL 4(SP), AX
+       JMP *AX
 
-       MOVL    p+0(FP),DX
-       MOVL    a+4(FP),SI
-       MOVL    c+8(FP),CX
-       CLD; REP; OUTSB
-       RET
+TEXT halt(SB), $0
+_halt:
+       JMP _halt
 
-/*
- *  output a string of shorts to a port
- */
-TEXT   outss(SB),$0
-       MOVL    p+0(FP),DX
-       MOVL    a+4(FP),SI
-       MOVL    c+8(FP),CX
-       CLD
-       REP; OPSIZE; OUTSL
+TEXT getc(SB), $0
+       CALL rmode16(SB)
+       STI
+       MOVB $0x00, AH
+       BIOSCALL(0x16)
+_getcret:
+       CALL16(pmode32(SB))
+       ANDL $0xFF, AX
        RET
 
-/*
- *  input a string of longs from a port
- */
-TEXT   insl(SB),$0
-
-       MOVL    p+0(FP),DX
-       MOVL    a+4(FP),DI
-       MOVL    c+8(FP),CX
-       CLD; REP; INSL
+TEXT gotc(SB), $0
+       CALL rmode16(SB)
+       STI
+       MOVB $0x01, AH
+       BIOSCALL(0x16)
+       JNZ _getcret
+       CLR(rAX)
+       JMP _getcret
+       
+TEXT putc(SB), $0
+       MOVL 4(SP),AX
+       CALL rmode16(SB)
+       STI
+       MOVB $0x0E, AH
+       BIOSCALL(0x10)
+_pret32:
+       CALL16(pmode32(SB))
+       ANDL $0xFFFF, AX
        RET
 
-/*
- *  output a string of longs to a port
- */
-TEXT   outsl(SB),$0
-
-       MOVL    p+0(FP),DX
-       MOVL    a+4(FP),SI
-       MOVL    c+8(FP),CX
-       CLD; REP; OUTSL
-       RET
+TEXT usleep(SB), $0
+       MOVL t+4(SP), AX
+       PUSHL AX
+       CALL rmode16(SB)
+       STI
+       POPR(rDX)
+       POPR(rCX)
+       MOVB $0x86, AH
+       BIOSCALL(0x15)
+       JMP _pret32
 
-/*
- *  routines to load/read various system registers
- */
-GLOBL  idtptr(SB),$6
-TEXT   putidt(SB),$0           /* interrupt descriptor table */
-       MOVL    t+0(FP),AX
-       MOVL    AX,idtptr+2(SB)
-       MOVL    l+4(FP),AX
-       MOVW    AX,idtptr(SB)
-       MOVL    idtptr(SB),IDTR
-       RET
+#ifdef PXE
 
-TEXT   putcr3(SB),$0           /* top level page table pointer */
-       MOVL    t+0(FP),AX
-       MOVL    AX,CR3
-       RET
+TEXT pxeinit(SB), $0
+       CALL rmode16(SB)
 
-TEXT   getcr0(SB),$0           /* coprocessor bits */
-       MOVL    CR0,AX
-       RET
+       /* get pxe env structure in ES:BX */
+       LWI(0x5650, rAX)
+       BIOSCALL(0x1A)
+       JC _pret32
 
-TEXT   getcr2(SB),$0           /* fault address */
-       MOVL    CR2,AX
-       RET
+       /* !PXE or PXEENV+ signature */
+       SEGES; LXW(0, xBX, rAX)
+       CMPI((('!'<<0)|('P'<<8)), rAX)
+       JEQ _getentry
+       CMPI((('P'<<0)|('X'<<8)), rAX)
+       JNE _pret32
 
-TEXT   getcr3(SB),$0           /* page directory base */
-       MOVL    CR3,AX
-       RET
+       SEGES; LXW(0x2A, xBX, rAX)
+       SEGES; LXW(0x28, xBX, rBX)
+       MTSR(rAX, rES)
 
-TEXT   getcr4(SB), $0          /* CR4 - extensions */
-       MOVL    CR4, AX
-       RET
+_getentry:
+       SEGES; LXW(0x12, xBX, rAX)
+       SW(rAX, pxepseg(SB))
+       SEGES; LXW(0x10, xBX, rAX)
+       SW(rAX, pxepoff(SB))
+       CLR(rAX)
+       JMP _pret32
 
-TEXT _cycles(SB), $0                           /* time stamp counter */
-       RDTSC
-       MOVL    vlong+0(FP), CX                 /* &vlong */
-       MOVL    AX, 0(CX)                       /* lo */
-       MOVL    DX, 4(CX)                       /* hi */
-       RET
+TEXT pxecallret(SB), $0
+       ADDI(6, rSP)
+       JMP _pret32
 
-TEXT rdmsr(SB), $0                             /* model-specific register */
-       MOVL    index+0(FP), CX
-       RDMSR
-       MOVL    vlong+4(FP), CX                 /* &vlong */
-       MOVL    AX, 0(CX)                       /* lo */
-       MOVL    DX, 4(CX)                       /* hi */
-       RET
-       
-TEXT wrmsr(SB), $0
-       MOVL    index+0(FP), CX
-       MOVL    lo+4(FP), AX
-       MOVL    hi+8(FP), DX
-       WRMSR
-       RET
+TEXT pxecall(SB), $0
+       MOVL op+4(SP),AX
+       MOVL buf+8(SP),SI
+       CALL rmode16(SB)
 
-TEXT mb386(SB), $0
-       POPL    AX                              /* return PC */
-       PUSHFL
-       PUSHL   CS
-       PUSHL   AX
-       IRETL
+       CLR(rCX)
+       PUSHR(rCX)
+       PUSHR(rSI)
 
-/*
- *  special traps
- */
-TEXT   intr0(SB),$0
-       PUSHL   $0
-       PUSHL   $0
-       JMP     intrcommon
-TEXT   intr1(SB),$0
-       PUSHL   $0
-       PUSHL   $1
-       JMP     intrcommon
-TEXT   intr2(SB),$0
-       PUSHL   $0
-       PUSHL   $2
-       JMP     intrcommon
-TEXT   intr3(SB),$0
-       PUSHL   $0
-       PUSHL   $3
-       JMP     intrcommon
-TEXT   intr4(SB),$0
-       PUSHL   $0
-       PUSHL   $4
-       JMP     intrcommon
-TEXT   intr5(SB),$0
-       PUSHL   $0
-       PUSHL   $5
-       JMP     intrcommon
-TEXT   intr6(SB),$0
-       PUSHL   $0
-       PUSHL   $6
-       JMP     intrcommon
-TEXT   intr7(SB),$0
-       PUSHL   $0
-       PUSHL   $7
-       JMP     intrcommon
-TEXT   intr8(SB),$0
-       PUSHL   $8
-       JMP     intrcommon
-TEXT   intr9(SB),$0
-       PUSHL   $0
-       PUSHL   $9
-       JMP     intrcommon
-TEXT   intr10(SB),$0
-       PUSHL   $10
-       JMP     intrcommon
-TEXT   intr11(SB),$0
-       PUSHL   $11
-       JMP     intrcommon
-TEXT   intr12(SB),$0
-       PUSHL   $12
-       JMP     intrcommon
-TEXT   intr13(SB),$0
-       PUSHL   $13
-       JMP     intrcommon
-TEXT   intr14(SB),$0
-       PUSHL   $14
-       JMP     intrcommon
-TEXT   intr15(SB),$0
-       PUSHL   $0
-       PUSHL   $15
-       JMP     intrcommon
-TEXT   intr16(SB),$0
-       PUSHL   $0
-       PUSHL   $16
-       JMP     intrcommon
-TEXT   intr24(SB),$0
-       PUSHL   $0
-       PUSHL   $24
-       JMP     intrcommon
-TEXT   intr25(SB),$0
-       PUSHL   $0
-       PUSHL   $25
-       JMP     intrcommon
-TEXT   intr26(SB),$0
-       PUSHL   $0
-       PUSHL   $26
-       JMP     intrcommon
-TEXT   intr27(SB),$0
-       PUSHL   $0
-       PUSHL   $27
-       JMP     intrcommon
-TEXT   intr28(SB),$0
-       PUSHL   $0
-       PUSHL   $28
-       JMP     intrcommon
-TEXT   intr29(SB),$0
-       PUSHL   $0
-       PUSHL   $29
-       JMP     intrcommon
-TEXT   intr30(SB),$0
-       PUSHL   $0
-       PUSHL   $30
-       JMP     intrcommon
-TEXT   intr31(SB),$0
-       PUSHL   $0
-       PUSHL   $31
-       JMP     intrcommon
-TEXT   intr32(SB),$0
-       PUSHL   $0
-       PUSHL   $32
-       JMP     intrcommon
-TEXT   intr33(SB),$0
-       PUSHL   $0
-       PUSHL   $33
-       JMP     intrcommon
-TEXT   intr34(SB),$0
-       PUSHL   $0
-       PUSHL   $34
-       JMP     intrcommon
-TEXT   intr35(SB),$0
-       PUSHL   $0
-       PUSHL   $35
-       JMP     intrcommon
-TEXT   intr36(SB),$0
-       PUSHL   $0
-       PUSHL   $36
-       JMP     intrcommon
-TEXT   intr37(SB),$0
-       PUSHL   $0
-       PUSHL   $37
-       JMP     intrcommon
-TEXT   intr38(SB),$0
-       PUSHL   $0
-       PUSHL   $38
-       JMP     intrcommon
-TEXT   intr39(SB),$0
-       PUSHL   $0
-       PUSHL   $39
-       JMP     intrcommon
-TEXT   intr64(SB),$0
-       PUSHL   $0
-       PUSHL   $64
-       JMP     intrcommon
-TEXT   intrbad(SB),$0
-       PUSHL   $0
-       PUSHL   $0x1ff
-       JMP     intrcommon
+       /* opcode */
+       PUSHR(rAX)
 
-intrcommon:
-       PUSHL   DS
-       PUSHL   ES
-       PUSHL   FS
-       PUSHL   GS
-       PUSHAL
-       MOVL    $(KDSEL),AX
-       MOVW    AX,DS
-       MOVW    AX,ES
-       LEAL    0(SP),AX
-       PUSHL   AX
-       CALL    trap(SB)
-       POPL    AX
-       POPAL
-       POPL    GS
-       POPL    FS
-       POPL    ES
-       POPL    DS
-       ADDL    $8,SP   /* error code and trap type */
-       IRETL
+       /* farcall */
+       PUSHR(rCX)
+       PUSHI(pxecallret(SB))
 
+       LW(pxepseg(SB), rAX)
+       PUSHR(rAX)
+       LW(pxepoff(SB), rAX)
+       PUSHR(rAX)
 
-/*
- *  interrupt level is interrupts on or off
- */
-TEXT   spllo(SB),$0
-       PUSHFL
-       POPL    AX
        STI
-       RET
 
-TEXT   splhi(SB),$0
-       PUSHFL
-       POPL    AX
-       CLI
-       RET
+       CLR(rAX)
+       CLR(rBX)
+       CLR(rCX)
+       CLR(rDX)
+       CLR(rDI)
+       CLR(rSI)
+       FARRET
 
-TEXT   splx(SB),$0
-       MOVL    s+0(FP),AX
-       PUSHL   AX
-       POPFL
-       RET
+TEXT pxepseg(SB), $0
+       WORD $0
+TEXT pxepoff(SB), $0
+       WORD $0
 
-/*
- *  do nothing whatsoever till interrupt happens
- */
-TEXT   idle(SB),$0
-       HLT
-       RET
+#else /* PXE */
 
 /*
- * Try to determine the CPU type which requires fiddling with EFLAGS.
- * If the Id bit can be toggled then the CPUID instruciton can be used
- * to determine CPU identity and features. First have to check if it's
- * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
- * toggled then it's an older 486 of some kind.
- *
- *     cpuid(id[], &ax, &dx);
+ * in:
+ *     DL drive
+ *     AX:BX lba32,
+ *     0000:SI buffer
  */
-#define CPUID          BYTE $0x0F; BYTE $0xA2  /* CPUID, argument in AX */
-TEXT cpuid(SB), $0
-       MOVL    $0x240000, AX
-       PUSHL   AX
-       POPFL                                   /* set Id|Ac */
-
-       PUSHFL
-       POPL    BX                              /* retrieve value */
-
-       MOVL    $0, AX
-       PUSHL   AX
-       POPFL                                   /* clear Id|Ac, EFLAGS initialised */
-
-       PUSHFL
-       POPL    AX                              /* retrieve value */
-       XORL    BX, AX
-       TESTL   $0x040000, AX                   /* Ac */
-       JZ      _cpu386                         /* can't set this bit on 386 */
-       TESTL   $0x200000, AX                   /* Id */
-       JZ      _cpu486                         /* can't toggle this bit on some 486 */
-
-       MOVL    $0, AX
-       CPUID
-       MOVL    id+0(FP), BP
-       MOVL    BX, 0(BP)                       /* "Genu" "Auth" "Cyri" */
-       MOVL    DX, 4(BP)                       /* "ineI" "enti" "xIns" */
-       MOVL    CX, 8(BP)                       /* "ntel" "cAMD" "tead" */
-
-       MOVL    $1, AX
-       CPUID
-       JMP     _cpuid
-
-_cpu486:
-       MOVL    $0x400, AX
-       MOVL    $0, DX
-       JMP     _cpuid
+TEXT readsect16(SB), $0
+       PUSHA
+       CLR(rCX)
 
-_cpu386:
-       MOVL    $0x300, AX
-       MOVL    $0, DX
+       PUSHR(rCX)              /* qword lba */
+       PUSHR(rCX)
+       PUSHR(rBX)
+       PUSHR(rAX)
 
-_cpuid:
-       MOVL    ax+4(FP), BP
-       MOVL    AX, 0(BP)
-       MOVL    dx+8(FP), BP
-       MOVL    DX, 0(BP)
-       RET
+       PUSHR(rCX)              /* dword buffer */
+       PUSHR(rSI)
 
+       INC(rCX)
+       PUSHR(rCX)              /* word # of sectors */
 
-/*
- *  basic timing loop to determine CPU frequency
- */
-TEXT   aamloop(SB),$0
+       PUSHI(0x0010)           /* byte reserved, byte packet size */
 
-       MOVL    c+0(FP),CX
-aaml1:
-       AAM
-       LOOP    aaml1
+       MW(rSP, rSI)
+       LWI(0x4200, rAX)
+       BIOSCALL(0x13)
+       JCC _readok
+       ADDI(0x10, rSP)
+       POPA
+       CLR(rAX)
+       DEC(rAX)
        RET
-
-TEXT hello(SB), $0
-       BYTE $'\r';
-       BYTE $'\n';
-       BYTE $'P'; BYTE $'l'; BYTE $'a'; BYTE $'n';
-       BYTE $' '; BYTE $'9'; BYTE $' '; BYTE $'f';
-       BYTE $'r'; BYTE $'o'; BYTE $'m'; BYTE $' ';
-       BYTE $'B'; BYTE $'e'; BYTE $'l'; BYTE $'l';
-       BYTE $' '; BYTE $'L'; BYTE $'a'; BYTE $'b';
-       BYTE $'s'; 
-#ifdef PXE
-       BYTE $' '; BYTE $'b'; BYTE $'y'; BYTE $' ';
-       BYTE $'P'; BYTE $'X'; BYTE $'E';
-#endif
-       BYTE $'\r';
-       BYTE $'\n';
-       BYTE $'\z';
-
-TEXT rock(SB), $0
-       BYTE $0; BYTE $0; BYTE $0; BYTE $0;
-
-GLOBL pxe(SB), $4
-#ifdef PXE
-DATA   pxe+0(SB)/4, $1
-#else
-DATA   pxe+0(SB)/4, $0
-#endif /* PXE */
-
-/*
- * Save registers.
- */
-TEXT saveregs(SB), $0
-       /* appease 8l */
-       SUBL $32, SP
-       POPL AX
-       POPL AX
-       POPL AX
-       POPL AX
-       POPL AX
-       POPL AX
-       POPL AX
-       POPL AX
-       
-       PUSHL   AX
-       PUSHL   BX
-       PUSHL   CX
-       PUSHL   DX
-       PUSHL   BP
-       PUSHL   DI
-       PUSHL   SI
-       PUSHFL
-
-       XCHGL   32(SP), AX      /* swap return PC and saved flags */
-       XCHGL   0(SP), AX
-       XCHGL   32(SP), AX
+_readok:
+       ADDI(0x10, rSP)
+       POPA
+       CLR(rAX)
        RET
 
-TEXT restoreregs(SB), $0
-       /* appease 8l */
-       PUSHL   AX
-       PUSHL   AX
-       PUSHL   AX
-       PUSHL   AX
-       PUSHL   AX
-       PUSHL   AX
-       PUSHL   AX
-       PUSHL   AX
-       ADDL    $32, SP
-       
-       XCHGL   32(SP), AX      /* swap return PC and saved flags */
-       XCHGL   0(SP), AX
-       XCHGL   32(SP), AX
-
-       POPFL
-       POPL    SI
-       POPL    DI
-       POPL    BP
-       POPL    DX
-       POPL    CX
-       POPL    BX
-       POPL    AX
+TEXT readsect(SB), $0
+       MOVL 4(SP), DX
+       MOVW 8(SP), AX
+       MOVW 10(SP), BX
+       MOVL 12(SP), SI 
+       CALL rmode16(SB)
+       STI
+       CALL16(readsect16(SB))
+       CALL16(pmode32(SB))
+       ANDL $0xFFFF, AX
        RET
 
-/*
- * Assumed to be in protected mode at time of call.
- * Switch to real mode, execute an interrupt, and
- * then switch back to protected mode.  
- *
- * Assumes:
- *
- *     - no device interrupts are going to come in
- *     - 0-16MB is identity mapped in page tables
- *     - can use code segment 0x1000 in real mode
- *             to get at l.s code
- */
-TEXT realmodeidtptr(SB), $0
-       WORD    $(4*256-1)
-       LONG    $0
-
-TEXT realmode0(SB), $0
-       CALL    saveregs(SB)
-
-       /* switch to low code address */
-       LEAL    physcode-KZERO(SB), AX
-       JMP *AX
-
-TEXT physcode(SB), $0
-
-       /* switch to low stack */
-       MOVL    SP, AX
-       MOVL    $0x7C00, SP
-       PUSHL   AX
-
-       /* load IDT with real-mode version; GDT already fine */
-       MOVL    realmodeidtptr(SB), IDTR
-
-       /* edit INT $0x00 instruction below */
-       MOVL    realmodeintr(SB), AX
-       MOVB    AX, realmodeintrinst+1(SB)
-
-       /* disable paging */
-       MOVL    CR0, AX
-       ANDL    $0x7FFFFFFF, AX
-       MOVL    AX, CR0
-       /* JMP .+2 to clear prefetch queue*/
-       BYTE $0xEB; BYTE $0x00
-
-       /* jump to 16-bit code segment */
-/*     JMPFAR  SELECTOR(3, SELGDT, 0):$again16bit(SB) /**/
-        BYTE   $0xEA
-        LONG   $again16bit-KZERO(SB)
-        WORD   $SELECTOR(3, SELGDT, 0)
-
-TEXT again16bit(SB), $0
-       /*
-        * Now in 16-bit compatibility mode.
-        * These are 32-bit instructions being interpreted
-        * as 16-bit instructions.  I'm being lazy and
-        * not using the macros because I know when
-        * the 16- and 32-bit instructions look the same
-        * or close enough.
-        */
-
-       /* disable protected mode and jump to real mode cs */
-       OPSIZE; MOVL CR0, AX
-       OPSIZE; XORL BX, BX
-       OPSIZE; INCL BX
-       OPSIZE; XORL BX, AX
-       OPSIZE; MOVL AX, CR0
-
-       /* JMPFAR 0x1000:now16real */
-        BYTE $0xEA
-        WORD   $now16real-KZERO(SB)
-        WORD   $0x1000
-
-TEXT now16real(SB), $0
-       /* copy the registers for the bios call */
-       LWI(0x1000, rAX)
-       MOVW    AX,SS
-       LWI(realmoderegs(SB), rBP)
-       
-       /* offsets are in Ureg */
-       LXW(44, xBP, rAX)
-       MOVW    AX, DS
-       LXW(40, xBP, rAX)
-       MOVW    AX, ES
-
-       OPSIZE; LXW(0, xBP, rDI)
-       OPSIZE; LXW(4, xBP, rSI)
-       OPSIZE; LXW(16, xBP, rBX)
-       OPSIZE; LXW(20, xBP, rDX)
-       OPSIZE; LXW(24, xBP, rCX)
-       OPSIZE; LXW(28, xBP, rAX)
-
-       CLC
-
-TEXT realmodeintrinst(SB), $0
-       INT $0x00
-
-
-       /* save the registers after the call */
-
-       LWI(0x7bfc, rSP)
-       OPSIZE; PUSHFL
-       OPSIZE; PUSHL AX
-
-       LWI(0x1000, rAX)
-       MOVW    AX,SS
-       LWI(realmoderegs(SB), rBP)
-       
-       OPSIZE; SXW(rDI, 0, xBP)
-       OPSIZE; SXW(rSI, 4, xBP)
-       OPSIZE; SXW(rBX, 16, xBP)
-       OPSIZE; SXW(rDX, 20, xBP)
-       OPSIZE; SXW(rCX, 24, xBP)
-       OPSIZE; POPL AX
-       OPSIZE; SXW(rAX, 28, xBP)
-
-       MOVW    DS, AX
-       OPSIZE; SXW(rAX, 44, xBP)
-       MOVW    ES, AX
-       OPSIZE; SXW(rAX, 40, xBP)
-
-       OPSIZE; POPL AX
-       OPSIZE; SXW(rAX, 64, xBP)       /* flags */
-
-       /* re-enter protected mode and jump to 32-bit code */
-       OPSIZE; MOVL $1, AX
-       OPSIZE; MOVL AX, CR0
-       
-/*     JMPFAR  SELECTOR(2, SELGDT, 0):$again32bit(SB) /**/
-        OPSIZE
-        BYTE $0xEA
-        LONG   $again32bit-KZERO(SB)
-        WORD   $SELECTOR(2, SELGDT, 0)
-
-TEXT again32bit(SB), $0
-       MOVW    $SELECTOR(1, SELGDT, 0),AX
-       MOVW    AX,DS
-       MOVW    AX,SS
-       MOVW    AX,ES
-       MOVW    AX,FS
-       MOVW    AX,GS
-
-       /* enable paging and jump to kzero-address code */
-       MOVL    CR0, AX
-       ORL     $0x80000000, AX
-       MOVL    AX, CR0
-       LEAL    again32kzero(SB), AX
-       JMP*    AX
-
-TEXT again32kzero(SB), $0
-       /* breathe a sigh of relief - back in 32-bit protected mode */
-
-       /* switch to old stack */       
-       PUSHL   AX      /* match popl below for 8l */
-       MOVL    $0x7BFC, SP
-       POPL    SP
+#endif
 
-       /* restore idt */
-       MOVL    idtptr(SB),IDTR
+#ifdef ISO
 
-       CALL    restoreregs(SB)
-       RET
+TEXT bootname(SB), $0
+       BYTE $'3'; BYTE $'8'; BYTE $'6'; BYTE $'/';
+       BYTE $'9'; BYTE $'b'; BYTE $'o'; BYTE $'o';
+       BYTE $'t'; BYTE $'i'; BYTE $'s'; BYTE $'o';
+       BYTE $0
 
-TEXT realmoderegs(SB), $0
-       LONG $0; LONG $0; LONG $0; LONG $0
-       LONG $0; LONG $0; LONG $0; LONG $0
-       LONG $0; LONG $0; LONG $0; LONG $0
-       LONG $0; LONG $0; LONG $0; LONG $0
-       LONG $0; LONG $0; LONG $0; LONG $0
+#endif
 
-TEXT realmodeintr(SB), $0
-       LONG $0
+TEXT crnl(SB), $0
+       BYTE $'\r'; BYTE $'\n'; BYTE $0
 
+TEXT hex(SB), $0
+       BYTE $'0'; BYTE $'1'; BYTE $'2'; BYTE $'3';
+       BYTE $'4'; BYTE $'5'; BYTE $'6'; BYTE $'7';
+       BYTE $'8'; BYTE $'9'; BYTE $'a'; BYTE $'b';
+       BYTE $'c'; BYTE $'d'; BYTE $'e'; BYTE $'f'