From 7094a911cb0108eb988c5f9f2bbac09e0a4bdc22 Mon Sep 17 00:00:00 2001 From: ru Date: Wed, 28 Apr 2004 14:31:44 +0000 Subject: After talking to Bruce Evans and reading more standards specs, switch to using C99-style comments everywhere in preprocessed assembler. The reason is that lines starting with the regexp '^[[:space:]]#' are treated as preprocessing directives, and while it seems to work now with GCC, it's not necessarily has to work. Use C99 comments `//' for the trailing comments to save whitespace. --- sys/boot/i386/boot2/boot1.S | 420 ++++---- sys/boot/i386/boot2/sio.S | 84 +- sys/boot/i386/btx/btx/btx.S | 1841 ++++++++++++++++++----------------- sys/boot/i386/btx/btxldr/btxldr.S | 522 +++++----- sys/boot/i386/libi386/amd64_tramp.S | 10 +- sys/boot/i386/pxeldr/pxeldr.S | 330 +++---- 6 files changed, 1606 insertions(+), 1601 deletions(-) (limited to 'sys') diff --git a/sys/boot/i386/boot2/boot1.S b/sys/boot/i386/boot2/boot1.S index badaee8..79e732b 100644 --- a/sys/boot/i386/boot2/boot1.S +++ b/sys/boot/i386/boot2/boot1.S @@ -16,33 +16,33 @@ */ /* Memory Locations */ - .set MEM_REL,0x700 # Relocation address - .set MEM_ARG,0x900 # Arguments - .set MEM_ORG,0x7c00 # Origin - .set MEM_BUF,0x8cec # Load area - .set MEM_BTX,0x9000 # BTX start - .set MEM_JMP,0x9010 # BTX entry point - .set MEM_USR,0xa000 # Client start - .set BDA_BOOT,0x472 # Boot howto flag + .set MEM_REL,0x700 // Relocation address + .set MEM_ARG,0x900 // Arguments + .set MEM_ORG,0x7c00 // Origin + .set MEM_BUF,0x8cec // Load area + .set MEM_BTX,0x9000 // BTX start + .set MEM_JMP,0x9010 // BTX entry point + .set MEM_USR,0xa000 // Client start + .set BDA_BOOT,0x472 // Boot howto flag /* Partition Constants */ - .set PRT_OFF,0x1be # Partition offset - .set PRT_NUM,0x4 # Partitions - .set PRT_BSD,0xa5 # Partition type + .set PRT_OFF,0x1be // Partition offset + .set PRT_NUM,0x4 // Partitions + .set PRT_BSD,0xa5 // Partition type /* Flag Bits */ - .set FL_PACKET,0x80 # Packet mode + .set FL_PACKET,0x80 // Packet mode /* Misc. Constants */ - .set SIZ_PAG,0x1000 # Page size - .set SIZ_SEC,0x200 # Sector size + .set SIZ_PAG,0x1000 // Page size + .set SIZ_SEC,0x200 // Sector size .set NSECT,0x10 .globl start .globl xread .code16 -start: jmp main # Start recognizably +start: jmp main // Start recognizably /* * This is the start of a standard BIOS Parameter Block (BPB). Most bootable @@ -59,24 +59,24 @@ start: jmp main # Start recognizably * move the "prompt" message data (below) to replace the OEM ID. */ .org 0x03, 0x00 -oemid: .space 0x08, 0x00 # OEM ID +oemid: .space 0x08, 0x00 // OEM ID .org 0x0b, 0x00 -bpb: .word 512 # sector size (T) - .byte 0 # sectors/clustor - .word 0 # reserved sectors - .byte 0 # number of FATs - .word 0 # root entries - .word 0 # small sectors - .byte 0 # media type (W) - .word 0 # sectors/fat - .word 18 # sectors per track (T) - .word 2 # number of heads (T) - .long 0 # hidden sectors (W) - .long 0 # large sectors +bpb: .word 512 // sector size (T) + .byte 0 // sectors/clustor + .word 0 // reserved sectors + .byte 0 // number of FATs + .word 0 // root entries + .word 0 // small sectors + .byte 0 // media type (W) + .word 0 // sectors/fat + .word 18 // sectors per track (T) + .word 2 // number of heads (T) + .long 0 // hidden sectors (W) + .long 0 // large sectors .org 0x24, 0x00 -ebpb: .byte 0 # BIOS physical drive number (W) +ebpb: .byte 0 // BIOS physical drive number (W) .org 0x25,0x90 /* @@ -89,25 +89,25 @@ ebpb: .byte 0 # BIOS physical drive number (W) * %dh - byte - num sectors to read */ -xread: push %ss # Address - pop %ds # data +xread: push %ss // Address + pop %ds // data /* * Setup an EDD disk packet and pass it to read */ -xread.1: # Starting - pushl $0x0 # absolute - push %cx # block - push %ax # number - push %es # Address of - push %bx # transfer buffer - xor %ax,%ax # Number of - movb %dh,%al # blocks to - push %ax # transfer - push $0x10 # Size of packet - mov %sp,%bp # Packet pointer - callw read # Read from disk - lea 0x10(%bp),%sp # Clear stack - lret # To far caller +xread.1: // Starting + pushl $0x0 // absolute + push %cx // block + push %ax // number + push %es // Address of + push %bx // transfer buffer + xor %ax,%ax // Number of + movb %dh,%al // blocks to + push %ax // transfer + push $0x10 // Size of packet + mov %sp,%bp // Packet pointer + callw read // Read from disk + lea 0x10(%bp),%sp // Clear stack + lret // To far caller /* * Load the rest of boot2 and BTX up, copy the parts to the right locations, * and start it all up. @@ -117,21 +117,21 @@ xread.1: # Starting * Setup the segment registers to flat addressing (segment 0) and setup the * stack to end just below the start of our code. */ -main: cld # String ops inc - xor %cx,%cx # Zero - mov %cx,%es # Address - mov %cx,%ds # data - mov %cx,%ss # Set up - mov $start,%sp # stack +main: cld // String ops inc + xor %cx,%cx // Zero + mov %cx,%es // Address + mov %cx,%ds // data + mov %cx,%ss // Set up + mov $start,%sp // stack /* * Relocate ourself to MEM_REL. Since %cx == 0, the inc %ch sets * %cx == 0x100. */ - mov %sp,%si # Source - mov $MEM_REL,%di # Destination - incb %ch # Word count - rep # Copy - movsw # code + mov %sp,%si // Source + mov $MEM_REL,%di // Destination + incb %ch // Word count + rep // Copy + movsw // code /* * If we are on a hard drive, then load the MBR and look for the first * FreeBSD slice. We use the fake partition entry below that points to @@ -139,35 +139,35 @@ main: cld # String ops inc * FreeBSD slice. The second pass looks for the first non-active FreeBSD * slice if the first one fails. */ - mov $part4,%si # Partition - cmpb $0x80,%dl # Hard drive? - jb main.4 # No - movb $0x1,%dh # Block count - callw nread # Read MBR - mov $0x1,%cx # Two passes -main.1: mov $MEM_BUF+PRT_OFF,%si # Partition table - movb $0x1,%dh # Partition -main.2: cmpb $PRT_BSD,0x4(%si) # Our partition type? - jne main.3 # No - jcxz main.5 # If second pass - testb $0x80,(%si) # Active? - jnz main.5 # Yes -main.3: add $0x10,%si # Next entry - incb %dh # Partition - cmpb $0x1+PRT_NUM,%dh # In table? - jb main.2 # Yes - dec %cx # Do two - jcxz main.1 # passes + mov $part4,%si // Partition + cmpb $0x80,%dl // Hard drive? + jb main.4 // No + movb $0x1,%dh // Block count + callw nread // Read MBR + mov $0x1,%cx // Two passes +main.1: mov $MEM_BUF+PRT_OFF,%si // Partition table + movb $0x1,%dh // Partition +main.2: cmpb $PRT_BSD,0x4(%si) // Our partition type? + jne main.3 // No + jcxz main.5 // If second pass + testb $0x80,(%si) // Active? + jnz main.5 // Yes +main.3: add $0x10,%si // Next entry + incb %dh // Partition + cmpb $0x1+PRT_NUM,%dh // In table? + jb main.2 // Yes + dec %cx // Do two + jcxz main.1 // passes /* * If we get here, we didn't find any FreeBSD slices at all, so print an * error message and die. */ - mov $msg_part,%si # Message - jmp error # Error + mov $msg_part,%si // Message + jmp error // Error /* * Floppies use partition 0 of drive 0. */ -main.4: xor %dx,%dx # Partition:drive +main.4: xor %dx,%dx // Partition:drive /* * Ok, we have a slice and drive in %dx now, so use that to locate and load * boot2. %si references the start of the slice we are looking for, so go @@ -182,80 +182,80 @@ main.4: xor %dx,%dx # Partition:drive * when we use btxld to create boot2, we use an entry point of 0x2000. That * entry point is relative to MEM_USR; thus boot2.bin starts at 0xc000. */ -main.5: mov %dx,MEM_ARG # Save args - movb $NSECT,%dh # Sector count - callw nread # Read disk - mov $MEM_BTX,%bx # BTX - mov 0xa(%bx),%si # Get BTX length and set - add %bx,%si # %si to start of boot2.bin - mov $MEM_USR+SIZ_PAG*2,%di # Client page 2 - mov $MEM_BTX+(NSECT-1)*SIZ_SEC,%cx # Byte - sub %si,%cx # count - rep # Relocate - movsb # client - sub %di,%cx # Byte count - xorb %al,%al # Zero assumed bss from - rep # the end of boot2.bin - stosb # up to 0x10000 - callw seta20 # Enable A20 - jmp start+MEM_JMP-MEM_ORG # Start BTX +main.5: mov %dx,MEM_ARG // Save args + movb $NSECT,%dh // Sector count + callw nread // Read disk + mov $MEM_BTX,%bx // BTX + mov 0xa(%bx),%si // Get BTX length and set + add %bx,%si // %si to start of boot2.bin + mov $MEM_USR+SIZ_PAG*2,%di // Client page 2 + mov $MEM_BTX+(NSECT-1)*SIZ_SEC,%cx // Byte + sub %si,%cx // count + rep // Relocate + movsb // client + sub %di,%cx // Byte count + xorb %al,%al // Zero assumed bss from + rep // the end of boot2.bin + stosb // up to 0x10000 + callw seta20 // Enable A20 + jmp start+MEM_JMP-MEM_ORG // Start BTX /* * Enable A20 so we can access memory above 1 meg. */ -seta20: cli # Disable interrupts -seta20.1: inb $0x64,%al # Get status - testb $0x2,%al # Busy? - jnz seta20.1 # Yes - movb $0xd1,%al # Command: Write - outb %al,$0x64 # output port -seta20.2: inb $0x64,%al # Get status - testb $0x2,%al # Busy? - jnz seta20.2 # Yes - movb $0xdf,%al # Enable - outb %al,$0x60 # A20 - sti # Enable interrupts - retw # To caller +seta20: cli // Disable interrupts +seta20.1: inb $0x64,%al // Get status + testb $0x2,%al // Busy? + jnz seta20.1 // Yes + movb $0xd1,%al // Command: Write + outb %al,$0x64 // output port +seta20.2: inb $0x64,%al // Get status + testb $0x2,%al // Busy? + jnz seta20.2 // Yes + movb $0xdf,%al // Enable + outb %al,$0x60 // A20 + sti // Enable interrupts + retw // To caller /* * Trampoline used to call read from within boot1. */ -nread: mov $MEM_BUF,%bx # Transfer buffer - mov 0x8(%si),%ax # Get - mov 0xa(%si),%cx # LBA - push %cs # Read from - callw xread.1 # disk - jnc return # If success, return - mov $msg_read,%si # Otherwise, set the error - # message and fall through to - # the error routine +nread: mov $MEM_BUF,%bx // Transfer buffer + mov 0x8(%si),%ax // Get + mov 0xa(%si),%cx // LBA + push %cs // Read from + callw xread.1 // disk + jnc return // If success, return + mov $msg_read,%si // Otherwise, set the error + // message and fall through to + // the error routine /* * Print out the error message pointed to by %ds:(%si) followed * by a prompt, wait for a keypress, and then reboot the machine. */ -error: callw putstr # Display message - mov $prompt,%si # Display - callw putstr # prompt - xorb %ah,%ah # BIOS: Get - int $0x16 # keypress - movw $0x1234, BDA_BOOT # Do a warm boot - ljmp $0xffff,$0x0 # reboot the machine +error: callw putstr // Display message + mov $prompt,%si // Display + callw putstr // prompt + xorb %ah,%ah // BIOS: Get + int $0x16 // keypress + movw $0x1234, BDA_BOOT // Do a warm boot + ljmp $0xffff,$0x0 // reboot the machine /* * Display a null-terminated string using the BIOS output. */ -putstr.0: mov $0x7,%bx # Page:attribute - movb $0xe,%ah # BIOS: Display - int $0x10 # character -putstr: lodsb # Get char - testb %al,%al # End of string? - jne putstr.0 # No +putstr.0: mov $0x7,%bx // Page:attribute + movb $0xe,%ah // BIOS: Display + int $0x10 // character +putstr: lodsb // Get char + testb %al,%al // End of string? + jne putstr.0 // No /* * Overused return code. ereturn is used to return an error from the * read function. Since we assume putstr succeeds, we (ab)use the * same code when we return from putstr. */ -ereturn: movb $0x1,%ah # Invalid - stc # argument -return: retw # To caller +ereturn: movb $0x1,%ah // Invalid + stc // argument +return: retw // To caller /* * Reads sectors from the disk. If EDD is enabled, then check if it is * installed and use it if it is. If it is not installed or not enabled, then @@ -266,83 +266,83 @@ return: retw # To caller * %dl - byte - drive number * stack - 10 bytes - EDD Packet */ -read: push %dx # Save - movb $0x8,%ah # BIOS: Get drive - int $0x13 # parameters - movb %dh,%ch # Max head number - pop %dx # Restore - jc return # If error - andb $0x3f,%cl # Sectors per track - jz ereturn # If zero - cli # Disable interrupts - mov 0x8(%bp),%eax # Get LBA - push %dx # Save - movzbl %cl,%ebx # Divide by - xor %edx,%edx # sectors - div %ebx # per track - movb %ch,%bl # Max head number - movb %dl,%ch # Sector number - inc %bx # Divide by - xorb %dl,%dl # number - div %ebx # of heads - movb %dl,%bh # Head number - pop %dx # Restore - cmpl $0x3ff,%eax # Cylinder number supportable? - sti # Enable interrupts - ja read.7 # No, try EDD - xchgb %al,%ah # Set up cylinder - rorb $0x2,%al # number - orb %ch,%al # Merge - inc %ax # sector - xchg %ax,%cx # number - movb %bh,%dh # Head number - subb %ah,%al # Sectors this track - mov 0x2(%bp),%ah # Blocks to read - cmpb %ah,%al # To read - jb read.2 # this +read: push %dx // Save + movb $0x8,%ah // BIOS: Get drive + int $0x13 // parameters + movb %dh,%ch // Max head number + pop %dx // Restore + jc return // If error + andb $0x3f,%cl // Sectors per track + jz ereturn // If zero + cli // Disable interrupts + mov 0x8(%bp),%eax // Get LBA + push %dx // Save + movzbl %cl,%ebx // Divide by + xor %edx,%edx // sectors + div %ebx // per track + movb %ch,%bl // Max head number + movb %dl,%ch // Sector number + inc %bx // Divide by + xorb %dl,%dl // number + div %ebx // of heads + movb %dl,%bh // Head number + pop %dx // Restore + cmpl $0x3ff,%eax // Cylinder number supportable? + sti // Enable interrupts + ja read.7 // No, try EDD + xchgb %al,%ah // Set up cylinder + rorb $0x2,%al // number + orb %ch,%al // Merge + inc %ax // sector + xchg %ax,%cx // number + movb %bh,%dh // Head number + subb %ah,%al // Sectors this track + mov 0x2(%bp),%ah // Blocks to read + cmpb %ah,%al // To read + jb read.2 // this #ifdef TRACK_AT_A_TIME - movb %ah,%al # track + movb %ah,%al // track #else - movb $1,%al # one sector + movb $1,%al // one sector #endif -read.2: mov $0x5,%di # Try count -read.3: les 0x4(%bp),%bx # Transfer buffer - push %ax # Save - movb $0x2,%ah # BIOS: Read - int $0x13 # from disk - pop %bx # Restore - jnc read.4 # If success - dec %di # Retry? - jz read.6 # No - xorb %ah,%ah # BIOS: Reset - int $0x13 # disk system - xchg %bx,%ax # Block count - jmp read.3 # Continue -read.4: movzbw %bl,%ax # Sectors read - add %ax,0x8(%bp) # Adjust - jnc read.5 # LBA, - incw 0xa(%bp) # transfer -read.5: shlb %bl # buffer - add %bl,0x5(%bp) # pointer, - sub %al,0x2(%bp) # block count - ja read # If not done -read.6: retw # To caller -read.7: testb $FL_PACKET,%cs:MEM_REL+flags-start # LBA support enabled? - jz ereturn # No, so return an error - mov $0x55aa,%bx # Magic - push %dx # Save - movb $0x41,%ah # BIOS: Check - int $0x13 # extensions present - pop %dx # Restore - jc return # If error, return an error - cmp $0xaa55,%bx # Magic? - jne ereturn # No, so return an error - testb $0x1,%cl # Packet interface? - jz ereturn # No, so return an error - mov %bp,%si # Disk packet - movb $0x42,%ah # BIOS: Extended - int $0x13 # read - retw # To caller +read.2: mov $0x5,%di // Try count +read.3: les 0x4(%bp),%bx // Transfer buffer + push %ax // Save + movb $0x2,%ah // BIOS: Read + int $0x13 // from disk + pop %bx // Restore + jnc read.4 // If success + dec %di // Retry? + jz read.6 // No + xorb %ah,%ah // BIOS: Reset + int $0x13 // disk system + xchg %bx,%ax // Block count + jmp read.3 // Continue +read.4: movzbw %bl,%ax // Sectors read + add %ax,0x8(%bp) // Adjust + jnc read.5 // LBA, + incw 0xa(%bp) // transfer +read.5: shlb %bl // buffer + add %bl,0x5(%bp) // pointer, + sub %al,0x2(%bp) // block count + ja read // If not done +read.6: retw // To caller +read.7: testb $FL_PACKET,%cs:MEM_REL+flags-start // LBA support enabled? + jz ereturn // No, so return an error + mov $0x55aa,%bx // Magic + push %dx // Save + movb $0x41,%ah // BIOS: Check + int $0x13 // extensions present + pop %dx // Restore + jc return // If error, return an error + cmp $0xaa55,%bx // Magic? + jne ereturn // No, so return an error + testb $0x1,%cl // Packet interface? + jz ereturn // No, so return an error + mov %bp,%si // Disk packet + movb $0x42,%ah // BIOS: Extended + int $0x13 // read + retw // To caller /* Messages */ @@ -351,7 +351,7 @@ msg_part: .asciz "Boot" prompt: .asciz " error\r\n" -flags: .byte FLAGS # Flags +flags: .byte FLAGS // Flags .org PRT_OFF,0x90 @@ -361,6 +361,6 @@ flags: .byte FLAGS # Flags part4: .byte 0x80, 0x00, 0x01, 0x00 .byte 0xa5, 0xfe, 0xff, 0xff .byte 0x00, 0x00, 0x00, 0x00 - .byte 0x50, 0xc3, 0x00, 0x00 # 50000 sectors long, bleh + .byte 0x50, 0xc3, 0x00, 0x00 // 50000 sectors long, bleh - .word 0xaa55 # Magic number + .word 0xaa55 // Magic number diff --git a/sys/boot/i386/boot2/sio.S b/sys/boot/i386/boot2/sio.S index 3fc2963..6ec4491 100644 --- a/sys/boot/i386/boot2/sio.S +++ b/sys/boot/i386/boot2/sio.S @@ -15,9 +15,9 @@ * $FreeBSD$ */ - .set SIO_PRT,SIOPRT # Base port - .set SIO_FMT,SIOFMT # 8N1 - .set SIO_DIV,(115200/SIOSPD) # 115200 / SPD + .set SIO_PRT,SIOPRT // Base port + .set SIO_FMT,SIOFMT // 8N1 + .set SIO_DIV,(115200/SIOSPD) // 115200 / SPD .globl sio_init .globl sio_flush @@ -27,54 +27,54 @@ /* void sio_init(void) */ -sio_init: movw $SIO_PRT+0x3,%dx # Data format reg - movb $SIO_FMT|0x80,%al # Set format - outb %al,(%dx) # and DLAB - pushl %edx # Save - subb $0x3,%dl # Divisor latch reg - movw $SIO_DIV,%ax # Set - outw %ax,(%dx) # BPS - popl %edx # Restore - movb $SIO_FMT,%al # Clear - outb %al,(%dx) # DLAB - incl %edx # Modem control reg - movb $0x3,%al # Set RTS, - outb %al,(%dx) # DTR - incl %edx # Line status reg +sio_init: movw $SIO_PRT+0x3,%dx // Data format reg + movb $SIO_FMT|0x80,%al // Set format + outb %al,(%dx) // and DLAB + pushl %edx // Save + subb $0x3,%dl // Divisor latch reg + movw $SIO_DIV,%ax // Set + outw %ax,(%dx) // BPS + popl %edx // Restore + movb $SIO_FMT,%al // Clear + outb %al,(%dx) // DLAB + incl %edx // Modem control reg + movb $0x3,%al // Set RTS, + outb %al,(%dx) // DTR + incl %edx // Line status reg /* void sio_flush(void) */ -sio_flush.0: call sio_getc.1 # Get character -sio_flush: call sio_ischar # Check for character - jnz sio_flush.0 # Till none - ret # To caller +sio_flush.0: call sio_getc.1 // Get character +sio_flush: call sio_ischar // Check for character + jnz sio_flush.0 // Till none + ret // To caller /* void sio_putc(int c) */ -sio_putc: movw $SIO_PRT+0x5,%dx # Line status reg - xor %ecx,%ecx # Timeout - movb $0x40,%ch # counter -sio_putc.1: inb (%dx),%al # Transmitter - testb $0x20,%al # buffer empty? - loopz sio_putc.1 # No - jz sio_putc.2 # If timeout - movb 0x4(%esp,1),%al # Get character - subb $0x5,%dl # Transmitter hold reg - outb %al,(%dx) # Write character -sio_putc.2: ret $0x4 # To caller +sio_putc: movw $SIO_PRT+0x5,%dx // Line status reg + xor %ecx,%ecx // Timeout + movb $0x40,%ch // counter +sio_putc.1: inb (%dx),%al // Transmitter + testb $0x20,%al // buffer empty? + loopz sio_putc.1 // No + jz sio_putc.2 // If timeout + movb 0x4(%esp,1),%al // Get character + subb $0x5,%dl // Transmitter hold reg + outb %al,(%dx) // Write character +sio_putc.2: ret $0x4 // To caller /* int sio_getc(void) */ -sio_getc: call sio_ischar # Character available? - jz sio_getc # No -sio_getc.1: subb $0x5,%dl # Receiver buffer reg - inb (%dx),%al # Read character - ret # To caller +sio_getc: call sio_ischar // Character available? + jz sio_getc // No +sio_getc.1: subb $0x5,%dl // Receiver buffer reg + inb (%dx),%al // Read character + ret // To caller /* int sio_ischar(void) */ -sio_ischar: movw $SIO_PRT+0x5,%dx # Line status register - xorl %eax,%eax # Zero - inb (%dx),%al # Received data - andb $0x1,%al # ready? - ret # To caller +sio_ischar: movw $SIO_PRT+0x5,%dx // Line status register + xorl %eax,%eax // Zero + inb (%dx),%al // Received data + andb $0x1,%al // ready? + ret // To caller diff --git a/sys/boot/i386/btx/btx/btx.S b/sys/boot/i386/btx/btx/btx.S index 7581519..77cfe86 100644 --- a/sys/boot/i386/btx/btx/btx.S +++ b/sys/boot/i386/btx/btx/btx.S @@ -18,587 +18,588 @@ /* * Memory layout. */ - .set MEM_BTX,0x1000 # Start of BTX memory - .set MEM_ESP0,0x1800 # Supervisor stack - .set MEM_BUF,0x1800 # Scratch buffer - .set MEM_ESP1,0x1e00 # Link stack - .set MEM_IDT,0x1e00 # IDT - .set MEM_TSS,0x1f98 # TSS - .set MEM_MAP,0x2000 # I/O bit map - .set MEM_DIR,0x4000 # Page directory - .set MEM_TBL,0x5000 # Page tables - .set MEM_ORG,0x9000 # BTX code - .set MEM_USR,0xa000 # Start of user memory + .set MEM_BTX,0x1000 // Start of BTX memory + .set MEM_ESP0,0x1800 // Supervisor stack + .set MEM_BUF,0x1800 // Scratch buffer + .set MEM_ESP1,0x1e00 // Link stack + .set MEM_IDT,0x1e00 // IDT + .set MEM_TSS,0x1f98 // TSS + .set MEM_MAP,0x2000 // I/O bit map + .set MEM_DIR,0x4000 // Page directory + .set MEM_TBL,0x5000 // Page tables + .set MEM_ORG,0x9000 // BTX code + .set MEM_USR,0xa000 // Start of user memory /* * Paging control. */ - .set PAG_SIZ,0x1000 # Page size - .set PAG_CNT,0x1000 # Pages to map + .set PAG_SIZ,0x1000 // Page size + .set PAG_CNT,0x1000 // Pages to map /* * Segment selectors. */ - .set SEL_SCODE,0x8 # Supervisor code - .set SEL_SDATA,0x10 # Supervisor data - .set SEL_RCODE,0x18 # Real mode code - .set SEL_RDATA,0x20 # Real mode data - .set SEL_UCODE,0x28|3 # User code - .set SEL_UDATA,0x30|3 # User data - .set SEL_TSS,0x38 # TSS + .set SEL_SCODE,0x8 // Supervisor code + .set SEL_SDATA,0x10 // Supervisor data + .set SEL_RCODE,0x18 // Real mode code + .set SEL_RDATA,0x20 // Real mode data + .set SEL_UCODE,0x28|3 // User code + .set SEL_UDATA,0x30|3 // User data + .set SEL_TSS,0x38 // TSS /* * Task state segment fields. */ - .set TSS_ESP0,0x4 # PL 0 ESP - .set TSS_SS0,0x8 # PL 0 SS - .set TSS_ESP1,0xc # PL 1 ESP - .set TSS_MAP,0x66 # I/O bit map base + .set TSS_ESP0,0x4 // PL 0 ESP + .set TSS_SS0,0x8 // PL 0 SS + .set TSS_ESP1,0xc // PL 1 ESP + .set TSS_MAP,0x66 // I/O bit map base /* * System calls. */ - .set SYS_EXIT,0x0 # Exit - .set SYS_EXEC,0x1 # Exec + .set SYS_EXIT,0x0 // Exit + .set SYS_EXEC,0x1 // Exec /* * V86 constants. */ - .set V86_FLG,0x208eff # V86 flag mask - .set V86_STK,0x400 # V86 stack allowance + .set V86_FLG,0x208eff // V86 flag mask + .set V86_STK,0x400 // V86 stack allowance /* * Dump format control bytes. */ - .set DMP_X16,0x1 # Word - .set DMP_X32,0x2 # Long - .set DMP_MEM,0x4 # Memory - .set DMP_EOL,0x8 # End of line + .set DMP_X16,0x1 // Word + .set DMP_X32,0x2 // Long + .set DMP_MEM,0x4 // Memory + .set DMP_EOL,0x8 // End of line /* * Screen defaults and assumptions. */ - .set SCR_MAT,0x7 # Mode/attribute - .set SCR_COL,0x50 # Columns per row - .set SCR_ROW,0x19 # Rows per screen + .set SCR_MAT,0x7 // Mode/attribute + .set SCR_COL,0x50 // Columns per row + .set SCR_ROW,0x19 // Rows per screen /* * BIOS Data Area locations. */ - .set BDA_MEM,0x413 # Free memory - .set BDA_KEYFLAGS,0x417 # Keyboard shift-state flags - .set BDA_SCR,0x449 # Video mode - .set BDA_POS,0x450 # Cursor position - .set BDA_BOOT,0x472 # Boot howto flag + .set BDA_MEM,0x413 // Free memory + .set BDA_KEYFLAGS,0x417 // Keyboard shift-state flags + .set BDA_SCR,0x449 // Video mode + .set BDA_POS,0x450 // Cursor position + .set BDA_BOOT,0x472 // Boot howto flag /* * Derivations, for brevity. */ - .set _ESP0H,MEM_ESP0>>0x8 # Byte 1 of ESP0 - .set _ESP1H,MEM_ESP1>>0x8 # Byte 1 of ESP1 - .set _TSSIO,MEM_MAP-MEM_TSS # TSS I/O base - .set _TSSLM,MEM_DIR-MEM_TSS-1 # TSS limit - .set _IDTLM,MEM_TSS-MEM_IDT-1 # IDT limit + .set _ESP0H,MEM_ESP0>>0x8 // Byte 1 of ESP0 + .set _ESP1H,MEM_ESP1>>0x8 // Byte 1 of ESP1 + .set _TSSIO,MEM_MAP-MEM_TSS // TSS I/O base + .set _TSSLM,MEM_DIR-MEM_TSS-1 // TSS limit + .set _IDTLM,MEM_TSS-MEM_IDT-1 // IDT limit /* * Code segment. */ .globl start .code16 -start: # Start of code +start: // Start of code /* * BTX header. */ -btx_hdr: .byte 0xeb # Machine ID - .byte 0xe # Header size - .ascii "BTX" # Magic - .byte 0x1 # Major version - .byte 0x1 # Minor version - .byte BTX_FLAGS # Flags - .word PAG_CNT-MEM_ORG>>0xc # Paging control - .word break-start # Text size - .long 0x0 # Entry address +btx_hdr: .byte 0xeb // Machine ID + .byte 0xe // Header size + .ascii "BTX" // Magic + .byte 0x1 // Major version + .byte 0x1 // Minor version + .byte BTX_FLAGS // Flags + .word PAG_CNT-MEM_ORG>>0xc // Paging control + .word break-start // Text size + .long 0x0 // Entry address /* * Initialization routine. */ -init: cli # Disable interrupts - xor %ax,%ax # Zero/segment - mov %ax,%ss # Set up - mov $MEM_ESP0,%sp # stack - mov %ax,%es # Address - mov %ax,%ds # data - pushl $0x2 # Clear - popfl # flags +init: cli // Disable interrupts + xor %ax,%ax // Zero/segment + mov %ax,%ss // Set up + mov $MEM_ESP0,%sp // stack + mov %ax,%es // Address + mov %ax,%ds // data + pushl $0x2 // Clear + popfl // flags /* * Initialize memory. */ - mov $MEM_IDT,%di # Memory to initialize - mov $(MEM_ORG-MEM_IDT)/2,%cx # Words to zero - push %di # Save - rep # Zero-fill - stosw # memory - pop %di # Restore + mov $MEM_IDT,%di // Memory to initialize + mov $(MEM_ORG-MEM_IDT)/2,%cx // Words to zero + push %di // Save + rep // Zero-fill + stosw // memory + pop %di // Restore /* * Create IDT. */ - mov $idtctl,%si # Control string -init.1: lodsb # Get entry - cbw # count - xchg %ax,%cx # as word - jcxz init.4 # If done - lodsb # Get segment - xchg %ax,%dx # P:DPL:type - lodsw # Get control - xchg %ax,%bx # set - lodsw # Get handler offset - mov $SEL_SCODE,%dh # Segment selector -init.2: shr %bx # Handle this int? - jnc init.3 # No - mov %ax,(%di) # Set handler offset - mov %dh,0x2(%di) # and selector - mov %dl,0x5(%di) # Set P:DPL:type - add $0x4,%ax # Next handler -init.3: lea 0x8(%di),%di # Next entry - loop init.2 # Till set done - jmp init.1 # Continue + mov $idtctl,%si // Control string +init.1: lodsb // Get entry + cbw // count + xchg %ax,%cx // as word + jcxz init.4 // If done + lodsb // Get segment + xchg %ax,%dx // P:DPL:type + lodsw // Get control + xchg %ax,%bx // set + lodsw // Get handler offset + mov $SEL_SCODE,%dh // Segment selector +init.2: shr %bx // Handle this int? + jnc init.3 // No + mov %ax,(%di) // Set handler offset + mov %dh,0x2(%di) // and selector + mov %dl,0x5(%di) // Set P:DPL:type + add $0x4,%ax // Next handler +init.3: lea 0x8(%di),%di // Next entry + loop init.2 // Till set done + jmp init.1 // Continue /* * Initialize TSS. */ -init.4: movb $_ESP0H,TSS_ESP0+1(%di) # Set ESP0 - movb $SEL_SDATA,TSS_SS0(%di) # Set SS0 - movb $_ESP1H,TSS_ESP1+1(%di) # Set ESP1 - movb $_TSSIO,TSS_MAP(%di) # Set I/O bit map base +init.4: movb $_ESP0H,TSS_ESP0+1(%di) // Set ESP0 + movb $SEL_SDATA,TSS_SS0(%di) // Set SS0 + movb $_ESP1H,TSS_ESP1+1(%di) // Set ESP1 + movb $_TSSIO,TSS_MAP(%di) // Set I/O bit map base #ifdef PAGING /* * Create page directory. */ - xor %edx,%edx # Page - mov $PAG_SIZ>>0x8,%dh # size - xor %eax,%eax # Zero - mov $MEM_DIR,%di # Page directory - mov $PAG_CNT>>0xa,%cl # Entries - mov $MEM_TBL|0x7,%ax # First entry -init.5: stosl # Write entry - add %dx,%ax # To next - loop init.5 # Till done + xor %edx,%edx // Page + mov $PAG_SIZ>>0x8,%dh // size + xor %eax,%eax // Zero + mov $MEM_DIR,%di // Page directory + mov $PAG_CNT>>0xa,%cl // Entries + mov $MEM_TBL|0x7,%ax // First entry +init.5: stosl // Write entry + add %dx,%ax // To next + loop init.5 // Till done /* * Create page tables. */ - mov $MEM_TBL,%di # Page table - mov $PAG_CNT>>0x8,%ch # Entries - xor %ax,%ax # Start address -init.6: mov $0x7,%al # Set U:W:P flags - cmp btx_hdr+0x8,%cx # Standard user page? - jb init.7 # Yes - cmp $PAG_CNT-MEM_BTX>>0xc,%cx # BTX memory? - jae init.7 # No or first page - and $~0x2,%al # Clear W flag - cmp $PAG_CNT-MEM_USR>>0xc,%cx # User page zero? - jne init.7 # No - testb $0x80,btx_hdr+0x7 # Unmap it? - jz init.7 # No - and $~0x1,%al # Clear P flag -init.7: stosl # Set entry - add %edx,%eax # Next address - loop init.6 # Till done + mov $MEM_TBL,%di // Page table + mov $PAG_CNT>>0x8,%ch // Entries + xor %ax,%ax // Start address +init.6: mov $0x7,%al // Set U:W:P flags + cmp btx_hdr+0x8,%cx // Standard user page? + jb init.7 // Yes + cmp $PAG_CNT-MEM_BTX>>0xc,%cx // BTX memory? + jae init.7 // No or first page + and $~0x2,%al // Clear W flag + cmp $PAG_CNT-MEM_USR>>0xc,%cx // User page zero? + jne init.7 // No + testb $0x80,btx_hdr+0x7 // Unmap it? + jz init.7 // No + and $~0x1,%al // Clear P flag +init.7: stosl // Set entry + add %edx,%eax // Next address + loop init.6 // Till done #endif /* * Bring up the system. */ - mov $0x2820,%bx # Set protected mode - callw setpic # IRQ offsets - lidt idtdesc # Set IDT + mov $0x2820,%bx // Set protected mode + callw setpic // IRQ offsets + lidt idtdesc // Set IDT #ifdef PAGING - xor %eax,%eax # Set base - mov $MEM_DIR>>0x8,%ah # of page - mov %eax,%cr3 # directory + xor %eax,%eax // Set base + mov $MEM_DIR>>0x8,%ah // of page + mov %eax,%cr3 // directory #endif - lgdt gdtdesc # Set GDT - mov %cr0,%eax # Switch to protected + lgdt gdtdesc // Set GDT + mov %cr0,%eax // Switch to protected #ifdef PAGING - or $0x80000001,%eax # mode and enable paging + or $0x80000001,%eax // mode and enable paging #else - or $0x01,%eax # mode + or $0x01,%eax // mode #endif - mov %eax,%cr0 # - ljmp $SEL_SCODE,$init.8 # To 32-bit code + mov %eax,%cr0 // + ljmp $SEL_SCODE,$init.8 // To 32-bit code .code32 -init.8: xorl %ecx,%ecx # Zero - movb $SEL_SDATA,%cl # To 32-bit - movw %cx,%ss # stack +init.8: xorl %ecx,%ecx // Zero + movb $SEL_SDATA,%cl // To 32-bit + movw %cx,%ss // stack /* * Launch user task. */ - movb $SEL_TSS,%cl # Set task - ltr %cx # register - movl $MEM_USR,%edx # User base address - movzwl %ss:BDA_MEM,%eax # Get free memory - shll $0xa,%eax # To bytes - subl $0x1000,%eax # Less arg space - subl %edx,%eax # Less base - movb $SEL_UDATA,%cl # User data selector - pushl %ecx # Set SS - pushl %eax # Set ESP - push $0x202 # Set flags (IF set) - push $SEL_UCODE # Set CS - pushl btx_hdr+0xc # Set EIP - pushl %ecx # Set GS - pushl %ecx # Set FS - pushl %ecx # Set DS - pushl %ecx # Set ES - pushl %edx # Set EAX - movb $0x7,%cl # Set remaining -init.9: push $0x0 # general - loop init.9 # registers + movb $SEL_TSS,%cl // Set task + ltr %cx // register + movl $MEM_USR,%edx // User base address + movzwl %ss:BDA_MEM,%eax // Get free memory + shll $0xa,%eax // To bytes + subl $0x1000,%eax // Less arg space + subl %edx,%eax // Less base + movb $SEL_UDATA,%cl // User data selector + pushl %ecx // Set SS + pushl %eax // Set ESP + push $0x202 // Set flags (IF set) + push $SEL_UCODE // Set CS + pushl btx_hdr+0xc // Set EIP + pushl %ecx // Set GS + pushl %ecx // Set FS + pushl %ecx // Set DS + pushl %ecx // Set ES + pushl %edx // Set EAX + movb $0x7,%cl // Set remaining +init.9: push $0x0 // general + loop init.9 // registers #ifdef BTX_SERIAL - call sio_init # setup the serial console + call sio_init // setup the serial console #endif - popa # and initialize - popl %es # Initialize - popl %ds # user - popl %fs # segment - popl %gs # registers - iret # To user mode + popa // and initialize + popl %es // Initialize + popl %ds // user + popl %fs // segment + popl %gs // registers + iret // To user mode /* * Exit routine. */ -exit: cli # Disable interrupts - movl $MEM_ESP0,%esp # Clear stack +exit: cli // Disable interrupts + movl $MEM_ESP0,%esp // Clear stack /* * Turn off paging. */ - movl %cr0,%eax # Get CR0 - andl $~0x80000000,%eax # Disable - movl %eax,%cr0 # paging - xorl %ecx,%ecx # Zero - movl %ecx,%cr3 # Flush TLB + movl %cr0,%eax // Get CR0 + andl $~0x80000000,%eax // Disable + movl %eax,%cr0 // paging + xorl %ecx,%ecx // Zero + movl %ecx,%cr3 // Flush TLB /* * Restore the GDT in case we caught a kernel trap. */ - lgdt gdtdesc # Set GDT + lgdt gdtdesc // Set GDT /* * To 16 bits. */ - ljmpw $SEL_RCODE,$exit.1 # Reload CS + ljmpw $SEL_RCODE,$exit.1 // Reload CS .code16 -exit.1: mov $SEL_RDATA,%cl # 16-bit selector - mov %cx,%ss # Reload SS - mov %cx,%ds # Load - mov %cx,%es # remaining - mov %cx,%fs # segment - mov %cx,%gs # registers +exit.1: mov $SEL_RDATA,%cl // 16-bit selector + mov %cx,%ss // Reload SS + mov %cx,%ds // Load + mov %cx,%es // remaining + mov %cx,%fs // segment + mov %cx,%gs // registers /* * To real-address mode. */ - dec %ax # Switch to - mov %eax,%cr0 # real mode - ljmp $0x0,$exit.2 # Reload CS -exit.2: xor %ax,%ax # Real mode segment - mov %ax,%ss # Reload SS - mov %ax,%ds # Address data - mov $0x7008,%bx # Set real mode - callw setpic # IRQ offsets - lidt ivtdesc # Set IVT + dec %ax // Switch to + mov %eax,%cr0 // real mode + ljmp $0x0,$exit.2 // Reload CS +exit.2: xor %ax,%ax // Real mode segment + mov %ax,%ss // Reload SS + mov %ax,%ds // Address data + mov $0x7008,%bx // Set real mode + callw setpic // IRQ offsets + lidt ivtdesc // Set IVT /* * Reboot or await reset. */ - sti # Enable interrupts - testb $0x1,btx_hdr+0x7 # Reboot? -exit.3: jz exit.3 # No - movw $0x1234, BDA_BOOT # Do a warm boot - ljmp $0xf000,$0xfff0 # reboot the machine + sti // Enable interrupts + testb $0x1,btx_hdr+0x7 // Reboot? +exit.3: jz exit.3 // No + movw $0x1234, BDA_BOOT // Do a warm boot + ljmp $0xf000,$0xfff0 // reboot the machine /* * Set IRQ offsets by reprogramming 8259A PICs. */ -setpic: in $0x21,%al # Save master - push %ax # IMR - in $0xa1,%al # Save slave - push %ax # IMR - movb $0x11,%al # ICW1 to - outb %al,$0x20 # master, - outb %al,$0xa0 # slave - movb %bl,%al # ICW2 to - outb %al,$0x21 # master - movb %bh,%al # ICW2 to - outb %al,$0xa1 # slave - movb $0x4,%al # ICW3 to - outb %al,$0x21 # master - movb $0x2,%al # ICW3 to - outb %al,$0xa1 # slave - movb $0x1,%al # ICW4 to - outb %al,$0x21 # master, - outb %al,$0xa1 # slave - pop %ax # Restore slave - outb %al,$0xa1 # IMR - pop %ax # Restore master - outb %al,$0x21 # IMR - retw # To caller +setpic: in $0x21,%al // Save master + push %ax // IMR + in $0xa1,%al // Save slave + push %ax // IMR + movb $0x11,%al // ICW1 to + outb %al,$0x20 // master, + outb %al,$0xa0 // slave + movb %bl,%al // ICW2 to + outb %al,$0x21 // master + movb %bh,%al // ICW2 to + outb %al,$0xa1 // slave + movb $0x4,%al // ICW3 to + outb %al,$0x21 // master + movb $0x2,%al // ICW3 to + outb %al,$0xa1 // slave + movb $0x1,%al // ICW4 to + outb %al,$0x21 // master, + outb %al,$0xa1 // slave + pop %ax // Restore slave + outb %al,$0xa1 // IMR + pop %ax // Restore master + outb %al,$0x21 // IMR + retw // To caller .code32 /* * Initiate return from V86 mode to user mode. */ -inthlt: hlt # To supervisor mode +inthlt: hlt // To supervisor mode /* * Exception jump table. */ -intx00: push $0x0 # Int 0x0: #DE - jmp ex_noc # Divide error - push $0x1 # Int 0x1: #DB - jmp ex_noc # Debug - push $0x3 # Int 0x3: #BP - jmp ex_noc # Breakpoint - push $0x4 # Int 0x4: #OF - jmp ex_noc # Overflow - push $0x5 # Int 0x5: #BR - jmp ex_noc # BOUND range exceeded - push $0x6 # Int 0x6: #UD - jmp ex_noc # Invalid opcode - push $0x7 # Int 0x7: #NM - jmp ex_noc # Device not available - push $0x8 # Int 0x8: #DF - jmp except # Double fault - push $0xa # Int 0xa: #TS - jmp except # Invalid TSS - push $0xb # Int 0xb: #NP - jmp except # Segment not present - push $0xc # Int 0xc: #SS - jmp except # Stack segment fault - push $0xd # Int 0xd: #GP - jmp ex_v86 # General protection - push $0xe # Int 0xe: #PF - jmp except # Page fault -intx10: push $0x10 # Int 0x10: #MF - jmp ex_noc # Floating-point error +intx00: push $0x0 // Int 0x0: #DE + jmp ex_noc // Divide error + push $0x1 // Int 0x1: #DB + jmp ex_noc // Debug + push $0x3 // Int 0x3: #BP + jmp ex_noc // Breakpoint + push $0x4 // Int 0x4: #OF + jmp ex_noc // Overflow + push $0x5 // Int 0x5: #BR + jmp ex_noc // BOUND range exceeded + push $0x6 // Int 0x6: #UD + jmp ex_noc // Invalid opcode + push $0x7 // Int 0x7: #NM + jmp ex_noc // Device not available + push $0x8 // Int 0x8: #DF + jmp except // Double fault + push $0xa // Int 0xa: #TS + jmp except // Invalid TSS + push $0xb // Int 0xb: #NP + jmp except // Segment not present + push $0xc // Int 0xc: #SS + jmp except // Stack segment fault + push $0xd // Int 0xd: #GP + jmp ex_v86 // General protection + push $0xe // Int 0xe: #PF + jmp except // Page fault +intx10: push $0x10 // Int 0x10: #MF + jmp ex_noc // Floating-point error /* * Handle #GP exception. */ -ex_v86: testb $0x2,0x12(%esp,1) # V86 mode? - jz except # No - jmp v86mon # To monitor +ex_v86: testb $0x2,0x12(%esp,1) // V86 mode? + jz except // No + jmp v86mon // To monitor /* * Save a zero error code. */ -ex_noc: pushl (%esp,1) # Duplicate int no - movb $0x0,0x4(%esp,1) # Fake error code +ex_noc: pushl (%esp,1) // Duplicate int no + movb $0x0,0x4(%esp,1) // Fake error code /* * Handle exception. */ -except: cld # String ops inc - pushl %ds # Save - pushl %es # most - pusha # registers - movb $0x6,%al # Push loop count - testb $0x2,0x3a(%esp,1) # V86 mode? - jnz except.1 # Yes - pushl %gs # Set GS - pushl %fs # Set FS - pushl %ds # Set DS - pushl %es # Set ES - movb $0x2,%al # Push loop count - cmpw $SEL_SCODE,0x44(%esp,1) # Supervisor mode? - jne except.1 # No - pushl %ss # Set SS - leal 0x50(%esp,1),%eax # Set - pushl %eax # ESP - jmp except.2 # Join common code -except.1: pushl 0x50(%esp,1) # Set GS, FS, DS, ES - decb %al # (if V86 mode), and - jne except.1 # SS, ESP -except.2: push $SEL_SDATA # Set up - popl %ds # to - pushl %ds # address - popl %es # data - movl %esp,%ebx # Stack frame - movl $dmpfmt,%esi # Dump format string - movl $MEM_BUF,%edi # Buffer - pushl %edi # Dump to - call dump # buffer - popl %esi # and - call putstr # display - leal 0x18(%esp,1),%esp # Discard frame - popa # Restore - popl %es # registers - popl %ds # saved - cmpb $0x3,(%esp,1) # Breakpoint? - je except.3 # Yes - cmpb $0x1,(%esp,1) # Debug? - jne except.2a # No - testl $0x100,0x10(%esp,1) # Trap flag set? - jnz except.3 # Yes -except.2a: jmp exit # Exit -except.3: leal 0x8(%esp,1),%esp # Discard err, int no - iret # From interrupt +except: cld // String ops inc + pushl %ds // Save + pushl %es // most + pusha // registers + movb $0x6,%al // Push loop count + testb $0x2,0x3a(%esp,1) // V86 mode? + jnz except.1 // Yes + pushl %gs // Set GS + pushl %fs // Set FS + pushl %ds // Set DS + pushl %es // Set ES + movb $0x2,%al // Push loop count + cmpw $SEL_SCODE,0x44(%esp,1) // Supervisor mode? + jne except.1 // No + pushl %ss // Set SS + leal 0x50(%esp,1),%eax // Set + pushl %eax // ESP + jmp except.2 // Join common code +except.1: pushl 0x50(%esp,1) // Set GS, FS, DS, ES + decb %al // (if V86 mode), and + jne except.1 // SS, ESP +except.2: push $SEL_SDATA // Set up + popl %ds // to + pushl %ds // address + popl %es // data + movl %esp,%ebx // Stack frame + movl $dmpfmt,%esi // Dump format string + movl $MEM_BUF,%edi // Buffer + pushl %edi // Dump to + call dump // buffer + popl %esi // and + call putstr // display + leal 0x18(%esp,1),%esp // Discard frame + popa // Restore + popl %es // registers + popl %ds // saved + cmpb $0x3,(%esp,1) // Breakpoint? + je except.3 // Yes + cmpb $0x1,(%esp,1) // Debug? + jne except.2a // No + testl $0x100,0x10(%esp,1) // Trap flag set? + jnz except.3 // Yes +except.2a: jmp exit // Exit +except.3: leal 0x8(%esp,1),%esp // Discard err, int no + iret // From interrupt /* * Return to user mode from V86 mode. */ -intrtn: cld # String ops inc - pushl %ds # Address - popl %es # data - leal 0x3c(%ebp),%edx # V86 Segment registers - movl MEM_TSS+TSS_ESP1,%esi # Link stack pointer - lodsl # INT_V86 args pointer - movl %esi,%ebx # Saved exception frame - testl %eax,%eax # INT_V86 args? - jz intrtn.2 # No - movl $MEM_USR,%edi # User base - movl 0x1c(%esi),%ebx # User ESP - movl %eax,(%edi,%ebx,1) # Restore to user stack - leal 0x8(%edi,%eax,1),%edi # Arg segment registers - testb $0x4,-0x6(%edi) # Return flags? - jz intrtn.1 # No - movl 0x30(%ebp),%eax # Get V86 flags - movw %ax,0x18(%esi) # Set user flags -intrtn.1: leal 0x10(%esi),%ebx # Saved exception frame - xchgl %edx,%esi # Segment registers - movb $0x4,%cl # Update seg regs - rep # in INT_V86 - movsl # args -intrtn.2: movl %edx,%esi # Segment registers - leal 0x28(%ebp),%edi # Set up seg - movb $0x4,%cl # regs for - rep # later - movsl # pop - movl %ebx,%esi # Restore exception - movb $0x5,%cl # frame to - rep # supervisor - movsl # stack - movl %esi,MEM_TSS+TSS_ESP1 # Link stack pointer - popa # Restore - leal 0x8(%esp,1),%esp # Discard err, int no - popl %es # Restore - popl %ds # user - popl %fs # segment - popl %gs # registers - iret # To user mode +intrtn: cld // String ops inc + pushl %ds // Address + popl %es // data + leal 0x3c(%ebp),%edx // V86 Segment registers + movl MEM_TSS+TSS_ESP1,%esi // Link stack pointer + lodsl // INT_V86 args pointer + movl %esi,%ebx // Saved exception frame + testl %eax,%eax // INT_V86 args? + jz intrtn.2 // No + movl $MEM_USR,%edi // User base + movl 0x1c(%esi),%ebx // User ESP + movl %eax,(%edi,%ebx,1) // Restore to user stack + leal 0x8(%edi,%eax,1),%edi // Arg segment registers + testb $0x4,-0x6(%edi) // Return flags? + jz intrtn.1 // No + movl 0x30(%ebp),%eax // Get V86 flags + movw %ax,0x18(%esi) // Set user flags +intrtn.1: leal 0x10(%esi),%ebx // Saved exception frame + xchgl %edx,%esi // Segment registers + movb $0x4,%cl // Update seg regs + rep // in INT_V86 + movsl // args +intrtn.2: movl %edx,%esi // Segment registers + leal 0x28(%ebp),%edi // Set up seg + movb $0x4,%cl // regs for + rep // later + movsl // pop + movl %ebx,%esi // Restore exception + movb $0x5,%cl // frame to + rep // supervisor + movsl // stack + movl %esi,MEM_TSS+TSS_ESP1 // Link stack pointer + popa // Restore + leal 0x8(%esp,1),%esp // Discard err, int no + popl %es // Restore + popl %ds // user + popl %fs // segment + popl %gs // registers + iret // To user mode /* * V86 monitor. */ -v86mon: cld # String ops inc - pushl $SEL_SDATA # Set up for - popl %ds # flat addressing - pusha # Save registers - movl %esp,%ebp # Address stack frame - movzwl 0x2c(%ebp),%edi # Load V86 CS - shll $0x4,%edi # To linear - movl 0x28(%ebp),%esi # Load V86 IP - addl %edi,%esi # Code pointer - xorl %ecx,%ecx # Zero - movb $0x2,%cl # 16-bit operands - xorl %eax,%eax # Zero -v86mon.1: lodsb # Get opcode - cmpb $0x66,%al # Operand size prefix? - jne v86mon.2 # No - movb $0x4,%cl # 32-bit operands - jmp v86mon.1 # Continue -v86mon.2: cmpb $0xf4,%al # HLT? - jne v86mon.3 # No - cmpl $inthlt+0x1,%esi # Is inthlt? - jne v86mon.7 # No (ignore) - jmp intrtn # Return to user mode -v86mon.3: cmpb $0xf,%al # Prefixed instruction? - jne v86mon.4 # No - cmpb $0x09,(%esi) # Is it a WBINVD? - je v86wbinvd # Yes - cmpb $0x30,(%esi) # Is it a WRMSR? - je v86wrmsr # Yes - cmpb $0x32,(%esi) # Is it a RDMSR? - je v86rdmsr # Yes - cmpb $0x20,(%esi) # Is this a - jne v86mon.4 # MOV EAX,CR0 - cmpb $0xc0,0x1(%esi) # instruction? - je v86mov # Yes -v86mon.4: cmpb $0xfa,%al # CLI? - je v86cli # Yes - cmpb $0xfb,%al # STI? - je v86sti # Yes - movzwl 0x38(%ebp),%ebx # Load V86 SS - shll $0x4,%ebx # To offset - pushl %ebx # Save - addl 0x34(%ebp),%ebx # Add V86 SP - movl 0x30(%ebp),%edx # Load V86 flags - cmpb $0x9c,%al # PUSHF/PUSHFD? - je v86pushf # Yes - cmpb $0x9d,%al # POPF/POPFD? - je v86popf # Yes - cmpb $0xcd,%al # INT imm8? - je v86intn # Yes - cmpb $0xcf,%al # IRET/IRETD? - je v86iret # Yes - popl %ebx # Restore - popa # Restore - jmp except # Handle exception -v86mon.5: movl %edx,0x30(%ebp) # Save V86 flags -v86mon.6: popl %edx # V86 SS adjustment - subl %edx,%ebx # Save V86 - movl %ebx,0x34(%ebp) # SP -v86mon.7: subl %edi,%esi # From linear - movl %esi,0x28(%ebp) # Save V86 IP - popa # Restore - leal 0x8(%esp,1),%esp # Discard int no, error - iret # To V86 mode +v86mon: cld // String ops inc + pushl $SEL_SDATA // Set up for + popl %ds // flat addressing + pusha // Save registers + movl %esp,%ebp // Address stack frame + movzwl 0x2c(%ebp),%edi // Load V86 CS + shll $0x4,%edi // To linear + movl 0x28(%ebp),%esi // Load V86 IP + addl %edi,%esi // Code pointer + xorl %ecx,%ecx // Zero + movb $0x2,%cl // 16-bit operands + xorl %eax,%eax // Zero +v86mon.1: lodsb // Get opcode + cmpb $0x66,%al // Operand size prefix? + jne v86mon.2 // No + movb $0x4,%cl // 32-bit operands + jmp v86mon.1 // Continue +v86mon.2: cmpb $0xf4,%al // HLT? + jne v86mon.3 // No + cmpl $inthlt+0x1,%esi // Is inthlt? + jne v86mon.7 // No (ignore) + jmp intrtn // Return to user mode +v86mon.3: cmpb $0xf,%al // Prefixed instruction? + jne v86mon.4 // No + cmpb $0x09,(%esi) // Is it a WBINVD? + je v86wbinvd // Yes + cmpb $0x30,(%esi) // Is it a WRMSR? + je v86wrmsr // Yes + cmpb $0x32,(%esi) // Is it a RDMSR? + je v86rdmsr // Yes + cmpb $0x20,(%esi) // Is this a + jne v86mon.4 // MOV EAX,CR0 + cmpb $0xc0,0x1(%esi) // instruction? + je v86mov // Yes +v86mon.4: cmpb $0xfa,%al // CLI? + je v86cli // Yes + cmpb $0xfb,%al // STI? + je v86sti // Yes + movzwl 0x38(%ebp),%ebx // Load V86 SS + shll $0x4,%ebx // To offset + pushl %ebx // Save + addl 0x34(%ebp),%ebx // Add V86 SP + movl 0x30(%ebp),%edx // Load V86 flags + cmpb $0x9c,%al // PUSHF/PUSHFD? + je v86pushf // Yes + cmpb $0x9d,%al // POPF/POPFD? + je v86popf // Yes + cmpb $0xcd,%al // INT imm8? + je v86intn // Yes + cmpb $0xcf,%al // IRET/IRETD? + je v86iret // Yes + popl %ebx // Restore + popa // Restore + jmp except // Handle exception +v86mon.5: movl %edx,0x30(%ebp) // Save V86 flags +v86mon.6: popl %edx // V86 SS adjustment + subl %edx,%ebx // Save V86 + movl %ebx,0x34(%ebp) // SP +v86mon.7: subl %edi,%esi // From linear + movl %esi,0x28(%ebp) // Save V86 IP + popa // Restore + leal 0x8(%esp,1),%esp // Discard int no, error + iret // To V86 mode /* * Emulate MOV EAX,CR0. */ -v86mov: movl %cr0,%eax # CR0 to - movl %eax,0x1c(%ebp) # saved EAX - incl %esi # Adjust IP +v86mov: movl %cr0,%eax // CR0 to + movl %eax,0x1c(%ebp) // saved EAX + incl %esi // Adjust IP /* * Return from emulating a 0x0f prefixed instruction */ -v86preret: incl %esi # Adjust IP - jmp v86mon.7 # Finish up +v86preret: incl %esi // Adjust IP + jmp v86mon.7 // Finish up /* * Emulate WBINVD */ -v86wbinvd: wbinvd # Write back and invalidate - # cache - jmp v86preret # Finish up +v86wbinvd: wbinvd // Write back and invalidate + // cache + jmp v86preret // Finish up /* * Emulate WRMSR */ -v86wrmsr: movl 0x18(%ebp),%ecx # Get user's %ecx (MSR to write) - movl 0x14(%ebp),%edx # Load the value - movl 0x1c(%ebp),%eax # to write - wrmsr # Write MSR - jmp v86preret # Finish up +v86wrmsr: movl 0x18(%ebp),%ecx // Get user's %ecx + // (MSR to write) + movl 0x14(%ebp),%edx // Load the value + movl 0x1c(%ebp),%eax // to write + wrmsr // Write MSR + jmp v86preret // Finish up /* * Emulate RDMSR */ -v86rdmsr: movl 0x18(%ebp),%ecx # MSR to read - rdmsr # Read the MSR - movl %eax,0x1c(%ebp) # Return the value of - movl %edx,0x14(%ebp) # the MSR to the user - jmp v86preret # Finish up +v86rdmsr: movl 0x18(%ebp),%ecx // MSR to read + rdmsr // Read the MSR + movl %eax,0x1c(%ebp) // Return the value of + movl %edx,0x14(%ebp) // the MSR to the user + jmp v86preret // Finish up /* * Emulate CLI. */ -v86cli: andb $~0x2,0x31(%ebp) # Clear IF - jmp v86mon.7 # Finish up +v86cli: andb $~0x2,0x31(%ebp) // Clear IF + jmp v86mon.7 // Finish up /* * Emulate STI. */ -v86sti: orb $0x2,0x31(%ebp) # Set IF - jmp v86mon.7 # Finish up +v86sti: orb $0x2,0x31(%ebp) // Set IF + jmp v86mon.7 // Finish up /* * Emulate PUSHF/PUSHFD. */ -v86pushf: subl %ecx,%ebx # Adjust SP - cmpb $0x4,%cl # 32-bit - je v86pushf.1 # Yes - data16 # 16-bit -v86pushf.1: movl %edx,(%ebx) # Save flags - jmp v86mon.6 # Finish up +v86pushf: subl %ecx,%ebx // Adjust SP + cmpb $0x4,%cl // 32-bit + je v86pushf.1 // Yes + data16 // 16-bit +v86pushf.1: movl %edx,(%ebx) // Save flags + jmp v86mon.6 // Finish up /* * Emulate IRET/IRETD. */ -v86iret: movzwl (%ebx),%esi # Load V86 IP - movzwl 0x2(%ebx),%edi # Load V86 CS - leal 0x4(%ebx),%ebx # Adjust SP - movl %edi,0x2c(%ebp) # Save V86 CS - xorl %edi,%edi # No ESI adjustment +v86iret: movzwl (%ebx),%esi // Load V86 IP + movzwl 0x2(%ebx),%edi // Load V86 CS + leal 0x4(%ebx),%ebx // Adjust SP + movl %edi,0x2c(%ebp) // Save V86 CS + xorl %edi,%edi // No ESI adjustment /* * Emulate POPF/POPFD (and remainder of IRET/IRETD). */ -v86popf: cmpb $0x4,%cl # 32-bit? - je v86popf.1 # Yes - movl %edx,%eax # Initialize - data16 # 16-bit -v86popf.1: movl (%ebx),%eax # Load flags - addl %ecx,%ebx # Adjust SP - andl $V86_FLG,%eax # Merge - andl $~V86_FLG,%edx # the - orl %eax,%edx # flags - jmp v86mon.5 # Finish up +v86popf: cmpb $0x4,%cl // 32-bit? + je v86popf.1 // Yes + movl %edx,%eax // Initialize + data16 // 16-bit +v86popf.1: movl (%ebx),%eax // Load flags + addl %ecx,%ebx // Adjust SP + andl $V86_FLG,%eax // Merge + andl $~V86_FLG,%edx // the + orl %eax,%edx // flags + jmp v86mon.5 // Finish up /* * trap int 15, function 87 * reads %es:%si from saved registers on stack to find a GDT containing @@ -606,566 +607,566 @@ v86popf.1: movl (%ebx),%eax # Load flags * reads count of words from saved %cx * returns success by setting %ah to 0 */ -int15_87: pushl %eax # Save - pushl %ebx # some information - pushl %esi # onto the stack. +int15_87: pushl %eax // Save + pushl %ebx // some information + pushl %esi // onto the stack. pushl %edi - xorl %eax,%eax # clean EAX - xorl %ebx,%ebx # clean EBX - movl 0x4(%ebp),%esi # Get user's ESI - movl 0x3C(%ebp),%ebx # store ES - movw %si,%ax # store SI - shll $0x4,%ebx # Make it a seg. - addl %eax,%ebx # ebx=(es<<4)+si - movb 0x14(%ebx),%al # Grab the - movb 0x17(%ebx),%ah # necessary - shll $0x10,%eax # information - movw 0x12(%ebx),%ax # from - movl %eax,%esi # the - movb 0x1c(%ebx),%al # GDT in order to - movb 0x1f(%ebx),%ah # have %esi offset - shll $0x10,%eax # of source and %edi - movw 0x1a(%ebx),%ax # of destination. + xorl %eax,%eax // clean EAX + xorl %ebx,%ebx // clean EBX + movl 0x4(%ebp),%esi // Get user's ESI + movl 0x3C(%ebp),%ebx // store ES + movw %si,%ax // store SI + shll $0x4,%ebx // Make it a seg. + addl %eax,%ebx // ebx=(es<<4)+si + movb 0x14(%ebx),%al // Grab the + movb 0x17(%ebx),%ah // necessary + shll $0x10,%eax // information + movw 0x12(%ebx),%ax // from + movl %eax,%esi // the + movb 0x1c(%ebx),%al // GDT in order to + movb 0x1f(%ebx),%ah // have %esi offset + shll $0x10,%eax // of source and %edi + movw 0x1a(%ebx),%ax // of destination. movl %eax,%edi - pushl %ds # Make: - popl %es # es = ds - pushl %ecx # stash ECX - xorl %ecx,%ecx # highw of ECX is clear - movw 0x18(%ebp),%cx # Get user's ECX - shll $0x1,%ecx # Convert from num words to num - # bytes - rep # repeat... - movsb # perform copy. - popl %ecx # Restore + pushl %ds // Make: + popl %es // es = ds + pushl %ecx // stash ECX + xorl %ecx,%ecx // highw of ECX is clear + movw 0x18(%ebp),%cx // Get user's ECX + shll $0x1,%ecx // Convert from num words to num + // bytes + rep // repeat... + movsb // perform copy. + popl %ecx // Restore popl %edi - popl %esi # previous - popl %ebx # register - popl %eax # values. - movb $0x0,0x1d(%ebp) # set ah = 0 to indicate - # success - andb $0xfe,%dl # clear CF - jmp v86mon.5 # Finish up + popl %esi // previous + popl %ebx // register + popl %eax // values. + movb $0x0,0x1d(%ebp) // set ah = 0 to indicate + // success + andb $0xfe,%dl // clear CF + jmp v86mon.5 // Finish up /* * Reboot the machine by setting the reboot flag and exiting */ -reboot: orb $0x1,btx_hdr+0x7 # Set the reboot flag - jmp exit # Terminate BTX and reboot +reboot: orb $0x1,btx_hdr+0x7 // Set the reboot flag + jmp exit // Terminate BTX and reboot /* * Emulate INT imm8... also make sure to check if it's int 15/87 */ -v86intn: lodsb # Get int no - cmpb $0x19,%al # is it int 19? - je reboot # yes, reboot the machine - cmpb $0x15,%al # is it int 15? - jne v86intn.3 # no, skip parse - pushl %eax # stash EAX - movl 0x1c(%ebp),%eax # user's saved EAX - cmpb $0x87,%ah # is it the memcpy subfunction? - jne v86intn.1 # no, keep checking - popl %eax # get the stack straight - jmp int15_87 # it's our cue -v86intn.1: cmpw $0x4f53,%ax # is it the delete key callout? - jne v86intn.2 # no, handle the int normally - movb BDA_KEYFLAGS,%al # get the shift key state - andb $0xc,%al # mask off just Ctrl and Alt - cmpb $0xc,%al # are both Ctrl and Alt down? - jne v86intn.2 # no, handle the int normally - popl %eax # restore EAX - jmp reboot # reboot the machine -v86intn.2: popl %eax # restore EAX -v86intn.3: subl %edi,%esi # From - shrl $0x4,%edi # linear - movw %dx,-0x2(%ebx) # Save flags - movw %di,-0x4(%ebx) # Save CS - leal -0x6(%ebx),%ebx # Adjust SP - movw %si,(%ebx) # Save IP - shll $0x2,%eax # Scale - movzwl (%eax),%esi # Load IP - movzwl 0x2(%eax),%edi # Load CS - movl %edi,0x2c(%ebp) # Save CS - xorl %edi,%edi # No ESI adjustment - andb $~0x1,%dh # Clear TF - jmp v86mon.5 # Finish up +v86intn: lodsb // Get int no + cmpb $0x19,%al // is it int 19? + je reboot // yes, reboot the machine + cmpb $0x15,%al // is it int 15? + jne v86intn.3 // no, skip parse + pushl %eax // stash EAX + movl 0x1c(%ebp),%eax // user's saved EAX + cmpb $0x87,%ah // is it the memcpy subfunction? + jne v86intn.1 // no, keep checking + popl %eax // get the stack straight + jmp int15_87 // it's our cue +v86intn.1: cmpw $0x4f53,%ax // is it the delete key callout? + jne v86intn.2 // no, handle the int normally + movb BDA_KEYFLAGS,%al // get the shift key state + andb $0xc,%al // mask off just Ctrl and Alt + cmpb $0xc,%al // are both Ctrl and Alt down? + jne v86intn.2 // no, handle the int normally + popl %eax // restore EAX + jmp reboot // reboot the machine +v86intn.2: popl %eax // restore EAX +v86intn.3: subl %edi,%esi // From + shrl $0x4,%edi // linear + movw %dx,-0x2(%ebx) // Save flags + movw %di,-0x4(%ebx) // Save CS + leal -0x6(%ebx),%ebx // Adjust SP + movw %si,(%ebx) // Save IP + shll $0x2,%eax // Scale + movzwl (%eax),%esi // Load IP + movzwl 0x2(%eax),%edi // Load CS + movl %edi,0x2c(%ebp) // Save CS + xorl %edi,%edi // No ESI adjustment + andb $~0x1,%dh // Clear TF + jmp v86mon.5 // Finish up /* * Hardware interrupt jump table. */ -intx20: push $0x8 # Int 0x20: IRQ0 - jmp int_hw # V86 int 0x8 - push $0x9 # Int 0x21: IRQ1 - jmp int_hw # V86 int 0x9 - push $0xa # Int 0x22: IRQ2 - jmp int_hw # V86 int 0xa - push $0xb # Int 0x23: IRQ3 - jmp int_hw # V86 int 0xb - push $0xc # Int 0x24: IRQ4 - jmp int_hw # V86 int 0xc - push $0xd # Int 0x25: IRQ5 - jmp int_hw # V86 int 0xd - push $0xe # Int 0x26: IRQ6 - jmp int_hw # V86 int 0xe - push $0xf # Int 0x27: IRQ7 - jmp int_hw # V86 int 0xf - push $0x70 # Int 0x28: IRQ8 - jmp int_hw # V86 int 0x70 - push $0x71 # Int 0x29: IRQ9 - jmp int_hw # V86 int 0x71 - push $0x72 # Int 0x2a: IRQ10 - jmp int_hw # V86 int 0x72 - push $0x73 # Int 0x2b: IRQ11 - jmp int_hw # V86 int 0x73 - push $0x74 # Int 0x2c: IRQ12 - jmp int_hw # V86 int 0x74 - push $0x75 # Int 0x2d: IRQ13 - jmp int_hw # V86 int 0x75 - push $0x76 # Int 0x2e: IRQ14 - jmp int_hw # V86 int 0x76 - push $0x77 # Int 0x2f: IRQ15 - jmp int_hw # V86 int 0x77 +intx20: push $0x8 // Int 0x20: IRQ0 + jmp int_hw // V86 int 0x8 + push $0x9 // Int 0x21: IRQ1 + jmp int_hw // V86 int 0x9 + push $0xa // Int 0x22: IRQ2 + jmp int_hw // V86 int 0xa + push $0xb // Int 0x23: IRQ3 + jmp int_hw // V86 int 0xb + push $0xc // Int 0x24: IRQ4 + jmp int_hw // V86 int 0xc + push $0xd // Int 0x25: IRQ5 + jmp int_hw // V86 int 0xd + push $0xe // Int 0x26: IRQ6 + jmp int_hw // V86 int 0xe + push $0xf // Int 0x27: IRQ7 + jmp int_hw // V86 int 0xf + push $0x70 // Int 0x28: IRQ8 + jmp int_hw // V86 int 0x70 + push $0x71 // Int 0x29: IRQ9 + jmp int_hw // V86 int 0x71 + push $0x72 // Int 0x2a: IRQ10 + jmp int_hw // V86 int 0x72 + push $0x73 // Int 0x2b: IRQ11 + jmp int_hw // V86 int 0x73 + push $0x74 // Int 0x2c: IRQ12 + jmp int_hw // V86 int 0x74 + push $0x75 // Int 0x2d: IRQ13 + jmp int_hw // V86 int 0x75 + push $0x76 // Int 0x2e: IRQ14 + jmp int_hw // V86 int 0x76 + push $0x77 // Int 0x2f: IRQ15 + jmp int_hw // V86 int 0x77 /* * Reflect hardware interrupts. */ -int_hw: testb $0x2,0xe(%esp,1) # V86 mode? - jz intusr # No - pushl $SEL_SDATA # Address - popl %ds # data - xchgl %eax,(%esp,1) # Swap EAX, int no - pushl %ebp # Address - movl %esp,%ebp # stack frame - pushl %ebx # Save - shll $0x2,%eax # Get int - movl (%eax),%eax # vector - subl $0x6,0x14(%ebp) # Adjust V86 ESP - movzwl 0x18(%ebp),%ebx # V86 SS - shll $0x4,%ebx # * 0x10 - addl 0x14(%ebp),%ebx # + V86 ESP - xchgw %ax,0x8(%ebp) # Swap V86 IP - rorl $0x10,%eax # Swap words - xchgw %ax,0xc(%ebp) # Swap V86 CS - roll $0x10,%eax # Swap words - movl %eax,(%ebx) # CS:IP for IRET - movl 0x10(%ebp),%eax # V86 flags - movw %ax,0x4(%ebx) # Flags for IRET - andb $~0x3,0x11(%ebp) # Clear IF, TF - popl %ebx # Restore - popl %ebp # saved - popl %eax # registers - iret # To V86 mode +int_hw: testb $0x2,0xe(%esp,1) // V86 mode? + jz intusr // No + pushl $SEL_SDATA // Address + popl %ds // data + xchgl %eax,(%esp,1) // Swap EAX, int no + pushl %ebp // Address + movl %esp,%ebp // stack frame + pushl %ebx // Save + shll $0x2,%eax // Get int + movl (%eax),%eax // vector + subl $0x6,0x14(%ebp) // Adjust V86 ESP + movzwl 0x18(%ebp),%ebx // V86 SS + shll $0x4,%ebx // * 0x10 + addl 0x14(%ebp),%ebx // + V86 ESP + xchgw %ax,0x8(%ebp) // Swap V86 IP + rorl $0x10,%eax // Swap words + xchgw %ax,0xc(%ebp) // Swap V86 CS + roll $0x10,%eax // Swap words + movl %eax,(%ebx) // CS:IP for IRET + movl 0x10(%ebp),%eax // V86 flags + movw %ax,0x4(%ebx) // Flags for IRET + andb $~0x3,0x11(%ebp) // Clear IF, TF + popl %ebx // Restore + popl %ebp // saved + popl %eax // registers + iret // To V86 mode /* * Invoke V86 interrupt from user mode, with arguments. */ -intx31: stc # Have btx_v86 - pushl %eax # Missing int no +intx31: stc // Have btx_v86 + pushl %eax // Missing int no /* * Invoke V86 interrupt from user mode. */ -intusr: std # String ops dec - pushl %eax # Expand - pushl %eax # stack - pushl %eax # frame - pusha # Save - pushl %gs # Save - movl %esp,%eax # seg regs - pushl %fs # and - pushl %ds # point - pushl %es # to them - push $SEL_SDATA # Set up - popl %ds # to - pushl %ds # address - popl %es # data - movl $MEM_USR,%ebx # User base - movl %ebx,%edx # address - jc intusr.1 # If btx_v86 - xorl %edx,%edx # Control flags - xorl %ebp,%ebp # btx_v86 pointer -intusr.1: leal 0x50(%esp,1),%esi # Base of frame - pushl %esi # Save - addl -0x4(%esi),%ebx # User ESP - movl MEM_TSS+TSS_ESP1,%edi # Link stack pointer - leal -0x4(%edi),%edi # Adjust for push - xorl %ecx,%ecx # Zero - movb $0x5,%cl # Push exception - rep # frame on - movsl # link stack - xchgl %eax,%esi # Saved seg regs - movl 0x40(%esp,1),%eax # Get int no - testl %edx,%edx # Have btx_v86? - jz intusr.2 # No - movl (%ebx),%ebp # btx_v86 pointer - movb $0x4,%cl # Count - addl %ecx,%ebx # Adjust for pop - rep # Push saved seg regs - movsl # on link stack - addl %ebp,%edx # Flatten btx_v86 ptr - leal 0x14(%edx),%esi # Seg regs pointer - movl 0x4(%edx),%eax # Get int no/address - movzwl 0x2(%edx),%edx # Get control flags -intusr.2: movl %ebp,(%edi) # Push btx_v86 and - movl %edi,MEM_TSS+TSS_ESP1 # save link stack ptr - popl %edi # Base of frame - xchgl %eax,%ebp # Save intno/address - movl 0x48(%esp,1),%eax # Get flags - testb $0x2,%dl # Simulate CALLF? - jnz intusr.3 # Yes - decl %ebx # Push flags - decl %ebx # on V86 - movw %ax,(%ebx) # stack -intusr.3: movb $0x4,%cl # Count - subl %ecx,%ebx # Push return address - movl $inthlt,(%ebx) # on V86 stack - rep # Copy seg regs to - movsl # exception frame - xchgl %eax,%ecx # Save flags - movl %ebx,%eax # User ESP - subl $V86_STK,%eax # Less bytes - ja intusr.4 # to - xorl %eax,%eax # keep -intusr.4: shrl $0x4,%eax # Gives segment - stosl # Set SS - shll $0x4,%eax # To bytes - xchgl %eax,%ebx # Swap - subl %ebx,%eax # Gives offset - stosl # Set ESP - xchgl %eax,%ecx # Get flags - btsl $0x11,%eax # Set VM - andb $~0x1,%ah # Clear TF - stosl # Set EFL - xchgl %eax,%ebp # Get int no/address - testb $0x1,%dl # Address? - jnz intusr.5 # Yes - shll $0x2,%eax # Scale - movl (%eax),%eax # Load int vector -intusr.5: movl %eax,%ecx # Save - shrl $0x10,%eax # Gives segment - stosl # Set CS - movw %cx,%ax # Restore - stosl # Set EIP - leal 0x10(%esp,1),%esp # Discard seg regs - popa # Restore - iret # To V86 mode +intusr: std // String ops dec + pushl %eax // Expand + pushl %eax // stack + pushl %eax // frame + pusha // Save + pushl %gs // Save + movl %esp,%eax // seg regs + pushl %fs // and + pushl %ds // point + pushl %es // to them + push $SEL_SDATA // Set up + popl %ds // to + pushl %ds // address + popl %es // data + movl $MEM_USR,%ebx // User base + movl %ebx,%edx // address + jc intusr.1 // If btx_v86 + xorl %edx,%edx // Control flags + xorl %ebp,%ebp // btx_v86 pointer +intusr.1: leal 0x50(%esp,1),%esi // Base of frame + pushl %esi // Save + addl -0x4(%esi),%ebx // User ESP + movl MEM_TSS+TSS_ESP1,%edi // Link stack pointer + leal -0x4(%edi),%edi // Adjust for push + xorl %ecx,%ecx // Zero + movb $0x5,%cl // Push exception + rep // frame on + movsl // link stack + xchgl %eax,%esi // Saved seg regs + movl 0x40(%esp,1),%eax // Get int no + testl %edx,%edx // Have btx_v86? + jz intusr.2 // No + movl (%ebx),%ebp // btx_v86 pointer + movb $0x4,%cl // Count + addl %ecx,%ebx // Adjust for pop + rep // Push saved seg regs + movsl // on link stack + addl %ebp,%edx // Flatten btx_v86 ptr + leal 0x14(%edx),%esi // Seg regs pointer + movl 0x4(%edx),%eax // Get int no/address + movzwl 0x2(%edx),%edx // Get control flags +intusr.2: movl %ebp,(%edi) // Push btx_v86 and + movl %edi,MEM_TSS+TSS_ESP1 // save link stack ptr + popl %edi // Base of frame + xchgl %eax,%ebp // Save intno/address + movl 0x48(%esp,1),%eax // Get flags + testb $0x2,%dl // Simulate CALLF? + jnz intusr.3 // Yes + decl %ebx // Push flags + decl %ebx // on V86 + movw %ax,(%ebx) // stack +intusr.3: movb $0x4,%cl // Count + subl %ecx,%ebx // Push return address + movl $inthlt,(%ebx) // on V86 stack + rep // Copy seg regs to + movsl // exception frame + xchgl %eax,%ecx // Save flags + movl %ebx,%eax // User ESP + subl $V86_STK,%eax // Less bytes + ja intusr.4 // to + xorl %eax,%eax // keep +intusr.4: shrl $0x4,%eax // Gives segment + stosl // Set SS + shll $0x4,%eax // To bytes + xchgl %eax,%ebx // Swap + subl %ebx,%eax // Gives offset + stosl // Set ESP + xchgl %eax,%ecx // Get flags + btsl $0x11,%eax // Set VM + andb $~0x1,%ah // Clear TF + stosl // Set EFL + xchgl %eax,%ebp // Get int no/address + testb $0x1,%dl // Address? + jnz intusr.5 // Yes + shll $0x2,%eax // Scale + movl (%eax),%eax // Load int vector +intusr.5: movl %eax,%ecx // Save + shrl $0x10,%eax // Gives segment + stosl // Set CS + movw %cx,%ax // Restore + stosl // Set EIP + leal 0x10(%esp,1),%esp // Discard seg regs + popa // Restore + iret // To V86 mode /* * System Call. */ -intx30: cmpl $SYS_EXEC,%eax # Exec system call? - jne intx30.1 # No - pushl %ss # Set up - popl %es # all - pushl %es # segment - popl %ds # registers - pushl %ds # for the - popl %fs # program - pushl %fs # we're - popl %gs # invoking - movl $MEM_USR,%eax # User base address - addl 0xc(%esp,1),%eax # Change to user - leal 0x4(%eax),%esp # stack +intx30: cmpl $SYS_EXEC,%eax // Exec system call? + jne intx30.1 // No + pushl %ss // Set up + popl %es // all + pushl %es // segment + popl %ds // registers + pushl %ds // for the + popl %fs // program + pushl %fs // we're + popl %gs // invoking + movl $MEM_USR,%eax // User base address + addl 0xc(%esp,1),%eax // Change to user + leal 0x4(%eax),%esp // stack #ifdef PAGING - movl %cr0,%eax # Turn - andl $~0x80000000,%eax # off - movl %eax,%cr0 # paging - xorl %eax,%eax # Flush - movl %eax,%cr3 # TLB + movl %cr0,%eax // Turn + andl $~0x80000000,%eax // off + movl %eax,%cr0 // paging + xorl %eax,%eax // Flush + movl %eax,%cr3 // TLB #endif - popl %eax # Call - call *%eax # program -intx30.1: orb $0x1,%ss:btx_hdr+0x7 # Flag reboot - jmp exit # Exit + popl %eax // Call + call *%eax // program +intx30.1: orb $0x1,%ss:btx_hdr+0x7 // Flag reboot + jmp exit // Exit /* * Dump structure [EBX] to [EDI], using format string [ESI]. */ -dump.0: stosb # Save char -dump: lodsb # Load char - testb %al,%al # End of string? - jz dump.10 # Yes - testb $0x80,%al # Control? - jz dump.0 # No - movb %al,%ch # Save control - movb $'=',%al # Append - stosb # '=' - lodsb # Get offset - pushl %esi # Save - movsbl %al,%esi # To - addl %ebx,%esi # pointer - testb $DMP_X16,%ch # Dump word? - jz dump.1 # No - lodsw # Get and - call hex16 # dump it -dump.1: testb $DMP_X32,%ch # Dump long? - jz dump.2 # No - lodsl # Get and - call hex32 # dump it -dump.2: testb $DMP_MEM,%ch # Dump memory? - jz dump.8 # No - pushl %ds # Save - testb $0x2,0x52(%ebx) # V86 mode? - jnz dump.3 # Yes - verr 0x4(%esi) # Readable selector? - jnz dump.3 # No - ldsl (%esi),%esi # Load pointer - jmp dump.4 # Join common code -dump.3: lodsl # Set offset - xchgl %eax,%edx # Save - lodsl # Get segment - shll $0x4,%eax # * 0x10 - addl %edx,%eax # + offset - xchgl %eax,%esi # Set pointer -dump.4: movb $2,%dl # Num lines -dump.4a: movb $0x10,%cl # Bytes to dump -dump.5: lodsb # Get byte and - call hex8 # dump it - decb %cl # Keep count - jz dump.6a # If done - movb $'-',%al # Separator - cmpb $0x8,%cl # Half way? - je dump.6 # Yes - movb $' ',%al # Use space -dump.6: stosb # Save separator - jmp dump.5 # Continue -dump.6a: decb %dl # Keep count - jz dump.7 # If done - movb $0xa,%al # Line feed - stosb # Save one - movb $7,%cl # Leading - movb $' ',%al # spaces -dump.6b: stosb # Dump - decb %cl # spaces +dump.0: stosb // Save char +dump: lodsb // Load char + testb %al,%al // End of string? + jz dump.10 // Yes + testb $0x80,%al // Control? + jz dump.0 // No + movb %al,%ch // Save control + movb $'=',%al // Append + stosb // '=' + lodsb // Get offset + pushl %esi // Save + movsbl %al,%esi // To + addl %ebx,%esi // pointer + testb $DMP_X16,%ch // Dump word? + jz dump.1 // No + lodsw // Get and + call hex16 // dump it +dump.1: testb $DMP_X32,%ch // Dump long? + jz dump.2 // No + lodsl // Get and + call hex32 // dump it +dump.2: testb $DMP_MEM,%ch // Dump memory? + jz dump.8 // No + pushl %ds // Save + testb $0x2,0x52(%ebx) // V86 mode? + jnz dump.3 // Yes + verr 0x4(%esi) // Readable selector? + jnz dump.3 // No + ldsl (%esi),%esi // Load pointer + jmp dump.4 // Join common code +dump.3: lodsl // Set offset + xchgl %eax,%edx // Save + lodsl // Get segment + shll $0x4,%eax // * 0x10 + addl %edx,%eax // + offset + xchgl %eax,%esi // Set pointer +dump.4: movb $2,%dl // Num lines +dump.4a: movb $0x10,%cl // Bytes to dump +dump.5: lodsb // Get byte and + call hex8 // dump it + decb %cl // Keep count + jz dump.6a // If done + movb $'-',%al // Separator + cmpb $0x8,%cl // Half way? + je dump.6 // Yes + movb $' ',%al // Use space +dump.6: stosb // Save separator + jmp dump.5 // Continue +dump.6a: decb %dl // Keep count + jz dump.7 // If done + movb $0xa,%al // Line feed + stosb // Save one + movb $7,%cl // Leading + movb $' ',%al // spaces +dump.6b: stosb // Dump + decb %cl // spaces jnz dump.6b - jmp dump.4a # Next line -dump.7: popl %ds # Restore -dump.8: popl %esi # Restore - movb $0xa,%al # Line feed - testb $DMP_EOL,%ch # End of line? - jnz dump.9 # Yes - movb $' ',%al # Use spaces - stosb # Save one -dump.9: jmp dump.0 # Continue -dump.10: stosb # Terminate string - ret # To caller + jmp dump.4a // Next line +dump.7: popl %ds // Restore +dump.8: popl %esi // Restore + movb $0xa,%al // Line feed + testb $DMP_EOL,%ch // End of line? + jnz dump.9 // Yes + movb $' ',%al // Use spaces + stosb // Save one +dump.9: jmp dump.0 // Continue +dump.10: stosb // Terminate string + ret // To caller /* * Convert EAX, AX, or AL to hex, saving the result to [EDI]. */ -hex32: pushl %eax # Save - shrl $0x10,%eax # Do upper - call hex16 # 16 - popl %eax # Restore -hex16: call hex16.1 # Do upper 8 -hex16.1: xchgb %ah,%al # Save/restore -hex8: pushl %eax # Save - shrb $0x4,%al # Do upper - call hex8.1 # 4 - popl %eax # Restore -hex8.1: andb $0xf,%al # Get lower 4 - cmpb $0xa,%al # Convert - sbbb $0x69,%al # to hex - das # digit - orb $0x20,%al # To lower case - stosb # Save char - ret # (Recursive) +hex32: pushl %eax // Save + shrl $0x10,%eax // Do upper + call hex16 // 16 + popl %eax // Restore +hex16: call hex16.1 // Do upper 8 +hex16.1: xchgb %ah,%al // Save/restore +hex8: pushl %eax // Save + shrb $0x4,%al // Do upper + call hex8.1 // 4 + popl %eax // Restore +hex8.1: andb $0xf,%al // Get lower 4 + cmpb $0xa,%al // Convert + sbbb $0x69,%al // to hex + das // digit + orb $0x20,%al // To lower case + stosb // Save char + ret // (Recursive) /* * Output zero-terminated string [ESI] to the console. */ -putstr.0: call putchr # Output char -putstr: lodsb # Load char - testb %al,%al # End of string? - jnz putstr.0 # No - ret # To caller +putstr.0: call putchr // Output char +putstr: lodsb // Load char + testb %al,%al // End of string? + jnz putstr.0 // No + ret // To caller #ifdef BTX_SERIAL - .set SIO_PRT,SIOPRT # Base port - .set SIO_FMT,SIOFMT # 8N1 - .set SIO_DIV,(115200/SIOSPD) # 115200 / SPD + .set SIO_PRT,SIOPRT // Base port + .set SIO_FMT,SIOFMT // 8N1 + .set SIO_DIV,(115200/SIOSPD) // 115200 / SPD * void sio_init(void) -sio_init: movw $SIO_PRT+0x3,%dx # Data format reg - movb $SIO_FMT|0x80,%al # Set format - outb %al,(%dx) # and DLAB - pushl %edx # Save - subb $0x3,%dl # Divisor latch reg - movw $SIO_DIV,%ax # Set - outw %ax,(%dx) # BPS - popl %edx # Restore - movb $SIO_FMT,%al # Clear - outb %al,(%dx) # DLAB - incl %edx # Modem control reg - movb $0x3,%al # Set RTS, - outb %al,(%dx) # DTR - incl %edx # Line status reg +sio_init: movw $SIO_PRT+0x3,%dx // Data format reg + movb $SIO_FMT|0x80,%al // Set format + outb %al,(%dx) // and DLAB + pushl %edx // Save + subb $0x3,%dl // Divisor latch reg + movw $SIO_DIV,%ax // Set + outw %ax,(%dx) // BPS + popl %edx // Restore + movb $SIO_FMT,%al // Clear + outb %al,(%dx) // DLAB + incl %edx // Modem control reg + movb $0x3,%al // Set RTS, + outb %al,(%dx) // DTR + incl %edx // Line status reg * void sio_flush(void) -sio_flush.0: call sio_getc.1 # Get character -sio_flush: call sio_ischar # Check for character - jnz sio_flush.0 # Till none - ret # To caller +sio_flush.0: call sio_getc.1 // Get character +sio_flush: call sio_ischar // Check for character + jnz sio_flush.0 // Till none + ret // To caller * void sio_putc(int c) -sio_putc: movw $SIO_PRT+0x5,%dx # Line status reg - xor %ecx,%ecx # Timeout - movb $0x40,%ch # counter -sio_putc.1: inb (%dx),%al # Transmitter - testb $0x20,%al # buffer empty? - loopz sio_putc.1 # No - jz sio_putc.2 # If timeout - movb 0x4(%esp,1),%al # Get character - subb $0x5,%dl # Transmitter hold reg - outb %al,(%dx) # Write character -sio_putc.2: ret $0x4 # To caller +sio_putc: movw $SIO_PRT+0x5,%dx // Line status reg + xor %ecx,%ecx // Timeout + movb $0x40,%ch // counter +sio_putc.1: inb (%dx),%al // Transmitter + testb $0x20,%al // buffer empty? + loopz sio_putc.1 // No + jz sio_putc.2 // If timeout + movb 0x4(%esp,1),%al // Get character + subb $0x5,%dl // Transmitter hold reg + outb %al,(%dx) // Write character +sio_putc.2: ret $0x4 // To caller * int sio_getc(void) -sio_getc: call sio_ischar # Character available? - jz sio_getc # No -sio_getc.1: subb $0x5,%dl # Receiver buffer reg - inb (%dx),%al # Read character - ret # To caller +sio_getc: call sio_ischar // Character available? + jz sio_getc // No +sio_getc.1: subb $0x5,%dl // Receiver buffer reg + inb (%dx),%al // Read character + ret // To caller * int sio_ischar(void) -sio_ischar: movw $SIO_PRT+0x5,%dx # Line status register - xorl %eax,%eax # Zero - inb (%dx),%al # Received data - andb $0x1,%al # ready? - ret # To caller +sio_ischar: movw $SIO_PRT+0x5,%dx // Line status register + xorl %eax,%eax // Zero + inb (%dx),%al // Received data + andb $0x1,%al // ready? + ret // To caller /* * Output character AL to the serial console. */ -putchr: pusha # Save - cmpb $10, %al # is it a newline? - jne putchr.1 # no?, then leave - push $13 # output a carriage - call sio_putc # return first - movb $10, %al # restore %al -putchr.1: pushl %eax # Push the character - # onto the stack - call sio_putc # Output the character - popa # Restore - ret # To caller +putchr: pusha // Save + cmpb $10, %al // is it a newline? + jne putchr.1 // no?, then leave + push $13 // output a carriage + call sio_putc // return first + movb $10, %al // restore %al +putchr.1: pushl %eax // Push the character + // onto the stack + call sio_putc // Output the character + popa // Restore + ret // To caller #else /* * Output character AL to the console. */ -putchr: pusha # Save - xorl %ecx,%ecx # Zero for loops - movb $SCR_MAT,%ah # Mode/attribute - movl $BDA_POS,%ebx # BDA pointer - movw (%ebx),%dx # Cursor position - movl $0xb8000,%edi # Regen buffer (color) - cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode? - jne putchr.1 # No - xorw %di,%di # Regen buffer (mono) -putchr.1: cmpb $0xa,%al # New line? - je putchr.2 # Yes - xchgl %eax,%ecx # Save char - movb $SCR_COL,%al # Columns per row - mulb %dh # * row position - addb %dl,%al # + column - adcb $0x0,%ah # position - shll %eax # * 2 - xchgl %eax,%ecx # Swap char, offset - movw %ax,(%edi,%ecx,1) # Write attr:char - incl %edx # Bump cursor - cmpb $SCR_COL,%dl # Beyond row? - jb putchr.3 # No -putchr.2: xorb %dl,%dl # Zero column - incb %dh # Bump row -putchr.3: cmpb $SCR_ROW,%dh # Beyond screen? - jb putchr.4 # No - leal 2*SCR_COL(%edi),%esi # New top line - movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move - rep # Scroll - movsl # screen - movb $0x20,%al # Space - movb $SCR_COL,%cl # Columns to clear - rep # Clear - stosw # line - movb $SCR_ROW-1,%dh # Bottom line -putchr.4: movw %dx,(%ebx) # Update position - popa # Restore - ret # To caller +putchr: pusha // Save + xorl %ecx,%ecx // Zero for loops + movb $SCR_MAT,%ah // Mode/attribute + movl $BDA_POS,%ebx // BDA pointer + movw (%ebx),%dx // Cursor position + movl $0xb8000,%edi // Regen buffer (color) + cmpb %ah,BDA_SCR-BDA_POS(%ebx) // Mono mode? + jne putchr.1 // No + xorw %di,%di // Regen buffer (mono) +putchr.1: cmpb $0xa,%al // New line? + je putchr.2 // Yes + xchgl %eax,%ecx // Save char + movb $SCR_COL,%al // Columns per row + mulb %dh // * row position + addb %dl,%al // + column + adcb $0x0,%ah // position + shll %eax // * 2 + xchgl %eax,%ecx // Swap char, offset + movw %ax,(%edi,%ecx,1) // Write attr:char + incl %edx // Bump cursor + cmpb $SCR_COL,%dl // Beyond row? + jb putchr.3 // No +putchr.2: xorb %dl,%dl // Zero column + incb %dh // Bump row +putchr.3: cmpb $SCR_ROW,%dh // Beyond screen? + jb putchr.4 // No + leal 2*SCR_COL(%edi),%esi // New top line + movw $(SCR_ROW-1)*SCR_COL/2,%cx // Words to move + rep // Scroll + movsl // screen + movb $0x20,%al // Space + movb $SCR_COL,%cl // Columns to clear + rep // Clear + stosw // line + movb $SCR_ROW-1,%dh // Bottom line +putchr.4: movw %dx,(%ebx) // Update position + popa // Restore + ret // To caller #endif .p2align 4 /* * Global descriptor table. */ -gdt: .word 0x0,0x0,0x0,0x0 # Null entry - .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE - .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA - .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE - .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA - .word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE - .word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA - .word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS +gdt: .word 0x0,0x0,0x0,0x0 // Null entry + .word 0xffff,0x0,0x9a00,0xcf // SEL_SCODE + .word 0xffff,0x0,0x9200,0xcf // SEL_SDATA + .word 0xffff,0x0,0x9a00,0x0 // SEL_RCODE + .word 0xffff,0x0,0x9200,0x0 // SEL_RDATA + .word 0xffff,MEM_USR,0xfa00,0xcf// SEL_UCODE + .word 0xffff,MEM_USR,0xf200,0xcf// SEL_UDATA + .word _TSSLM,MEM_TSS,0x8900,0x0 // SEL_TSS gdt.1: /* * Pseudo-descriptors. */ -gdtdesc: .word gdt.1-gdt-1,gdt,0x0 # GDT -idtdesc: .word _IDTLM,MEM_IDT,0x0 # IDT -ivtdesc: .word 0x400-0x0-1,0x0,0x0 # IVT +gdtdesc: .word gdt.1-gdt-1,gdt,0x0 // GDT +idtdesc: .word _IDTLM,MEM_IDT,0x0 // IDT +ivtdesc: .word 0x400-0x0-1,0x0,0x0 // IVT /* * IDT construction control string. */ -idtctl: .byte 0x10, 0x8e # Int 0x0-0xf - .word 0x7dfb,intx00 # (exceptions) - .byte 0x10, 0x8e # Int 0x10 - .word 0x1, intx10 # (exception) - .byte 0x10, 0x8e # Int 0x20-0x2f - .word 0xffff,intx20 # (hardware) - .byte 0x1, 0xee # int 0x30 - .word 0x1, intx30 # (system call) - .byte 0x2, 0xee # Int 0x31-0x32 - .word 0x1, intx31 # (V86, null) - .byte 0x0 # End of string +idtctl: .byte 0x10, 0x8e // Int 0x0-0xf + .word 0x7dfb,intx00 // (exceptions) + .byte 0x10, 0x8e // Int 0x10 + .word 0x1, intx10 // (exception) + .byte 0x10, 0x8e // Int 0x20-0x2f + .word 0xffff,intx20 // (hardware) + .byte 0x1, 0xee // int 0x30 + .word 0x1, intx30 // (system call) + .byte 0x2, 0xee // Int 0x31-0x32 + .word 0x1, intx31 // (V86, null) + .byte 0x0 // End of string /* * Dump format string. */ -dmpfmt: .byte '\n' # "\n" - .ascii "int" # "int=" - .byte 0x80|DMP_X32, 0x40 # "00000000 " - .ascii "err" # "err=" - .byte 0x80|DMP_X32, 0x44 # "00000000 " - .ascii "efl" # "efl=" - .byte 0x80|DMP_X32, 0x50 # "00000000 " - .ascii "eip" # "eip=" - .byte 0x80|DMP_X32|DMP_EOL,0x48 # "00000000\n" - .ascii "eax" # "eax=" - .byte 0x80|DMP_X32, 0x34 # "00000000 " - .ascii "ebx" # "ebx=" - .byte 0x80|DMP_X32, 0x28 # "00000000 " - .ascii "ecx" # "ecx=" - .byte 0x80|DMP_X32, 0x30 # "00000000 " - .ascii "edx" # "edx=" - .byte 0x80|DMP_X32|DMP_EOL,0x2c # "00000000\n" - .ascii "esi" # "esi=" - .byte 0x80|DMP_X32, 0x1c # "00000000 " - .ascii "edi" # "edi=" - .byte 0x80|DMP_X32, 0x18 # "00000000 " - .ascii "ebp" # "ebp=" - .byte 0x80|DMP_X32, 0x20 # "00000000 " - .ascii "esp" # "esp=" - .byte 0x80|DMP_X32|DMP_EOL,0x0 # "00000000\n" - .ascii "cs" # "cs=" - .byte 0x80|DMP_X16, 0x4c # "0000 " - .ascii "ds" # "ds=" - .byte 0x80|DMP_X16, 0xc # "0000 " - .ascii "es" # "es=" - .byte 0x80|DMP_X16, 0x8 # "0000 " - .ascii " " # " " - .ascii "fs" # "fs=" - .byte 0x80|DMP_X16, 0x10 # "0000 " - .ascii "gs" # "gs=" - .byte 0x80|DMP_X16, 0x14 # "0000 " - .ascii "ss" # "ss=" - .byte 0x80|DMP_X16|DMP_EOL,0x4 # "0000\n" - .ascii "cs:eip" # "cs:eip=" - .byte 0x80|DMP_MEM|DMP_EOL,0x48 # "00 00 ... 00 00\n" - .ascii "ss:esp" # "ss:esp=" - .byte 0x80|DMP_MEM|DMP_EOL,0x0 # "00 00 ... 00 00\n" - .asciz "BTX halted\n" # End +dmpfmt: .byte '\n' // "\n" + .ascii "int" // "int=" + .byte 0x80|DMP_X32, 0x40 // "00000000 " + .ascii "err" // "err=" + .byte 0x80|DMP_X32, 0x44 // "00000000 " + .ascii "efl" // "efl=" + .byte 0x80|DMP_X32, 0x50 // "00000000 " + .ascii "eip" // "eip=" + .byte 0x80|DMP_X32|DMP_EOL,0x48 // "00000000\n" + .ascii "eax" // "eax=" + .byte 0x80|DMP_X32, 0x34 // "00000000 " + .ascii "ebx" // "ebx=" + .byte 0x80|DMP_X32, 0x28 // "00000000 " + .ascii "ecx" // "ecx=" + .byte 0x80|DMP_X32, 0x30 // "00000000 " + .ascii "edx" // "edx=" + .byte 0x80|DMP_X32|DMP_EOL,0x2c // "00000000\n" + .ascii "esi" // "esi=" + .byte 0x80|DMP_X32, 0x1c // "00000000 " + .ascii "edi" // "edi=" + .byte 0x80|DMP_X32, 0x18 // "00000000 " + .ascii "ebp" // "ebp=" + .byte 0x80|DMP_X32, 0x20 // "00000000 " + .ascii "esp" // "esp=" + .byte 0x80|DMP_X32|DMP_EOL,0x0 // "00000000\n" + .ascii "cs" // "cs=" + .byte 0x80|DMP_X16, 0x4c // "0000 " + .ascii "ds" // "ds=" + .byte 0x80|DMP_X16, 0xc // "0000 " + .ascii "es" // "es=" + .byte 0x80|DMP_X16, 0x8 // "0000 " + .ascii " " // " " + .ascii "fs" // "fs=" + .byte 0x80|DMP_X16, 0x10 // "0000 " + .ascii "gs" // "gs=" + .byte 0x80|DMP_X16, 0x14 // "0000 " + .ascii "ss" // "ss=" + .byte 0x80|DMP_X16|DMP_EOL,0x4 // "0000\n" + .ascii "cs:eip" // "cs:eip=" + .byte 0x80|DMP_MEM|DMP_EOL,0x48 // "00 00 ... 00 00\n" + .ascii "ss:esp" // "ss:esp=" + .byte 0x80|DMP_MEM|DMP_EOL,0x0 // "00 00 ... 00 00\n" + .asciz "BTX halted\n" // End /* * End of BTX memory. */ diff --git a/sys/boot/i386/btx/btxldr/btxldr.S b/sys/boot/i386/btx/btxldr/btxldr.S index aa531b8..22adbcc 100644 --- a/sys/boot/i386/btx/btxldr/btxldr.S +++ b/sys/boot/i386/btx/btxldr/btxldr.S @@ -23,39 +23,39 @@ /* * Memory locations. */ - .set MEM_STUB,0x600 # Real mode stub - .set MEM_ESP,0x1000 # New stack pointer - .set MEM_TBL,0x5000 # BTX page tables - .set MEM_ENTRY,0x9010 # BTX entry point - .set MEM_DATA,start+0x1000 # Data segment + .set MEM_STUB,0x600 // Real mode stub + .set MEM_ESP,0x1000 // New stack pointer + .set MEM_TBL,0x5000 // BTX page tables + .set MEM_ENTRY,0x9010 // BTX entry point + .set MEM_DATA,start+0x1000 // Data segment /* * Segment selectors. */ - .set SEL_SCODE,0x8 # 4GB code - .set SEL_SDATA,0x10 # 4GB data - .set SEL_RCODE,0x18 # 64K code - .set SEL_RDATA,0x20 # 64K data + .set SEL_SCODE,0x8 // 4GB code + .set SEL_SDATA,0x10 // 4GB data + .set SEL_RCODE,0x18 // 64K code + .set SEL_RDATA,0x20 // 64K data /* * Paging constants. */ - .set PAG_SIZ,0x1000 # Page size - .set PAG_ENT,0x4 # Page entry size + .set PAG_SIZ,0x1000 // Page size + .set PAG_ENT,0x4 // Page entry size /* * Screen constants. */ - .set SCR_MAT,0x7 # Mode/attribute - .set SCR_COL,0x50 # Columns per row - .set SCR_ROW,0x19 # Rows per screen + .set SCR_MAT,0x7 // Mode/attribute + .set SCR_COL,0x50 // Columns per row + .set SCR_ROW,0x19 // Rows per screen /* * BIOS Data Area locations. */ - .set BDA_MEM,0x413 # Free memory - .set BDA_SCR,0x449 # Video mode - .set BDA_POS,0x450 # Cursor position + .set BDA_MEM,0x413 // Free memory + .set BDA_SCR,0x449 // Video mode + .set BDA_POS,0x450 // Cursor position /* * Required by aout gas inadequacy. */ - .set SIZ_STUB,0x1a # Size of stub + .set SIZ_STUB,0x1a // Size of stub /* * We expect to be loaded by boot2 at the origin defined in ./Makefile. */ @@ -63,303 +63,303 @@ /* * BTX program loader for ELF clients. */ -start: cld # String ops inc - movl $m_logo,%esi # Identify - call putstr # ourselves - movzwl BDA_MEM,%eax # Get base memory - shll $0xa,%eax # in bytes - movl %eax,%ebp # Base of user stack +start: cld // String ops inc + movl $m_logo,%esi // Identify + call putstr // ourselves + movzwl BDA_MEM,%eax // Get base memory + shll $0xa,%eax // in bytes + movl %eax,%ebp // Base of user stack #ifdef BTXLDR_VERBOSE - movl $m_mem,%esi # Display - call hexout # amount of - call putstr # base memory + movl $m_mem,%esi // Display + call hexout // amount of + call putstr // base memory #endif - lgdt gdtdesc # Load new GDT + lgdt gdtdesc // Load new GDT /* * Relocate caller's arguments. */ #ifdef BTXLDR_VERBOSE - movl $m_esp,%esi # Display - movl %esp,%eax # caller - call hexout # stack - call putstr # pointer - movl $m_args,%esi # Format string - leal 0x4(%esp,1),%ebx # First argument - movl $0x6,%ecx # Count -start.1: movl (%ebx),%eax # Get argument and - addl $0x4,%ebx # bump pointer - call hexout # Display it - loop start.1 # Till done - call putstr # End message + movl $m_esp,%esi // Display + movl %esp,%eax // caller + call hexout // stack + call putstr // pointer + movl $m_args,%esi // Format string + leal 0x4(%esp,1),%ebx // First argument + movl $0x6,%ecx // Count +start.1: movl (%ebx),%eax // Get argument and + addl $0x4,%ebx // bump pointer + call hexout // Display it + loop start.1 // Till done + call putstr // End message #endif - movl $0x48,%ecx # Allocate space - subl %ecx,%ebp # for bootinfo - movl 0x18(%esp,1),%esi # Source: bootinfo - cmpl $0x0, %esi # If the bootinfo pointer - je start_null_bi # is null, don't copy it - movl %ebp,%edi # Destination - rep # Copy - movsb # it - movl %ebp,0x18(%esp,1) # Update pointer + movl $0x48,%ecx // Allocate space + subl %ecx,%ebp // for bootinfo + movl 0x18(%esp,1),%esi // Source: bootinfo + cmpl $0x0, %esi // If the bootinfo pointer + je start_null_bi // is null, don't copy it + movl %ebp,%edi // Destination + rep // Copy + movsb // it + movl %ebp,0x18(%esp,1) // Update pointer #ifdef BTXLDR_VERBOSE - movl $m_rel_bi,%esi # Display - movl %ebp,%eax # bootinfo - call hexout # relocation - call putstr # message + movl $m_rel_bi,%esi // Display + movl %ebp,%eax // bootinfo + call hexout // relocation + call putstr // message #endif -start_null_bi: movl $0x18,%ecx # Allocate space - subl %ecx,%ebp # for arguments - leal 0x4(%esp,1),%esi # Source - movl %ebp,%edi # Destination - rep # Copy - movsb # them +start_null_bi: movl $0x18,%ecx // Allocate space + subl %ecx,%ebp // for arguments + leal 0x4(%esp,1),%esi // Source + movl %ebp,%edi // Destination + rep // Copy + movsb // them #ifdef BTXLDR_VERBOSE - movl $m_rel_args,%esi # Display - movl %ebp,%eax # argument - call hexout # relocation - call putstr # message + movl $m_rel_args,%esi // Display + movl %ebp,%eax // argument + call hexout // relocation + call putstr // message #endif /* * Set up BTX kernel. */ - movl $MEM_ESP,%esp # Set up new stack - movl $MEM_DATA,%ebx # Data segment - movl $m_vers,%esi # Display BTX - call putstr # version message - movb 0x5(%ebx),%al # Get major version - addb $'0',%al # Display - call putchr # it - movb $'.',%al # And a - call putchr # dot - movb 0x6(%ebx),%al # Get minor - xorb %ah,%ah # version - movb $0xa,%dl # Divide - divb %dl,%al # by 10 - addb $'0',%al # Display - call putchr # tens - movb %ah,%al # Get units - addb $'0',%al # Display - call putchr # units - call putstr # End message - movl %ebx,%esi # BTX image - movzwl 0x8(%ebx),%edi # Compute - orl $PAG_SIZ/PAG_ENT-1,%edi # the - incl %edi # BTX - shll $0x2,%edi # load - addl $MEM_TBL,%edi # address - pushl %edi # Save load address - movzwl 0xa(%ebx),%ecx # Image size + movl $MEM_ESP,%esp // Set up new stack + movl $MEM_DATA,%ebx // Data segment + movl $m_vers,%esi // Display BTX + call putstr // version message + movb 0x5(%ebx),%al // Get major version + addb $'0',%al // Display + call putchr // it + movb $'.',%al // And a + call putchr // dot + movb 0x6(%ebx),%al // Get minor + xorb %ah,%ah // version + movb $0xa,%dl // Divide + divb %dl,%al // by 10 + addb $'0',%al // Display + call putchr // tens + movb %ah,%al // Get units + addb $'0',%al // Display + call putchr // units + call putstr // End message + movl %ebx,%esi // BTX image + movzwl 0x8(%ebx),%edi // Compute + orl $PAG_SIZ/PAG_ENT-1,%edi // the + incl %edi // BTX + shll $0x2,%edi // load + addl $MEM_TBL,%edi // address + pushl %edi // Save load address + movzwl 0xa(%ebx),%ecx // Image size #ifdef BTXLDR_VERBOSE - pushl %ecx # Save image size + pushl %ecx // Save image size #endif - rep # Relocate - movsb # BTX - movl %esi,%ebx # Keep place + rep // Relocate + movsb // BTX + movl %esi,%ebx // Keep place #ifdef BTXLDR_VERBOSE - movl $m_rel_btx,%esi # Restore - popl %eax # parameters - call hexout # and + movl $m_rel_btx,%esi // Restore + popl %eax // parameters + call hexout // and #endif - popl %ebp # display + popl %ebp // display #ifdef BTXLDR_VERBOSE - movl %ebp,%eax # the - call hexout # relocation - call putstr # message + movl %ebp,%eax // the + call hexout // relocation + call putstr // message #endif - addl $PAG_SIZ,%ebp # Display + addl $PAG_SIZ,%ebp // Display #ifdef BTXLDR_VERBOSE - movl $m_base,%esi # the - movl %ebp,%eax # user - call hexout # base - call putstr # address + movl $m_base,%esi // the + movl %ebp,%eax // user + call hexout // base + call putstr // address #endif /* * Set up ELF-format client program. */ - cmpl $0x464c457f,(%ebx) # ELF magic number? - je start.3 # Yes - movl $e_fmt,%esi # Display error - call putstr # message -start.2: jmp start.2 # Hang + cmpl $0x464c457f,(%ebx) // ELF magic number? + je start.3 // Yes + movl $e_fmt,%esi // Display error + call putstr // message +start.2: jmp start.2 // Hang start.3: #ifdef BTXLDR_VERBOSE - movl $m_elf,%esi # Display ELF - call putstr # message - movl $m_segs,%esi # Format string + movl $m_elf,%esi // Display ELF + call putstr // message + movl $m_segs,%esi // Format string #endif - movl $0x2,%edi # Segment count - movl 0x1c(%ebx),%edx # Get e_phoff - addl %ebx,%edx # To pointer - movzwl 0x2c(%ebx),%ecx # Get e_phnum -start.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD? - jne start.6 # No + movl $0x2,%edi // Segment count + movl 0x1c(%ebx),%edx // Get e_phoff + addl %ebx,%edx // To pointer + movzwl 0x2c(%ebx),%ecx // Get e_phnum +start.4: cmpl $0x1,(%edx) // Is p_type PT_LOAD? + jne start.6 // No #ifdef BTXLDR_VERBOSE - movl 0x4(%edx),%eax # Display - call hexout # p_offset - movl 0x8(%edx),%eax # Display - call hexout # p_vaddr - movl 0x10(%edx),%eax # Display - call hexout # p_filesz - movl 0x14(%edx),%eax # Display - call hexout # p_memsz - call putstr # End message + movl 0x4(%edx),%eax // Display + call hexout // p_offset + movl 0x8(%edx),%eax // Display + call hexout // p_vaddr + movl 0x10(%edx),%eax // Display + call hexout // p_filesz + movl 0x14(%edx),%eax // Display + call hexout // p_memsz + call putstr // End message #endif - pushl %esi # Save - pushl %edi # working - pushl %ecx # registers - movl 0x4(%edx),%esi # Get p_offset - addl %ebx,%esi # as pointer - movl 0x8(%edx),%edi # Get p_vaddr - addl %ebp,%edi # as pointer - movl 0x10(%edx),%ecx # Get p_filesz - rep # Set up - movsb # segment - movl 0x14(%edx),%ecx # Any bytes - subl 0x10(%edx),%ecx # to zero? - jz start.5 # No - xorb %al,%al # Then - rep # zero - stosb # them -start.5: popl %ecx # Restore - popl %edi # working - popl %esi # registers - decl %edi # Segments to do - je start.7 # If none -start.6: addl $0x20,%edx # To next entry - loop start.4 # Till done + pushl %esi // Save + pushl %edi // working + pushl %ecx // registers + movl 0x4(%edx),%esi // Get p_offset + addl %ebx,%esi // as pointer + movl 0x8(%edx),%edi // Get p_vaddr + addl %ebp,%edi // as pointer + movl 0x10(%edx),%ecx // Get p_filesz + rep // Set up + movsb // segment + movl 0x14(%edx),%ecx // Any bytes + subl 0x10(%edx),%ecx // to zero? + jz start.5 // No + xorb %al,%al // Then + rep // zero + stosb // them +start.5: popl %ecx // Restore + popl %edi // working + popl %esi // registers + decl %edi // Segments to do + je start.7 // If none +start.6: addl $0x20,%edx // To next entry + loop start.4 // Till done start.7: #ifdef BTXLDR_VERBOSE - movl $m_done,%esi # Display done - call putstr # message + movl $m_done,%esi // Display done + call putstr // message #endif - movl $start.8,%esi # Real mode stub - movl $MEM_STUB,%edi # Destination - movl $start.9-start.8,%ecx # Size - rep # Relocate - movsb # it - ljmp $SEL_RCODE,$MEM_STUB # To 16-bit code + movl $start.8,%esi // Real mode stub + movl $MEM_STUB,%edi // Destination + movl $start.9-start.8,%ecx // Size + rep // Relocate + movsb // it + ljmp $SEL_RCODE,$MEM_STUB // To 16-bit code .code16 -start.8: xorw %ax,%ax # Data - movb $SEL_RDATA,%al # selector - movw %ax,%ss # Reload SS - movw %ax,%ds # Reset - movw %ax,%es # other - movw %ax,%fs # segment - movw %ax,%gs # limits - movl %cr0,%eax # Switch to - decw %ax # real - movl %eax,%cr0 # mode - ljmp $0,$MEM_ENTRY # Jump to BTX entry point +start.8: xorw %ax,%ax // Data + movb $SEL_RDATA,%al // selector + movw %ax,%ss // Reload SS + movw %ax,%ds // Reset + movw %ax,%es // other + movw %ax,%fs // segment + movw %ax,%gs // limits + movl %cr0,%eax // Switch to + decw %ax // real + movl %eax,%cr0 // mode + ljmp $0,$MEM_ENTRY // Jump to BTX entry point start.9: .code32 /* * Output message [ESI] followed by EAX in hex. */ -hexout: pushl %eax # Save - call putstr # Display message - popl %eax # Restore - pushl %esi # Save - pushl %edi # caller's - movl $buf,%edi # Buffer - pushl %edi # Save - call hex32 # To hex - xorb %al,%al # Terminate - stosb # string - popl %esi # Restore -hexout.1: lodsb # Get a char - cmpb $'0',%al # Leading zero? - je hexout.1 # Yes - testb %al,%al # End of string? - jne hexout.2 # No - decl %esi # Undo -hexout.2: decl %esi # Adjust for inc - call putstr # Display hex - popl %edi # Restore - popl %esi # caller's - ret # To caller +hexout: pushl %eax // Save + call putstr // Display message + popl %eax // Restore + pushl %esi // Save + pushl %edi // caller's + movl $buf,%edi // Buffer + pushl %edi // Save + call hex32 // To hex + xorb %al,%al // Terminate + stosb // string + popl %esi // Restore +hexout.1: lodsb // Get a char + cmpb $'0',%al // Leading zero? + je hexout.1 // Yes + testb %al,%al // End of string? + jne hexout.2 // No + decl %esi // Undo +hexout.2: decl %esi // Adjust for inc + call putstr // Display hex + popl %edi // Restore + popl %esi // caller's + ret // To caller /* * Output zero-terminated string [ESI] to the console. */ -putstr.0: call putchr # Output char -putstr: lodsb # Load char - testb %al,%al # End of string? - jne putstr.0 # No - ret # To caller +putstr.0: call putchr // Output char +putstr: lodsb // Load char + testb %al,%al // End of string? + jne putstr.0 // No + ret // To caller /* * Output character AL to the console. */ -putchr: pusha # Save - xorl %ecx,%ecx # Zero for loops - movb $SCR_MAT,%ah # Mode/attribute - movl $BDA_POS,%ebx # BDA pointer - movw (%ebx),%dx # Cursor position - movl $0xb8000,%edi # Regen buffer (color) - cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode? - jne putchr.1 # No - xorw %di,%di # Regen buffer (mono) -putchr.1: cmpb $0xa,%al # New line? - je putchr.2 # Yes - xchgl %eax,%ecx # Save char - movb $SCR_COL,%al # Columns per row - mulb %dh # * row position - addb %dl,%al # + column - adcb $0x0,%ah # position - shll %eax # * 2 - xchgl %eax,%ecx # Swap char, offset - movw %ax,(%edi,%ecx,1) # Write attr:char - incl %edx # Bump cursor - cmpb $SCR_COL,%dl # Beyond row? - jb putchr.3 # No -putchr.2: xorb %dl,%dl # Zero column - incb %dh # Bump row -putchr.3: cmpb $SCR_ROW,%dh # Beyond screen? - jb putchr.4 # No - leal 2*SCR_COL(%edi),%esi # New top line - movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move - rep # Scroll - movsl # screen - movb $' ',%al # Space - movb $SCR_COL,%cl # Columns to clear - rep # Clear - stosw # line - movb $SCR_ROW-1,%dh # Bottom line -putchr.4: movw %dx,(%ebx) # Update position - popa # Restore - ret # To caller +putchr: pusha // Save + xorl %ecx,%ecx // Zero for loops + movb $SCR_MAT,%ah // Mode/attribute + movl $BDA_POS,%ebx // BDA pointer + movw (%ebx),%dx // Cursor position + movl $0xb8000,%edi // Regen buffer (color) + cmpb %ah,BDA_SCR-BDA_POS(%ebx) // Mono mode? + jne putchr.1 // No + xorw %di,%di // Regen buffer (mono) +putchr.1: cmpb $0xa,%al // New line? + je putchr.2 // Yes + xchgl %eax,%ecx // Save char + movb $SCR_COL,%al // Columns per row + mulb %dh // * row position + addb %dl,%al // + column + adcb $0x0,%ah // position + shll %eax // * 2 + xchgl %eax,%ecx // Swap char, offset + movw %ax,(%edi,%ecx,1) // Write attr:char + incl %edx // Bump cursor + cmpb $SCR_COL,%dl // Beyond row? + jb putchr.3 // No +putchr.2: xorb %dl,%dl // Zero column + incb %dh // Bump row +putchr.3: cmpb $SCR_ROW,%dh // Beyond screen? + jb putchr.4 // No + leal 2*SCR_COL(%edi),%esi // New top line + movw $(SCR_ROW-1)*SCR_COL/2,%cx // Words to move + rep // Scroll + movsl // screen + movb $' ',%al // Space + movb $SCR_COL,%cl // Columns to clear + rep // Clear + stosw // line + movb $SCR_ROW-1,%dh // Bottom line +putchr.4: movw %dx,(%ebx) // Update position + popa // Restore + ret // To caller /* * Convert EAX, AX, or AL to hex, saving the result to [EDI]. */ -hex32: pushl %eax # Save - shrl $0x10,%eax # Do upper - call hex16 # 16 - popl %eax # Restore -hex16: call hex16.1 # Do upper 8 -hex16.1: xchgb %ah,%al # Save/restore -hex8: pushl %eax # Save - shrb $0x4,%al # Do upper - call hex8.1 # 4 - popl %eax # Restore -hex8.1: andb $0xf,%al # Get lower 4 - cmpb $0xa,%al # Convert - sbbb $0x69,%al # to hex - das # digit - orb $0x20,%al # To lower case - stosb # Save char - ret # (Recursive) +hex32: pushl %eax // Save + shrl $0x10,%eax // Do upper + call hex16 // 16 + popl %eax // Restore +hex16: call hex16.1 // Do upper 8 +hex16.1: xchgb %ah,%al // Save/restore +hex8: pushl %eax // Save + shrb $0x4,%al // Do upper + call hex8.1 // 4 + popl %eax // Restore +hex8.1: andb $0xf,%al // Get lower 4 + cmpb $0xa,%al // Convert + sbbb $0x69,%al // to hex + das // digit + orb $0x20,%al // To lower case + stosb // Save char + ret // (Recursive) .data .p2align 4 /* * Global descriptor table. */ -gdt: .word 0x0,0x0,0x0,0x0 # Null entry - .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE - .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA - .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE - .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA +gdt: .word 0x0,0x0,0x0,0x0 // Null entry + .word 0xffff,0x0,0x9a00,0xcf // SEL_SCODE + .word 0xffff,0x0,0x9200,0xcf // SEL_SDATA + .word 0xffff,0x0,0x9a00,0x0 // SEL_RCODE + .word 0xffff,0x0,0x9200,0x0 // SEL_RDATA gdt.1: -gdtdesc: .word gdt.1-gdt-1 # Limit - .long gdt # Base +gdtdesc: .word gdt.1-gdt-1 // Limit + .long gdt // Base /* * Messages. */ @@ -393,4 +393,4 @@ m_done: .asciz "Loading complete\n" /* * Uninitialized data area. */ -buf: # Scratch buffer +buf: // Scratch buffer diff --git a/sys/boot/i386/libi386/amd64_tramp.S b/sys/boot/i386/libi386/amd64_tramp.S index ff12c66..1e4a728 100644 --- a/sys/boot/i386/libi386/amd64_tramp.S +++ b/sys/boot/i386/libi386/amd64_tramp.S @@ -56,15 +56,15 @@ PT2: gdtdesc: .word gdtend - gdt - .long VTOP(gdt) # low - .long 0 # high + .long VTOP(gdt) // low + .long 0 // high gdt: - .long 0 # null descriptor + .long 0 // null descriptor .long 0 - .long 0x00000000 # %cs + .long 0x00000000 // %cs .long 0x00209800 - .long 0x00000000 # %ds + .long 0x00000000 // %ds .long 0x00008000 gdtend: diff --git a/sys/boot/i386/pxeldr/pxeldr.S b/sys/boot/i386/pxeldr/pxeldr.S index 25ab5c0..7c09c8a 100644 --- a/sys/boot/i386/pxeldr/pxeldr.S +++ b/sys/boot/i386/pxeldr/pxeldr.S @@ -19,7 +19,7 @@ * This simple program is a preloader for the normal boot3 loader. It is simply * prepended to the beginning of a fully built and btxld'd loader. It then * copies the loader to the address boot2 normally loads it, emulates the - * boot[12] environment (protected mode, a bootinfo struct, etc.), and then jumps + * boot[12] environment (protected mode, a bootinfo struct, etc.) and then jumps * to the start of btxldr to start the boot process. This method allows a stock * /boot/loader to be booted over the network via PXE w/o having to write a * separate PXE-aware client just to load the loader. @@ -28,45 +28,45 @@ /* * Memory locations. */ - .set MEM_PAGE_SIZE,0x1000 # memory page size, 4k - .set MEM_ARG,0x900 # Arguments at start - .set MEM_ARG_BTX,0xa100 # Where we move them to so the - # BTX client can see them - .set MEM_ARG_SIZE,0x18 # Size of the arguments - .set MEM_BTX_ADDRESS,0x9000 # where BTX lives - .set MEM_BTX_ENTRY,0x9010 # where BTX starts to execute - .set MEM_BTX_OFFSET,MEM_PAGE_SIZE # offset of BTX in the loader - .set MEM_BTX_CLIENT,0xa000 # where BTX clients live - .set MEM_BIOS_KEYBOARD,0x496 # BDA byte with keyboard bit + .set MEM_PAGE_SIZE,0x1000 // memory page size, 4k + .set MEM_ARG,0x900 // Arguments at start + .set MEM_ARG_BTX,0xa100 // Where we move them to so the + // BTX client can see them + .set MEM_ARG_SIZE,0x18 // Size of the arguments + .set MEM_BTX_ADDRESS,0x9000 // where BTX lives + .set MEM_BTX_ENTRY,0x9010 // where BTX starts to execute + .set MEM_BTX_OFFSET,MEM_PAGE_SIZE // offset of BTX in the loader + .set MEM_BTX_CLIENT,0xa000 // where BTX clients live + .set MEM_BIOS_KEYBOARD,0x496 // BDA byte with keyboard bit /* * a.out header fields */ - .set AOUT_TEXT,0x04 # text segment size - .set AOUT_DATA,0x08 # data segment size - .set AOUT_BSS,0x0c # zero'd BSS size - .set AOUT_SYMBOLS,0x10 # symbol table - .set AOUT_ENTRY,0x14 # entry point - .set AOUT_HEADER,MEM_PAGE_SIZE # size of the a.out header + .set AOUT_TEXT,0x04 // text segment size + .set AOUT_DATA,0x08 // data segment size + .set AOUT_BSS,0x0c // zero'd BSS size + .set AOUT_SYMBOLS,0x10 // symbol table + .set AOUT_ENTRY,0x14 // entry point + .set AOUT_HEADER,MEM_PAGE_SIZE // size of the a.out header /* * Flags for kargs->bootflags */ - .set KARGS_FLAGS_PXE,0x2 # flag to indicate booting from - # PXE loader + .set KARGS_FLAGS_PXE,0x2 // flag to indicate booting from + // PXE loader /* * Boot howto bits */ - .set RB_SERIAL,0x1000 # serial console + .set RB_SERIAL,0x1000 // serial console /* * Segment selectors. */ - .set SEL_SDATA,0x8 # Supervisor data - .set SEL_RDATA,0x10 # Real mode data - .set SEL_SCODE,0x18 # PM-32 code - .set SEL_SCODE16,0x20 # PM-16 code + .set SEL_SDATA,0x8 // Supervisor data + .set SEL_RDATA,0x10 // Real mode data + .set SEL_SCODE,0x18 // PM-32 code + .set SEL_SCODE16,0x20 // PM-16 code /* * BTX constants */ - .set INT_SYS,0x30 # BTX syscall interrupt + .set INT_SYS,0x30 // BTX syscall interrupt /* * Bit in MEM_BIOS_KEYBOARD that is set if an enhanced keyboard is present */ @@ -81,186 +81,190 @@ /* * BTX program loader for PXE network booting */ -start: cld # string ops inc - xorw %ax, %ax # zero %ax - movw %ax, %ss # setup the - movw $start, %sp # stack - movw %es, %cx # save PXENV+ segment - movw %ax, %ds # setup the - movw %ax, %es # data segments - andl $0xffff, %ecx # clear upper words - andl $0xffff, %ebx # of %ebx and %ecx - shll $4, %ecx # calculate the offset of - addl %ebx, %ecx # the PXENV+ struct and - pushl %ecx # save it on the stack - movw $welcome_msg, %si # %ds:(%si) -> welcome message - callw putstr # display the welcome message +start: cld // string ops inc + xorw %ax, %ax // zero %ax + movw %ax, %ss // setup the + movw $start, %sp // stack + movw %es, %cx // save PXENV+ segment + movw %ax, %ds // setup the + movw %ax, %es // data segments + andl $0xffff, %ecx // clear upper words + andl $0xffff, %ebx // of %ebx and %ecx + shll $4, %ecx // calculate the offset of + addl %ebx, %ecx // the PXENV+ struct and + pushl %ecx // save it on the stack + movw $welcome_msg, %si // %ds:(%si) -> welcome message + callw putstr // display the welcome message /* * Setup the arguments that the loader is expecting from boot[12] */ - movw $bootinfo_msg, %si # %ds:(%si) -> boot args message - callw putstr # display the message - movw $MEM_ARG, %bx # %ds:(%bx) -> boot args - movw %bx, %di # %es:(%di) -> boot args - xorl %eax, %eax # zero %eax - movw $(MEM_ARG_SIZE/4), %cx # Size of arguments in 32-bit - # dwords - rep # Clear the arguments - stosl # to zero - orb $KARGS_FLAGS_PXE, 0x8(%bx) # kargs->bootflags |= - # KARGS_FLAGS_PXE - popl 0xc(%bx) # kargs->pxeinfo = *PXENV+ + movw $bootinfo_msg, %si // %ds:(%si) -> boot args + // message + callw putstr // display the message + movw $MEM_ARG, %bx // %ds:(%bx) -> boot args + movw %bx, %di // %es:(%di) -> boot args + xorl %eax, %eax // zero %eax + movw $(MEM_ARG_SIZE/4), %cx // Size of arguments in 32-bit + // dwords + rep // Clear the arguments + stosl // to zero + orb $KARGS_FLAGS_PXE, 0x8(%bx) // kargs->bootflags |= + // KARGS_FLAGS_PXE + popl 0xc(%bx) // kargs->pxeinfo = *PXENV+ #ifdef ALWAYS_SERIAL /* * set the RBX_SERIAL bit in the howto byte. */ - orl $RB_SERIAL, (%bx) # enable serial console + orl $RB_SERIAL, (%bx) // enable serial console #endif #ifdef PROBE_KEYBOARD /* * Look at the BIOS data area to see if we have an enhanced keyboard. If not, * set the RBX_SERIAL bit in the howto byte. */ - testb $KEYBOARD_BIT, MEM_BIOS_KEYBOARD # keyboard present? - jnz keyb # yes, so skip - orl $RB_SERIAL, (%bx) # enable serial console + testb $KEYBOARD_BIT, MEM_BIOS_KEYBOARD // keyboard present? + jnz keyb // yes, so skip + orl $RB_SERIAL, (%bx) // enable serial console keyb: #endif /* * Turn on the A20 address line */ - callw seta20 # Turn A20 on + callw seta20 // Turn A20 on /* * Relocate the loader and BTX using a very lazy protected mode */ - movw $relocate_msg, %si # Display the - callw putstr # relocation message - movl end+AOUT_ENTRY, %edi # %edi is the destination - movl $(end+AOUT_HEADER), %esi # %esi is - # the start of the text - # segment - movl end+AOUT_TEXT, %ecx # %ecx = length of the text - # segment - lgdt gdtdesc # setup our own gdt - cli # turn off interrupts - movl %cr0, %eax # Turn on - orb $0x1, %al # protected - movl %eax, %cr0 # mode - ljmp $SEL_SCODE,$pm_start # long jump to clear the - # instruction pre-fetch queue + movw $relocate_msg, %si // Display the + callw putstr // relocation message + movl end+AOUT_ENTRY, %edi // %edi is the destination + movl $(end+AOUT_HEADER), %esi // %esi is + // the start of the text + // segment + movl end+AOUT_TEXT, %ecx // %ecx = length of the text + // segment + lgdt gdtdesc // setup our own gdt + cli // turn off interrupts + movl %cr0, %eax // Turn on + orb $0x1, %al // protected + movl %eax, %cr0 // mode + ljmp $SEL_SCODE,$pm_start // long jump to clear the + // instruction pre-fetch queue .code32 -pm_start: movw $SEL_SDATA, %ax # Initialize - movw %ax, %ds # %ds and - movw %ax, %es # %es to a flat selector - rep # Relocate the - movsb # text segment - addl $(MEM_PAGE_SIZE - 1), %edi # pad %edi out to a new page - andl $~(MEM_PAGE_SIZE - 1), %edi # for the data segment - movl end+AOUT_DATA, %ecx # size of the data segment - rep # Relocate the - movsb # data segment - movl end+AOUT_BSS, %ecx # size of the bss - xorl %eax, %eax # zero %eax - addb $3, %cl # round %ecx up to - shrl $2, %ecx # a multiple of 4 - rep # zero the - stosl # bss - movl end+AOUT_ENTRY, %esi # %esi -> relocated loader - addl $MEM_BTX_OFFSET, %esi # %esi -> BTX in the loader - movl $MEM_BTX_ADDRESS, %edi # %edi -> where BTX needs to go - movzwl 0xa(%esi), %ecx # %ecx -> length of BTX - rep # Relocate - movsb # BTX - ljmp $SEL_SCODE16,$pm_16 # Jump to 16-bit PM +pm_start: movw $SEL_SDATA, %ax // Initialize + movw %ax, %ds // %ds and + movw %ax, %es // %es to a flat selector + rep // Relocate the + movsb // text segment + addl $(MEM_PAGE_SIZE - 1), %edi // pad %edi out to a new page + andl $~(MEM_PAGE_SIZE - 1), %edi // for the data segment + movl end+AOUT_DATA, %ecx // size of the data segment + rep // Relocate the + movsb // data segment + movl end+AOUT_BSS, %ecx // size of the bss + xorl %eax, %eax // zero %eax + addb $3, %cl // round %ecx up to + shrl $2, %ecx // a multiple of 4 + rep // zero the + stosl // bss + movl end+AOUT_ENTRY, %esi // %esi -> relocated loader + addl $MEM_BTX_OFFSET, %esi // %esi -> BTX in the loader + movl $MEM_BTX_ADDRESS, %edi // %edi -> where BTX needs to go + movzwl 0xa(%esi), %ecx // %ecx -> length of BTX + rep // Relocate + movsb // BTX + ljmp $SEL_SCODE16,$pm_16 // Jump to 16-bit PM .code16 -pm_16: movw $SEL_RDATA, %ax # Initialize - movw %ax, %ds # %ds and - movw %ax, %es # %es to a real mode selector - movl %cr0, %eax # Turn off - andb $~0x1, %al # protected - movl %eax, %cr0 # mode - ljmp $0,$pm_end # Long jump to clear the - # instruction pre-fetch queue -pm_end: sti # Turn interrupts back on now +pm_16: movw $SEL_RDATA, %ax // Initialize + movw %ax, %ds // %ds and + movw %ax, %es // %es to a real mode selector + movl %cr0, %eax // Turn off + andb $~0x1, %al // protected + movl %eax, %cr0 // mode + ljmp $0,$pm_end // Long jump to clear the + // instruction pre-fetch queue +pm_end: sti // Turn interrupts back on now /* * Copy the BTX client to MEM_BTX_CLIENT */ - xorw %ax, %ax # zero %ax and set - movw %ax, %ds # %ds and %es - movw %ax, %es # to segment 0 - movw $MEM_BTX_CLIENT, %di # Prepare to relocate - movw $btx_client, %si # the simple btx client - movw $(btx_client_end-btx_client), %cx # length of btx client - rep # Relocate the - movsb # simple BTX client + xorw %ax, %ax // zero %ax and set + movw %ax, %ds // %ds and %es + movw %ax, %es // to segment 0 + movw $MEM_BTX_CLIENT, %di // Prepare to relocate + movw $btx_client, %si // the simple btx client + movw $(btx_client_end-btx_client), %cx // length of btx client + rep // Relocate the + movsb // simple BTX client /* * Copy the boot[12] args to where the BTX client can see them */ - movw $MEM_ARG, %si # where the args are at now - movw $MEM_ARG_BTX, %di # where the args are moving to - movw $(MEM_ARG_SIZE/4), %cx # size of the arguments in longs - rep # Relocate - movsl # the words + movw $MEM_ARG, %si // where the args are at now + movw $MEM_ARG_BTX, %di // where the args are moving to + movw $(MEM_ARG_SIZE/4), %cx // size of the arguments in + // longs + rep // Relocate + movsl // the words /* * Save the entry point so the client can get to it later on */ - movl end+AOUT_ENTRY, %eax # load the entry point - stosl # add it to the end of the - # arguments + movl end+AOUT_ENTRY, %eax // load the entry point + stosl // add it to the end of the + // arguments /* * Now we just start up BTX and let it do the rest */ - movw $jump_message, %si # Display the - callw putstr # jump message - ljmp $0,$MEM_BTX_ENTRY # Jump to the BTX entry point + movw $jump_message, %si // Display the + callw putstr // jump message + ljmp $0,$MEM_BTX_ENTRY // Jump to the BTX entry point /* * Display a null-terminated string */ -putstr: lodsb # load %al from %ds:(%si) - testb %al,%al # stop at null - jnz putc # if the char != null, output it - retw # return when null is hit -putc: movw $0x7,%bx # attribute for output - movb $0xe,%ah # BIOS: put_char - int $0x10 # call BIOS, print char in %al - jmp putstr # keep looping +putstr: lodsb // load %al from %ds:(%si) + testb %al,%al // stop at null + jnz putc // if the char != null, + // output it + retw // return when null is hit +putc: movw $0x7,%bx // attribute for output + movb $0xe,%ah // BIOS: put_char + int $0x10 // call BIOS, print char in %al + jmp putstr // keep looping /* * Enable A20 */ -seta20: cli # Disable interrupts -seta20.1: inb $0x64,%al # Get status - testb $0x2,%al # Busy? - jnz seta20.1 # Yes - movb $0xd1,%al # Command: Write - outb %al,$0x64 # output port -seta20.2: inb $0x64,%al # Get status - testb $0x2,%al # Busy? - jnz seta20.2 # Yes - movb $0xdf,%al # Enable - outb %al,$0x60 # A20 - sti # Enable interrupts - retw # To caller +seta20: cli // Disable interrupts +seta20.1: inb $0x64,%al // Get status + testb $0x2,%al // Busy? + jnz seta20.1 // Yes + movb $0xd1,%al // Command: Write + outb %al,$0x64 // output port +seta20.2: inb $0x64,%al // Get status + testb $0x2,%al // Busy? + jnz seta20.2 // Yes + movb $0xdf,%al // Enable + outb %al,$0x60 // A20 + sti // Enable interrupts + retw // To caller /* * BTX client to start btxldr */ .code32 btx_client: movl $(MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE-4), %esi - # %ds:(%esi) -> end - # of boot[12] args - movl $(MEM_ARG_SIZE/4), %ecx # Number of words to push - std # Go backwards -push_arg: lodsl # Read argument - pushl %eax # Push it onto the stack - loop push_arg # Push all of the arguments - cld # In case anyone depends on this - pushl MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE # Entry point of - # the loader - pushl %eax # Emulate a near call - movl $0x1, %eax # 'exec' system call - int $INT_SYS # BTX system call + // %ds:(%esi) -> end + // of boot[12] args + movl $(MEM_ARG_SIZE/4), %ecx // Number of words to push + std // Go backwards +push_arg: lodsl // Read argument + pushl %eax // Push it onto the stack + loop push_arg // Push all of the arguments + cld // In case anyone depends + // on this + pushl MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE // Entry point of + // the loader + pushl %eax // Emulate a near call + movl $0x1, %eax // 'exec' system call + int $INT_SYS // BTX system call btx_client_end: .code16 @@ -268,17 +272,17 @@ btx_client_end: /* * Global descriptor table. */ -gdt: .word 0x0,0x0,0x0,0x0 # Null entry - .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA - .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA - .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE (32-bit) - .word 0xffff,0x0,0x9a00,0x8f # SEL_SCODE16 (16-bit) +gdt: .word 0x0,0x0,0x0,0x0 // Null entry + .word 0xffff,0x0,0x9200,0xcf // SEL_SDATA + .word 0xffff,0x0,0x9200,0x0 // SEL_RDATA + .word 0xffff,0x0,0x9a00,0xcf // SEL_SCODE (32-bit) + .word 0xffff,0x0,0x9a00,0x8f // SEL_SCODE16 (16-bit) gdt.1: /* * Pseudo-descriptors. */ -gdtdesc: .word gdt.1-gdt-1 # Limit - .long gdt # Base +gdtdesc: .word gdt.1-gdt-1 // Limit + .long gdt // Base welcome_msg: .asciz "PXE Loader 1.00\r\n\n" bootinfo_msg: .asciz "Building the boot loader arguments\r\n" -- cgit v1.1