blob: 65819e948b2d377ede938b15595d9e7e8aade902 [file] [log] [blame]
Stefan Reinauer0316e1a2015-11-20 17:58:59 +01001/*
2 * linux_trampoline
3 *
4 * Copyright (C) 2013 Patrick Georgi <patrick@georgi-clan.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16/* NOTE: THIS CODE MUST REMAIN POSITION INDEPENDENT
17 * IT SHOULDN'T USE THE STACK
18 * AND IN GENERAL EXPECT NOTHING BUT RAM TO WORK
19 */
20.code32
21.data
22
23#include "linux_trampoline.h"
24#define HEADER_SIG 0x4f49424c // LBIO little endian
25#define CB_TAG_FORWARD 0x11
26#define CB_TAG_MEMORY 0x1
27#define CB_TAG_FRAMEBUFFER 0x12
28
29#define E820_NR_OFFSET 0x1e8
30#define LINUX_ENTRY_OFFSET 0x214
31#define E820_OFFSET 0x2d0
32
33.trampoline_start:
34
35cld
36xor %edx, %edx
37mov $0, %ecx
38
39.headerSearch:
40mov $0x10000, %ebx
41add %ecx, %ebx
42mov (%ecx), %eax
43cmp $HEADER_SIG, %eax
44je .headerSearchDone // found the header
45add $16, %ecx
46cmp %ecx, %ebx
47jne .headerSearch
48
49.headerSearchDone:
50cmp %ecx, %ebx // reached the end == not found anything?
51je 2f // give up
52
53// we assume the checksum is okay, no test
54mov 4(%ecx), %ebx
55add %ecx, %ebx // ebx = cb_header + header_bytes
56mov 20(%ecx), %ecx // ecx = table_entries
57
58.tableScan:
59cmp $CB_TAG_FORWARD, (%ebx)
60jne .testMemory
61
62/* forward tag: assume 32bit pointer */
63mov 8(%ebx), %ecx
64jmp .headerSearch
65
66.testMemory:
67cmp $CB_TAG_MEMORY, (%ebx)
68jne .testFramebuffer
69
70/* memory tag: copy e820 map and entry count. also determine alt_mem_k */
71mov 4(%ebx), %eax
72sub $8, %eax
73shr $2, %eax /* eax = number of dwords of e820 data */
74cmp $(32 * 5), %eax /* linux wants at most 32 entries of 5 dwords */
75jng 1f
76mov $(32 * 5), %eax /* only copy 32 entries */
771:
78mov %eax, %esi
79mov $5, %edi
80div %edi
81mov %eax, (LINUX_PARAM_LOC + E820_NR_OFFSET)
82mov %esi, %eax
83xchg %eax, %ecx
84lea 8(%ebx), %esi /* e820 data source */
85mov $(LINUX_PARAM_LOC + E820_OFFSET), %edi
86rep movsl
87xchg %eax, %ecx
88jmp .endScan
89
90.testFramebuffer:
91cmp $CB_TAG_FRAMEBUFFER, (%ebx)
92jne .endScan
93/* TODO: handle framebuffer tag */
94
95.endScan:
96add 4(%ebx), %ebx
97dec %ecx
98jnz .tableScan
99
100/* Setup basic code and data segment selectors for Linux
101**
102** Flat code segment descriptor:
103** selector: 0x10
104** base : 0x00000000
105** limit : 0xFFFFFFFF
106** type : code, execute, read
107**
108** Flat data segment descriptor:
109** selector: 0x18
110** base : 0x00000000
111** limit : 0xFFFFFFFF
112** type : data, read/write
113**
114** Use TRAMPOLINE_ENTRY_LOC as a scratchpad.
115*/
116mov $TRAMPOLINE_ENTRY_LOC, %eax
117sgdt (%eax)
118mov 2(%eax), %ebx
119movl $0x0000ffff, 16(%ebx)
120movl $0x00cf9b00, 20(%ebx)
121movl $0x0000ffff, 24(%ebx)
122movl $0x00cf9300, 28(%ebx)
123
124/* finally: jump to kernel */
125mov $LINUX_PARAM_LOC, %esi
126jmp *(LINUX_PARAM_LOC + LINUX_ENTRY_OFFSET)
127
128
1292:
130hlt
131jmp 2b
132
133.trampoline_end: