diff options
author | ru <ru@FreeBSD.org> | 2004-05-14 20:29:30 +0000 |
---|---|---|
committer | ru <ru@FreeBSD.org> | 2004-05-14 20:29:30 +0000 |
commit | 9d75d5e3a570a2d9da34b9cdd60eb4ce488a9073 (patch) | |
tree | a1d07b6a6ab6f3789e2952ef64b917b2ea697b90 /sys/boot/i386 | |
parent | 81741e7e6db50d912c4e5fbedcdcc37c63d6b1f2 (diff) | |
download | FreeBSD-src-9d75d5e3a570a2d9da34b9cdd60eb4ce488a9073.zip FreeBSD-src-9d75d5e3a570a2d9da34b9cdd60eb4ce488a9073.tar.gz |
Back out last revision that unnecessarily changed valid assembler
line comments and damaged the CVS history.
Prompted by: bde, jhb
Diffstat (limited to 'sys/boot/i386')
-rw-r--r-- | sys/boot/i386/boot2/boot1.S | 420 | ||||
-rw-r--r-- | sys/boot/i386/boot2/sio.S | 84 | ||||
-rw-r--r-- | sys/boot/i386/btx/btx/btx.S | 1841 | ||||
-rw-r--r-- | sys/boot/i386/btx/btxldr/btxldr.S | 522 | ||||
-rw-r--r-- | sys/boot/i386/libi386/amd64_tramp.S | 10 | ||||
-rw-r--r-- | sys/boot/i386/pxeldr/pxeldr.S | 330 |
6 files changed, 1601 insertions, 1606 deletions
diff --git a/sys/boot/i386/boot2/boot1.S b/sys/boot/i386/boot2/boot1.S index 79e732b..badaee8 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 6ec4491..3fc2963 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 77cfe86..7581519 100644 --- a/sys/boot/i386/btx/btx/btx.S +++ b/sys/boot/i386/btx/btx/btx.S @@ -18,588 +18,587 @@ /* * 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 @@ -607,566 +606,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 22adbcc..aa531b8 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 1e4a728..ff12c66 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 7c09c8a..25ab5c0 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,190 +81,186 @@ /* * 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 @@ -272,17 +268,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" |