1/* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12/* 13 * Copyright 2016 Toomas Soome <tsoome@me.com> 14 */ 15 16#include <x86/specialreg.h> 17 18 .file "multiboot_tramp.s" 19 20/* 21 * dboot expects a 32-bit multiboot environment and to execute in 32-bit mode. 22 * 23 * EAX: MB magic 24 * EBX: 32-bit physical address of MBI 25 * CS: 32-bit read/execute code segment with offset 0 and limit 0xFFFFFFFF 26 * DS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF 27 * ES: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF 28 * FS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF 29 * GS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF 30 * SS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF 31 * A20 enabled 32 * CR0: PG cleared, PE set 33 * EFLAGS: VM cleared, IF cleared 34 * interrupts disabled 35 */ 36 37 .set SEL_SCODE,0x8 38 .set SEL_SDATA,0x10 39 40 .text 41 .p2align 4 42 .globl multiboot_tramp 43 .type multiboot_tramp, STT_FUNC 44 45/* 46 * Note as we are running in 32-bit mode, all pointers are 32-bit. 47 * void multiboot_tramp(uint32_t magic, struct relocator *relocator, 48 * vm_offset_t entry) 49 */ 50multiboot_tramp: 51 cli 52 pushl %ebp /* keep familiar stack frame */ 53 movl %esp, %ebp /* current SP */ 54 movl 0xc(%ebp),%eax /* relocator */ 55 movl (%eax), %eax /* new SP */ 56 movl %eax, %esp 57 58 /* now copy arguments to new stack */ 59 movl 0x10(%ebp),%eax /* entry */ 60 pushl %eax 61 movl 0xc(%ebp),%eax /* relocator */ 62 pushl %eax 63 movl 0x8(%ebp),%eax /* magic */ 64 pushl %eax 65 xorl %eax,%eax 66 pushl %eax /* fake IP, just to keep stack frame */ 67 pushl %ebp 68 movl %esp, %ebp 69 subl $0x30, %esp /* local mbi, gdt and gdt desc */ 70 71 movl 0xc(%ebp), %eax /* relocator */ 72 pushl %eax 73 movl 0x4(%eax), %eax /* relocator->copy */ 74 call *%eax 75 addl $0x4, %esp 76 movl %eax, -0x4(%ebp) /* save MBI */ 77 78 /* set up GDT descriptor */ 79 lea -0x1c(%ebp), %eax /* address of GDT */ 80 movw $0x17, -0x22(%ebp) /* limit */ 81 movl %eax, -0x20(%ebp) /* base */ 82 83/* 84 * set up following GDT: 85 * .word 0x0, 0x0 NULL entry 86 * .byte 0x0, 0x0, 0x0, 0x0 87 * .word 0xffff, 0x0 code segment 88 * .byte 0x0, 0x9a, 0xcf, 0x0 89 * .word 0xffff, 0x0 data segment 90 * .byte 0x0, 0x92, 0xcf, 0x0 91 * 92 * This will create access for 4GB flat memory with 93 * base = 0x00000000, segment limit = 0xffffffff 94 * page granulariy 4k 95 * 32-bit protected mode 96 * ring 0 97 * code segment is executable RW 98 * data segment is not-executable RW 99 */ 100 movw $0x0, -0x1c(%ebp) 101 movw $0x0, -0x1a(%ebp) 102 movb $0x0, -0x18(%ebp) 103 movb $0x0, -0x17(%ebp) 104 movb $0x0, -0x16(%ebp) 105 movb $0x0, -0x15(%ebp) 106 107 movw $0xffff, -0x14(%ebp) 108 movw $0x0, -0x12(%ebp) 109 movb $0x0, -0x10(%ebp) 110 movb $0x9a, -0xf(%ebp) 111 movb $0xcf, -0xe(%ebp) 112 movb $0x0, -0xd(%ebp) 113 114 movw $0xffff, -0xc(%ebp) 115 movw $0x0, -0xa(%ebp) 116 movb $0x0, -0x8(%ebp) 117 movb $0x92, -0x7(%ebp) 118 movb $0xcf, -0x6(%ebp) 119 movb $0x0, -0x5(%ebp) 120 121 lea -0x22(%ebp), %eax /* address of GDT */ 122 lgdt (%eax) 123 124 movl 0x8(%ebp), %edx /* magic */ 125 movl -0x4(%ebp), %ebx /* MBI */ 126 movl 0x10(%ebp), %esi /* entry */ 127 128 movl $SEL_SDATA, %eax 129 movw %ax, %ss 130 movw %ax, %ds 131 movw %ax, %es 132 movw %ax, %fs 133 movw %ax, %gs 134 135 /* 136 * We most likely don't need to push SEL_SDATA and esp 137 * because we do not expect to perform a privilege transition. 138 * However, it doesn't hurt us to push them as dboot will set 139 * up its own stack. 140 */ 141 movl %esp, %eax 142 pushl $SEL_SDATA 143 pushl %eax 144 pushf 145 pushl $SEL_SCODE 146 pushl %esi 147 movl %edx, %eax 148 iretl 149 150multiboot_tramp_end: 151