github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/boot/multiboot/internal/trampoline/trampoline_linux_amd64.s (about) 1 // Copyright 2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // We want all the trampoline's assembly code to be located 6 // in a contiguous byte range in a compiled binary. 7 // Go compiler does not guarantee that. Still, current version 8 // of compiler puts all pieces together. 9 10 #include "textflag.h" 11 12 #define MSR_EFER 0xC0000080 13 #define EFER_LME 0xFFFFFEFF 14 #define CR0_PG 0x0FFFFFFF 15 16 #define DATA_SEGMENT 0x00CF92000000FFFF 17 #define CODE_SEGMENT 0x00CF9A000000FFFF 18 19 // func addrOfStart() uintptr 20 TEXT ·addrOfStart(SB), $0-8 21 MOVQ $start(SB), AX 22 MOVQ AX, ret+0(FP) 23 RET 24 25 // func addrOfEnd() uintptr 26 TEXT ·addrOfEnd(SB), $0-8 27 MOVQ $end(SB), AX 28 MOVQ AX, ret+0(FP) 29 RET 30 31 // func addrOfInfo() uintptr 32 TEXT ·addrOfInfo(SB), $0-8 33 MOVQ $info(SB), AX 34 MOVQ AX, ret+0(FP) 35 RET 36 37 // func addrOfMagic() uintptr 38 TEXT ·addrOfMagic(SB), $0-8 39 MOVQ $magic(SB), AX 40 MOVQ AX, ret+0(FP) 41 RET 42 43 // func addrOfEntry() uintptr 44 TEXT ·addrOfEntry(SB), $0-8 45 MOVQ $entry(SB), AX 46 MOVQ AX, ret+0(FP) 47 RET 48 49 TEXT start(SB),NOSPLIT,$0 50 // Create GDT pointer on stack. 51 LEAQ gdt(SB), CX 52 SHLQ $16, CX 53 ORQ $(4*8 - 1), CX 54 PUSHQ CX 55 56 LGDT (SP) 57 58 // Store value of multiboot info addr in BX. 59 // Don't modify BX. 60 MOVL info(SB), BX 61 62 // Store value of mu(l)tiboot magic in SI. 63 // Don't modify SI. 64 MOVL magic(SB), SI 65 66 // Far return doesn't work on QEMU in 64-bit mode, 67 // let's do far jump. 68 // 69 // In a regular plan9 assembly we can do something like: 70 // BYTE $0xFF; BYTE $0x2D 71 // LONG $bootaddr(SB) 72 // TEXT bootaddr(SB),NOSPLIT,$0 73 // LONG $boot(SB) 74 // LONG $0x8 75 // 76 // Go compiler doesn't let us do it. 77 // 78 // Setup offset to make a far jump from boot(SB) 79 // to a final kernel in a 32-bit mode. 80 MOVL entry(SB), AX 81 MOVL AX, farjump32+1(SB) 82 83 // Setup offset to make a far jump to boot(SB) 84 // to switch from 64-bit mode to 32-bit mode. 85 LEAQ boot(SB), CX 86 MOVL CX, farjump64+6(SB) 87 JMP farjump64(SB) 88 89 90 TEXT boot(SB),NOSPLIT,$0 91 // We are in 32-bit mode now. 92 // 93 // Be careful editing this code!!! Go compiler 94 // interprets all commands as 64-bit commands. 95 96 // Disable paging. 97 MOVL CR0, AX 98 ANDL $CR0_PG, AX 99 MOVL AX, CR0 100 101 // Disable long mode. 102 MOVL $MSR_EFER, CX 103 RDMSR 104 ANDL $EFER_LME, AX 105 WRMSR 106 107 // Disable PAE. 108 XORL AX, AX 109 MOVL AX, CR4 110 111 // Load data segments. 112 MOVL $0x10, AX // GDT 0x10 data segment 113 BYTE $0x8e; BYTE $0xd8 // MOVL AX, DS 114 BYTE $0x8e; BYTE $0xc0 // MOVL AX, ES 115 BYTE $0x8e; BYTE $0xd0 // MOVL AX, SS 116 BYTE $0x8e; BYTE $0xe0 // MOVL AX, FS 117 BYTE $0x8e; BYTE $0xe8 // MOVL AX, GS 118 119 // We stored the magic in SI before the far jump. 120 MOVL SI, AX 121 JMP farjump32(SB) 122 123 TEXT farjump64(SB),NOSPLIT,$0 124 BYTE $0xFF; BYTE $0x2D; LONG $0x0 // ljmp *(ip) 125 126 LONG $0x0 // farjump64+6(SB) 127 LONG $0x8 // code segment 128 129 TEXT farjump32(SB),NOSPLIT,$0 130 // ljmp $0x18, offset 131 BYTE $0xEA 132 LONG $0x0 // farjump32+1(SB) 133 WORD $0x18 // code segment 134 135 TEXT gdt(SB),NOSPLIT,$0 136 QUAD $0x0 // 0x0 null entry 137 QUAD $CODE_SEGMENT // 0x8 138 QUAD $DATA_SEGMENT // 0x10 139 QUAD $CODE_SEGMENT // 0x18 140 141 TEXT info(SB),NOSPLIT,$0 142 LONG $0x0 143 144 TEXT entry(SB),NOSPLIT,$0 145 LONG $0x0 146 147 TEXT magic(SB),NOSPLIT,$0 148 LONG $0x0 149 150 TEXT end(SB),NOSPLIT,$0