|
|
1.1 ! root 1: /* netboot ! 2: * ! 3: * start.s,v ! 4: # Revision 1.1 1993/07/08 16:04:11 brezak ! 5: # Diskless boot prom code from Jim McKim ([email protected]) ! 6: # ! 7: * Revision 1.3 1993/06/30 20:19:14 mckim ! 8: * Exit to BIOS support added. ! 9: * ! 10: * Revision 1.2 1993/05/28 20:01:30 mckim ! 11: * Fixed various StartProg() problems. ! 12: * ! 13: * Revision 1.1.1.1 1993/05/28 11:41:08 mckim ! 14: * Initial version. ! 15: * ! 16: */ ! 17: ! 18: #include "asm.h" ! 19: ! 20: /* At entry, the processor is in 16 bit real mode and the code is being ! 21: * executed from an address it was not linked to. Code must be pic and ! 22: * 32 bit sensitive until things are fixed up. ! 23: */ ! 24: ! 25: .word 0xaa55 /* bios extension signature */ ! 26: .byte 0 /* no. of 512B blocks */ ! 27: jmp 1f /* enter from bios here */ ! 28: .byte 0 /* checksum */ ! 29: 1: ! 30: cli ! 31: # save the bios return address in these registers until protected ! 32: # mode %ds is set up ! 33: # mov (%esp), %edx ! 34: # mov 2(%esp), %ebp ! 35: pop %dx /* return offset */ ! 36: pop %ebp /* return segment */ ! 37: ! 38: /* save stack [, data] context in case we are under dos */ ! 39: mov %esp, %ecx ! 40: mov %ss, %ax ! 41: mov %eax, %ebx ! 42: ! 43: /* set up a usable stack */ ! 44: .byte 0xb8 /* (mov $0xa000, %ax) */ ! 45: .word 0xa000 ! 46: mov %ax, %ss ! 47: xor %esp, %esp ! 48: ! 49: push %ebp /* return segment */ ! 50: push %dx /* return offset */ ! 51: push %ds ! 52: ! 53: #if 0 ! 54: jmp ret16 ! 55: #endif ! 56: ! 57: ! 58: #ifdef CHECK_386 ! 59: # check if 386 or later ! 60: # from Intel i486 programmer\'s reference manual, section 22.10 ! 61: # Care must be taken with the first few instructions to ensure ! 62: # operations are compatible with 386 progenitors - no operand ! 63: # or address size overrides, all operations must be 16 bit. ! 64: # Real mode not well supported by gas so it looks a bit crufty ! 65: ! 66: # TBD - there is little stack space, although the routine below ! 67: # uses only two bytes; might set up new stack first thing, then ! 68: # check processor type - would mean carrying sp, ss in two gp ! 69: # registers for a while. also make alternate provisions for saving ! 70: # ds: below. ! 71: ! 72: pushf ! 73: pop %ebx ! 74: .byte 0x81, 0xe3 /* (and 0x0fff, %ebx) */ ! 75: .word 0x0fff ! 76: push %ebx ! 77: popf ! 78: pushf ! 79: pop %eax ! 80: .byte 0x25 /* (and 0xf000, %eax) */ ! 81: .word 0xf000 ! 82: .byte 0x3d /* (cmp 0xf000, %eax) */ ! 83: .word 0xf000 ! 84: jz Lwrong_cpu /* \'86 */ ! 85: .byte 0x81, 0xcb /* (or 0xf000, %ebx) */ ! 86: .word 0xf000 ! 87: push %ebx ! 88: popf ! 89: pushf ! 90: pop %eax ! 91: .byte 0x25 /* (and 0xf000, %eax) */ ! 92: .word 0xf000 ! 93: jnz Lcpu_ok /* else is \'286 */ ! 94: ! 95: Lwrong_cpu: ! 96: .byte 0xbb /* (mov bad_cpu_msg, %ebx) */ ! 97: .word bad_cpu_msg ! 98: .byte 0xe8 /* (call xputs) */ ! 99: .word xputs-.-2 ! 100: lret ! 101: ! 102: xputc: /* print byte in %al */ ! 103: data32 ! 104: pusha ! 105: .byte 0xbb /* (mov $0x1, %ebx) %bh=0, %bl=1 (blue) */ ! 106: .word 0x0001 ! 107: movb $0xe, %ah ! 108: # sti ! 109: int $0x10 /* display a byte */ ! 110: # cli ! 111: data32 ! 112: popa ! 113: ret ! 114: ! 115: xputs: /* print string pointed to by cs:bx */ ! 116: data32 ! 117: pusha ! 118: 1: ! 119: cs ! 120: .byte 0x8a, 0x07 /* (mov (%ebx), %al) */ ! 121: cmpb $0, %al ! 122: jz 1f ! 123: push %ebx ! 124: .byte 0xe8 /* (call xputc) */ ! 125: .word xputc-.-2 ! 126: pop %ebx ! 127: inc %ebx ! 128: jmp 1b ! 129: 1: ! 130: data32 ! 131: popa ! 132: ret ! 133: ! 134: bad_cpu_msg: .asciz "netboot: cpu cannot execute '386 instructions, net boot not done.\n\r" ! 135: ! 136: Lcpu_ok: ! 137: # at this point it is known this can execute 386 instructions ! 138: # so operand and address size prefixes are ok ! 139: #endif /* CHECK_386 */ ! 140: ! 141: /* copy rom to link addr, prepare for relocation */ ! 142: xor %esi, %esi /* source */ ! 143: opsize ! 144: mov $0, %edi /* destination */ ! 145: opsize ! 146: mov $(RELOC)>>4, %eax ! 147: mov %ax, %es ! 148: opsize ! 149: mov $(ROM_SIZE), %ecx /* count */ ! 150: cs ! 151: rep ! 152: movsb ! 153: ! 154: addrsize ! 155: cs ! 156: lgdt gdtarg-RELOC ! 157: ! 158: /* turn on protected mode */ ! 159: cli ! 160: mov %cr0, %eax ! 161: opsize ! 162: or $CR0_PE, %eax ! 163: mov %eax, %cr0 ! 164: ! 165: /* jump to relocation, flush prefetch queue, and reload %cs */ ! 166: opsize ! 167: ljmp $KERN_CODE_SEG, $1f ! 168: 1: ! 169: /* reload other segment registers */ ! 170: movl $KERN_DATA_SEG, %eax ! 171: movl %ax, %ds ! 172: movl %ax, %es ! 173: movl %ax, %ss ! 174: movl $0xa0000, %esp ! 175: call _main ! 176: call _exit ! 177: ! 178: _ExitToBios: ! 179: .globl _ExitToBios ! 180: /* set up a dummy stack frame for the second seg change. */ ! 181: mov $(RELOC)>>4, %eax ! 182: pushw %ax /* real cs */ ! 183: pushw $2f /* real pc */ ! 184: ! 185: /* Change to use16 mode. */ ! 186: ljmp $BOOT_16_SEG, $1f /* jump to a 16 bit segment */ ! 187: 1: ! 188: /* clear the PE bit of CR0 */ ! 189: mov %cr0, %eax ! 190: opsize ! 191: and $0!CR0_PE, %eax ! 192: mov %eax, %cr0 ! 193: ! 194: /* make intersegment jmp to flush the processor pipeline ! 195: * using the fake stack frame set up earlier ! 196: * and reload CS register ! 197: */ ! 198: lret ! 199: 2: ! 200: /* we are in real mode now ! 201: * set up the real mode segment registers : DS, SS, ES ! 202: */ ! 203: movw %cs, %ax ! 204: movw %ax, %ds ! 205: movw %ax, %ss ! 206: movw %ax, %es ! 207: ! 208: ret16: /* temporary label - remove (TBD) */ ! 209: /* now in dumbed down mode, caveats */ ! 210: /* restore old context and return to whatever called us */ ! 211: pop %ds ! 212: pop %dx ! 213: pop %ebp ! 214: ! 215: mov %ebx, %eax ! 216: mov %ax, %ss ! 217: mov %ecx, %esp ! 218: ! 219: push %ebp ! 220: push %dx ! 221: sti ! 222: lret ! 223: ! 224: #ifdef USE_BIOS ! 225: _real_to_prot: ! 226: .global _real_to_prot ! 227: ! 228: addrsize ! 229: cs ! 230: lgdt gdtarg-RELOC ! 231: cli ! 232: mov %cr0, %eax ! 233: opsize ! 234: or $CR0_PE, %eax ! 235: mov %eax, %cr0 ! 236: ! 237: /* jump to relocation, flush prefetch queue, and reload %cs */ ! 238: opsize ! 239: ljmp $KERN_CODE_SEG, $1f ! 240: 1: ! 241: movl $KERN_DATA_SEG, %eax ! 242: movl %ax, %ds ! 243: movl %ax, %es ! 244: movl %ax, %ss ! 245: ! 246: ret ! 247: #endif ! 248: ! 249: #ifdef USE_BIOS ! 250: _prot_to_real: ! 251: .global _prot_to_real ! 252: ! 253: /* set up a dummy stack frame for the second seg change. */ ! 254: movl $(RELOC), %eax ! 255: sarl $4, %eax ! 256: pushw %ax /* real cs */ ! 257: pushw $2f /* real pc */ ! 258: ! 259: /* Change to use16 mode. */ ! 260: ljmp $BOOT_16_SEG, $1f /* jump to a 16 bit segment */ ! 261: 1: ! 262: /* clear the PE bit of CR0 */ ! 263: mov %cr0, %eax ! 264: opsize ! 265: and $0!CR0_PE, %eax ! 266: mov %eax, %cr0 ! 267: ! 268: /* make intersegment jmp to flush the processor pipeline ! 269: * using the fake stack frame set up earlier ! 270: * and reload CS register ! 271: */ ! 272: lret ! 273: 2: ! 274: /* we are in real mode now ! 275: * set up the real mode segment registers : DS, SS, ES ! 276: */ ! 277: movw %cs, %ax ! 278: movw %ax, %ds ! 279: movw %ax, %ss ! 280: movw %ax, %es ! 281: ! 282: opsize ! 283: ret ! 284: #endif ! 285: ! 286: .align 4 ! 287: gdt: ! 288: .word 0, 0 ! 289: .byte 0, 0x00, 0x00, 0 ! 290: ! 291: /* code segment */ ! 292: .word 0xffff, 0 ! 293: .byte 0, 0x9f, 0xcf, 0 ! 294: ! 295: /* data segment */ ! 296: .word 0xffff, 0 ! 297: .byte 0, 0x93, 0xcf, 0 ! 298: ! 299: /* 16 bit real mode */ ! 300: .word 0xffff, 0 ! 301: .byte 0, 0x9e, 0x00, 0 ! 302: ! 303: .align 4 ! 304: gdtarg: ! 305: .word 0x1f /* limit */ ! 306: .long gdt /* addr */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.