2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * High memory temporary load address
23 * Temporary buffer into which to copy (or decompress) our runtime
24 * image, prior to calling get_memmap() and relocate(). We don't
25 * actually leave anything here once install() has returned.
27 * We use the start of an even megabyte so that we don't have to worry
28 * about the current state of the A20 line.
30 * We use 4MB rather than 2MB because there is at least one commercial
31 * PXE ROM ("Broadcom UNDI, PXE-2.1 (build 082) v2.0.4") which stores
32 * data required by the UNDI ROM loader (yes, the ROM loader; that's
33 * the component which should be impossible to damage short of
34 * screwing with the MMU) around the 2MB mark. Sadly, this is not a
38 #define HIGHMEM_LOADPOINT ( 4 << 20 )
40 /* Image compression enabled */
46 .section ".prefix.lib", "awx", @progbits
47 .section ".data16", "aw", @progbits
49 /****************************************************************************
50 * install_block (real-mode near call)
52 * Install block to specified address
55 * %esi : start offset within loaded image (must be a multiple of 16)
56 * %es:edi : destination address
57 * %ecx : length of (decompressed) data
58 * %edx : total length of block (including any uninitialised data portion)
60 * %esi : end offset within image (rounded up to next multiple of 16)
63 ****************************************************************************
65 .section ".prefix.lib"
68 /* Preserve registers */
74 /* Starting segment => %ds */
81 /* Calculate start and length of uninitialised data portion */
82 addr32 leal (%edi,%ecx), %eax
93 /* Zero remaining space */
104 /* Restore registers */
109 .size install_block, . - install_block
111 /****************************************************************************
112 * alloc_basemem (real-mode near call)
114 * Allocate space for .text16 and .data16 from top of base memory.
115 * Memory is allocated using the BIOS free base memory counter at
121 * %ax : .text16 segment address
122 * %bx : .data16 segment address
125 ****************************************************************************
127 .section ".prefix.lib"
130 /* FBMS => %ax as segment address */
136 /* .data16 segment address */
137 subw $_data16_size_pgh, %ax
140 /* .text16 segment address */
141 subw $_text16_size_pgh, %ax
152 .size alloc_basemem, . - alloc_basemem
154 /****************************************************************************
155 * install_basemem (real-mode near call)
157 * Install .text16 and .data16 into base memory
160 * %ax : .text16 segment address
161 * %bx : .data16 segment address
162 * %esi : start offset within loaded image (must be a multiple of 16)
164 * %esi : end offset within image (rounded up to next multiple of 16)
167 ****************************************************************************
169 .section ".prefix.lib"
172 /* Preserve registers */
178 /* Install .text16 */
181 movl $_text16_size, %ecx
185 /* Install .data16 */
188 movl $_data16_progbits_size, %ecx
189 movl $_data16_size, %edx
192 /* Restore registers */
198 .size install_basemem, . - install_basemem
200 /****************************************************************************
201 * install_highmem (flat real-mode near call)
203 * Install .text and .data into high memory
206 * %esi : start offset within loaded image (must be a multiple of 16)
207 * %es:edi : address in high memory
209 * %esi : end offset within image (rounded up to next multiple of 16)
212 ****************************************************************************
217 .section ".prefix.lib"
220 /* Preserve registers */
225 /* Install .text and .data to specified address */
226 movl $_textdata_progbits_size, %ecx
227 movl $_textdata_size, %edx
230 /* Restore registers and interrupt status */
235 .size install_highmem, . - install_highmem
237 #endif /* KEEP_IT_REAL */
239 /****************************************************************************
240 * GDT for flat real mode
242 * We only ever use this GDT to set segment limits; the bases are
243 * unused. Also, we only change data segments, so we don't need to
244 * worry about the code or stack segments. This makes everything much
246 ****************************************************************************
251 .section ".prefix.lib"
254 gdt_limit: .word gdt_length - 1
256 .word 0 /* padding */
258 flat_ds: /* Flat real mode data segment */
259 .equ FLAT_DS, flat_ds - gdt
261 .byte 0, 0x93, 0xcf, 0
263 real_ds: /* Normal real mode data segment */
264 .equ REAL_DS, real_ds - gdt
266 .byte 0, 0x93, 0x00, 0
269 .equ gdt_length, gdt_end - gdt
272 #endif /* KEEP_IT_REAL */
274 /****************************************************************************
275 * set_real_mode_limits (real-mode near call)
277 * Sets limits on the data segments %ds and %es.
280 * %cx : segment type (FLAT_DS for 4GB or REAL_DS for 64kB)
281 ****************************************************************************
286 .section ".prefix.lib"
288 set_real_mode_limits:
289 /* Preserve real-mode segment values and temporary registers */
295 /* Set GDT base and load GDT */
306 /* Switch to protected mode */
311 /* Set flat segment limits */
315 /* Switch back to real mode */
320 /* Restore real-mode segment values and temporary registers */
326 .size set_real_mode_limits, . - set_real_mode_limits
328 #endif /* KEEP_IT_REAL */
330 /****************************************************************************
331 * install (real-mode near call)
332 * install_prealloc (real-mode near call)
334 * Install all text and data segments.
337 * %ax : .text16 segment address (install_prealloc only)
338 * %bx : .data16 segment address (install_prealloc only)
340 * %ax : .text16 segment address
341 * %bx : .data16 segment address
342 * %edi : .text physical address (if applicable)
345 ****************************************************************************
347 .section ".prefix.lib"
351 /* Allocate space for .text16 and .data16 */
353 .size install, . - install
354 .globl install_prealloc
358 /* Install .text16 and .data16 */
359 movl $_payload_offset, %esi
363 /* Preserve %ds, call init_libkir, restore registers */
366 movw %ax, (init_libkir_vector+2)
367 lcall *init_libkir_vector
370 /* Preserve registers and interrupt status, and disable interrupts */
377 /* Load up %ds and %es, and set up vectors for far calls to .text16 */
381 movw %ax, (init_librm_vector+2)
382 movw %ax, (prot_call_vector+2)
384 /* Install .text and .data to temporary area in high memory,
385 * prior to reading the E820 memory map and relocating
389 call set_real_mode_limits
390 movl $HIGHMEM_LOADPOINT, %edi
393 /* Set up initial protected-mode GDT, call relocate().
394 * relocate() will return with %esi, %edi and %ecx set up
395 * ready for the copy to the new location.
397 lcall *init_librm_vector
399 lcall *prot_call_vector
402 /* Move code to new location, set up new protected-mode GDT */
404 call set_real_mode_limits
408 lcall *init_librm_vector
410 /* Restore real-mode segment limits */
412 call set_real_mode_limits
414 /* Restore registers and interrupt status */
422 .size install_prealloc, . - install_prealloc
424 /* Vectors for far calls to .text16 functions */
430 .size init_libkir_vector, . - init_libkir_vector
435 .size init_librm_vector, . - init_librm_vector
439 .size prot_call_vector, . - prot_call_vector