1f16408dfSAlexander Graf/* 2f16408dfSAlexander Graf * Multiboot Option ROM 3f16408dfSAlexander Graf * 4f16408dfSAlexander Graf * This program is free software; you can redistribute it and/or modify 5f16408dfSAlexander Graf * it under the terms of the GNU General Public License as published by 6f16408dfSAlexander Graf * the Free Software Foundation; either version 2 of the License, or 7f16408dfSAlexander Graf * (at your option) any later version. 8f16408dfSAlexander Graf * 9f16408dfSAlexander Graf * This program is distributed in the hope that it will be useful, 10f16408dfSAlexander Graf * but WITHOUT ANY WARRANTY; without even the implied warranty of 11f16408dfSAlexander Graf * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12f16408dfSAlexander Graf * GNU General Public License for more details. 13f16408dfSAlexander Graf * 14f16408dfSAlexander Graf * You should have received a copy of the GNU General Public License 158167ee88SBlue Swirl * along with this program; if not, see <http://www.gnu.org/licenses/>. 16f16408dfSAlexander Graf * 17f16408dfSAlexander Graf * Copyright Novell Inc, 2009 18f16408dfSAlexander Graf * Authors: Alexander Graf <agraf@suse.de> 19f16408dfSAlexander Graf */ 20f16408dfSAlexander Graf 21dd4b2659SAlexander Graf#include "optionrom.h" 22f16408dfSAlexander Graf 2375b9f690SGleb Natapov#define BOOT_ROM_PRODUCT "multiboot loader" 2475b9f690SGleb Natapov 25f16408dfSAlexander Graf#define MULTIBOOT_MAGIC 0x2badb002 26f16408dfSAlexander Graf 2777873196SAlexander Graf#define GS_PROT_JUMP 0 2877873196SAlexander Graf#define GS_GDT_DESC 6 2977873196SAlexander Graf 3077873196SAlexander Graf 31dd4b2659SAlexander GrafBOOT_ROM_START 32f16408dfSAlexander Graf 33f16408dfSAlexander Grafrun_multiboot: 34f16408dfSAlexander Graf 35f16408dfSAlexander Graf cli 36f16408dfSAlexander Graf cld 37f16408dfSAlexander Graf 38f16408dfSAlexander Graf mov %cs, %eax 39f16408dfSAlexander Graf shl $0x4, %eax 40f16408dfSAlexander Graf 4177873196SAlexander Graf /* set up a long jump descriptor that is PC relative */ 42f16408dfSAlexander Graf 4377873196SAlexander Graf /* move stack memory to %gs */ 4477873196SAlexander Graf mov %ss, %ecx 4577873196SAlexander Graf shl $0x4, %ecx 4677873196SAlexander Graf mov %esp, %ebx 4777873196SAlexander Graf add %ebx, %ecx 4877873196SAlexander Graf sub $0x20, %ecx 4977873196SAlexander Graf sub $0x30, %esp 5077873196SAlexander Graf shr $0x4, %ecx 5177873196SAlexander Graf mov %cx, %gs 5277873196SAlexander Graf 53*e7d81004SStefan Weil /* now push the indirect jump descriptor there */ 54f16408dfSAlexander Graf mov (prot_jump), %ebx 55f16408dfSAlexander Graf add %eax, %ebx 5677873196SAlexander Graf movl %ebx, %gs:GS_PROT_JUMP 5777873196SAlexander Graf mov $8, %bx 5877873196SAlexander Graf movw %bx, %gs:GS_PROT_JUMP + 4 5977873196SAlexander Graf 6077873196SAlexander Graf /* fix the gdt descriptor to be PC relative */ 6177873196SAlexander Graf movw (gdt_desc), %bx 6277873196SAlexander Graf movw %bx, %gs:GS_GDT_DESC 6377873196SAlexander Graf movl (gdt_desc+2), %ebx 6477873196SAlexander Graf add %eax, %ebx 6577873196SAlexander Graf movl %ebx, %gs:GS_GDT_DESC + 2 6677873196SAlexander Graf 6753ea95deSAdam Lackorzynski xor %eax, %eax 6853ea95deSAdam Lackorzynski mov %eax, %es 6953ea95deSAdam Lackorzynski 7077873196SAlexander Graf /* Read the bootinfo struct into RAM */ 7177873196SAlexander Graf read_fw_blob(FW_CFG_INITRD) 72f16408dfSAlexander Graf 73f16408dfSAlexander Graf /* FS = bootinfo_struct */ 74f16408dfSAlexander Graf read_fw FW_CFG_INITRD_ADDR 75f16408dfSAlexander Graf shr $4, %eax 76f16408dfSAlexander Graf mov %ax, %fs 77f16408dfSAlexander Graf 78f16408dfSAlexander Graf /* ES = mmap_addr */ 7953ea95deSAdam Lackorzynski mov %fs:48, %eax 80f16408dfSAlexander Graf shr $4, %eax 81f16408dfSAlexander Graf mov %ax, %es 82f16408dfSAlexander Graf 83f16408dfSAlexander Graf /* Initialize multiboot mmap structs using int 0x15(e820) */ 84f16408dfSAlexander Graf xor %ebx, %ebx 85f16408dfSAlexander Graf /* mmap start after first size */ 86f16408dfSAlexander Graf movl $4, %edi 87f16408dfSAlexander Graf 88f16408dfSAlexander Grafmmap_loop: 89f16408dfSAlexander Graf /* entry size (mmap struct) & max buffer size (int15) */ 90f16408dfSAlexander Graf movl $20, %ecx 91f16408dfSAlexander Graf /* store entry size */ 92ff56954bSJuergen Lock /* old as(1) doesn't like this insn so emit the bytes instead: 93f16408dfSAlexander Graf movl %ecx, %es:-4(%edi) 94ff56954bSJuergen Lock */ 95ff56954bSJuergen Lock .dc.b 0x26,0x67,0x66,0x89,0x4f,0xfc 96f16408dfSAlexander Graf /* e820 */ 97f16408dfSAlexander Graf movl $0x0000e820, %eax 98f16408dfSAlexander Graf /* 'SMAP' magic */ 99f16408dfSAlexander Graf movl $0x534d4150, %edx 100f16408dfSAlexander Graf int $0x15 101f16408dfSAlexander Graf 102f16408dfSAlexander Grafmmap_check_entry: 103f16408dfSAlexander Graf /* last entry? then we're done */ 104f16408dfSAlexander Graf jb mmap_done 105f16408dfSAlexander Graf and %bx, %bx 106f16408dfSAlexander Graf jz mmap_done 107f16408dfSAlexander Graf /* valid entry, so let's loop on */ 108f16408dfSAlexander Graf 109f16408dfSAlexander Grafmmap_store_entry: 110f16408dfSAlexander Graf /* %ax = entry_number * 24 */ 111f16408dfSAlexander Graf mov $24, %ax 112f16408dfSAlexander Graf mul %bx 113f16408dfSAlexander Graf mov %ax, %di 114f16408dfSAlexander Graf movw %di, %fs:0x2c 115f16408dfSAlexander Graf /* %di = 4 + (entry_number * 24) */ 116f16408dfSAlexander Graf add $4, %di 117f16408dfSAlexander Graf jmp mmap_loop 118f16408dfSAlexander Graf 119f16408dfSAlexander Grafmmap_done: 120f16408dfSAlexander Grafreal_to_prot: 121f16408dfSAlexander Graf /* Load the GDT before going into protected mode */ 122f16408dfSAlexander Graflgdt: 12377873196SAlexander Graf data32 lgdt %gs:GS_GDT_DESC 124f16408dfSAlexander Graf 125f16408dfSAlexander Graf /* get us to protected mode now */ 126f16408dfSAlexander Graf movl $1, %eax 127f16408dfSAlexander Graf movl %eax, %cr0 128f16408dfSAlexander Graf 129f16408dfSAlexander Graf /* the LJMP sets CS for us and gets us to 32-bit */ 130f16408dfSAlexander Grafljmp: 13177873196SAlexander Graf data32 ljmp *%gs:GS_PROT_JUMP 132f16408dfSAlexander Graf 133f16408dfSAlexander Grafprot_mode: 134f16408dfSAlexander Graf.code32 135f16408dfSAlexander Graf 136f16408dfSAlexander Graf /* initialize all other segments */ 137f16408dfSAlexander Graf movl $0x10, %eax 138f16408dfSAlexander Graf movl %eax, %ss 139f16408dfSAlexander Graf movl %eax, %ds 140f16408dfSAlexander Graf movl %eax, %es 141f16408dfSAlexander Graf movl %eax, %fs 142f16408dfSAlexander Graf movl %eax, %gs 143f16408dfSAlexander Graf 14477873196SAlexander Graf /* Read the kernel and modules into RAM */ 14577873196SAlexander Graf read_fw_blob(FW_CFG_KERNEL) 14677873196SAlexander Graf 147f16408dfSAlexander Graf /* Jump off to the kernel */ 14877873196SAlexander Graf read_fw FW_CFG_KERNEL_ENTRY 149f16408dfSAlexander Graf mov %eax, %ecx 150f16408dfSAlexander Graf 151f16408dfSAlexander Graf /* EBX contains a pointer to the bootinfo struct */ 152f16408dfSAlexander Graf read_fw FW_CFG_INITRD_ADDR 153f16408dfSAlexander Graf movl %eax, %ebx 154f16408dfSAlexander Graf 155f16408dfSAlexander Graf /* EAX has to contain the magic */ 156f16408dfSAlexander Graf movl $MULTIBOOT_MAGIC, %eax 157f16408dfSAlexander Grafljmp2: 158f16408dfSAlexander Graf jmp *%ecx 159f16408dfSAlexander Graf 160f16408dfSAlexander Graf/* Variables */ 161f16408dfSAlexander Graf.align 4, 0 162f16408dfSAlexander Grafprot_jump: .long prot_mode 163f16408dfSAlexander Graf .short 8 164f16408dfSAlexander Graf 165f16408dfSAlexander Graf.align 4, 0 166f16408dfSAlexander Grafgdt: 167f16408dfSAlexander Graf /* 0x00 */ 168f16408dfSAlexander Graf.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 169f16408dfSAlexander Graf 170f16408dfSAlexander Graf /* 0x08: code segment (base=0, limit=0xfffff, type=32bit code exec/read, DPL=0, 4k) */ 171f16408dfSAlexander Graf.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00 172f16408dfSAlexander Graf 173f16408dfSAlexander Graf /* 0x10: data segment (base=0, limit=0xfffff, type=32bit data read/write, DPL=0, 4k) */ 174f16408dfSAlexander Graf.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00 175f16408dfSAlexander Graf 176f16408dfSAlexander Graf /* 0x18: code segment (base=0, limit=0x0ffff, type=16bit code exec/read/conf, DPL=0, 1b) */ 177f16408dfSAlexander Graf.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00 178f16408dfSAlexander Graf 179f16408dfSAlexander Graf /* 0x20: data segment (base=0, limit=0x0ffff, type=16bit data read/write, DPL=0, 1b) */ 180f16408dfSAlexander Graf.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00 181f16408dfSAlexander Graf 182f16408dfSAlexander Grafgdt_desc: 183f16408dfSAlexander Graf.short (5 * 8) - 1 184f16408dfSAlexander Graf.long gdt 185f16408dfSAlexander Graf 186dd4b2659SAlexander GrafBOOT_ROM_END 187