github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/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 TEXT ·start(SB),NOSPLIT,$0 20 // Create GDT pointer on stack. 21 LEAQ gdt(SB), CX 22 SHLQ $16, CX 23 ORQ $(4*8 - 1), CX 24 PUSHQ CX 25 26 LGDT (SP) 27 28 // Store value of multiboot info addr in BX. 29 // Don't modify BX. 30 MOVL ·info(SB), BX 31 32 // Store value of mu(l)tiboot magic in SI. 33 // Don't modify SI. 34 MOVL ·magic(SB), SI 35 36 // Far return doesn't work on QEMU in 64-bit mode, 37 // let's do far jump. 38 // 39 // In a regular plan9 assembly we can do something like: 40 // BYTE $0xFF; BYTE $0x2D 41 // LONG $bootaddr(SB) 42 // TEXT bootaddr(SB),NOSPLIT,$0 43 // LONG $boot(SB) 44 // LONG $0x8 45 // 46 // Go compiler doesn't let us do it. 47 // 48 // Setup offset to make a far jump from boot(SB) 49 // to a final kernel in a 32-bit mode. 50 MOVL ·entry(SB), AX 51 MOVL AX, farjump32+1(SB) 52 53 // Setup offset to make a far jump to boot(SB) 54 // to switch from 64-bit mode to 32-bit mode. 55 LEAQ boot(SB), CX 56 MOVL CX, farjump64+6(SB) 57 JMP farjump64(SB) 58 59 60 TEXT boot(SB),NOSPLIT,$0 61 // We are in 32-bit mode now. 62 // 63 // Be careful editing this code!!! Go compiler 64 // interprets all commands as 64-bit commands. 65 66 // Disable paging. 67 MOVL CR0, AX 68 ANDL $CR0_PG, AX 69 MOVL AX, CR0 70 71 // Disable long mode. 72 MOVL $MSR_EFER, CX 73 RDMSR 74 ANDL $EFER_LME, AX 75 WRMSR 76 77 // Disable PAE. 78 XORL AX, AX 79 MOVL AX, CR4 80 81 // Load data segments. 82 MOVL $0x10, AX // GDT 0x10 data segment 83 BYTE $0x8e; BYTE $0xd8 // MOVL AX, DS 84 BYTE $0x8e; BYTE $0xc0 // MOVL AX, ES 85 BYTE $0x8e; BYTE $0xd0 // MOVL AX, SS 86 BYTE $0x8e; BYTE $0xe0 // MOVL AX, FS 87 BYTE $0x8e; BYTE $0xe8 // MOVL AX, GS 88 89 // We stored the magic in SI before the far jump. 90 MOVL SI, AX 91 JMP farjump32(SB) 92 93 TEXT farjump64(SB),NOSPLIT,$0 94 BYTE $0xFF; BYTE $0x2D; LONG $0x0 // ljmp *(ip) 95 96 LONG $0x0 // farjump64+6(SB) 97 LONG $0x8 // code segment 98 99 TEXT farjump32(SB),NOSPLIT,$0 100 // ljmp $0x18, offset 101 BYTE $0xEA 102 LONG $0x0 // farjump32+1(SB) 103 WORD $0x18 // code segment 104 105 TEXT gdt(SB),NOSPLIT,$0 106 QUAD $0x0 // 0x0 null entry 107 QUAD $CODE_SEGMENT // 0x8 108 QUAD $DATA_SEGMENT // 0x10 109 QUAD $CODE_SEGMENT // 0x18 110 111 TEXT ·info(SB),NOSPLIT,$0 112 LONG $0x0 113 114 TEXT ·entry(SB),NOSPLIT,$0 115 LONG $0x0 116 117 TEXT ·magic(SB),NOSPLIT,$0 118 LONG $0x0 119 120 TEXT ·end(SB),NOSPLIT,$0