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.
23 .section ".prefix.lib", "awx", @progbits
24 .section ".data16", "aw", @progbits
26 /****************************************************************************
27 * install_block (real-mode near call)
29 * Install block to specified address
32 * %esi : byte offset within loaded image (must be a multiple of 16)
33 * %es:edi : destination address
34 * %ecx : length of (decompressed) data
35 * %edx : total length of block (including any uninitialised data portion)
39 * %esi, %edi, %ecx, %edx
40 ****************************************************************************
42 .section ".prefix.lib"
45 /* Preserve registers */
49 /* Starting segment => %ds */
56 /* Calculate start and length of uninitialised data portion */
57 addr32 leal (%edi,%ecx), %eax
62 rep addr32 movsb /* or "call decompress16" */
64 /* Zero remaining space */
70 /* Restore registers */
74 .size install_block, . - install_block
76 /****************************************************************************
77 * alloc_basemem (real-mode near call)
79 * Allocate space for .text16 and .data16 from top of base memory.
80 * Memory is allocated using the BIOS free base memory counter at
86 * %ax : .text16 segment address
87 * %bx : .data16 segment address
90 ****************************************************************************
92 .section ".prefix.lib"
95 /* FBMS => %ax as segment address */
101 /* .data16 segment address */
102 subw $_data16_size_pgh, %ax
105 /* .text16 segment address */
106 subw $_text16_size_pgh, %ax
117 .size alloc_basemem, . - alloc_basemem
119 /****************************************************************************
120 * install_basemem (real-mode near call)
122 * Install .text16 and .data16 into base memory
125 * %ax : .text16 segment address
126 * %bx : .data16 segment address
131 ****************************************************************************
133 .section ".prefix.lib"
136 /* Preserve registers */
143 /* Install .text16 */
146 movl $_text16_load_offset, %esi
147 movl $_text16_size, %ecx
151 /* Install .data16 */
154 movl $_data16_load_offset, %esi
155 movl $_data16_progbits_size, %ecx
156 movl $_data16_size, %edx
159 /* Restore registers */
166 .size install_basemem, . - install_basemem
168 /****************************************************************************
169 * install_highmem (flat real-mode near call)
171 * Install .text and .data into high memory
174 * %es:edi : address in high memory
179 ****************************************************************************
184 .section ".prefix.lib"
187 /* Preserve registers */
193 /* Install .text and .data to specified address */
194 movl $_textdata_load_offset, %esi
195 movl $_textdata_progbits_size, %ecx
196 movl $_textdata_size, %edx
199 /* Restore registers and interrupt status */
205 .size install_highmem, . - install_highmem
207 #endif /* KEEP_IT_REAL */
209 /****************************************************************************
210 * GDT for flat real mode
212 * We only ever use this GDT to set segment limits; the bases are
213 * unused. Also, we only flatten data segments, so we don't need to
214 * worry about the code or stack segments. This makes everything much
216 ****************************************************************************
221 .section ".prefix.lib"
224 gdt_limit: .word gdt_length - 1
226 .word 0 /* padding */
228 flat_ds: /* Flat real mode data segment */
229 .equ FLAT_DS, flat_ds - gdt
231 .byte 0, 0x93, 0xcf, 0
234 .equ gdt_length, gdt_end - gdt
237 #endif /* KEEP_IT_REAL */
239 /****************************************************************************
240 * flatten_real_mode (real-mode near call)
242 * Sets 4GB limits on the data segments %ds and %es.
246 ****************************************************************************
251 .section ".prefix.lib"
254 /* Preserve real-mode segment values and temporary registers */
260 /* Set GDT base and load GDT */
271 /* Switch to protected mode */
276 /* Set flat segment limits */
281 /* Switch back to real mode */
286 /* Restore real-mode segment values and temporary registers */
292 .size flatten_real_mode, . - flatten_real_mode
294 #endif /* KEEP_IT_REAL */
296 /****************************************************************************
297 * install (real-mode near call)
298 * install_prealloc (real-mode near call)
300 * Install all text and data segments.
303 * %ax : .text16 segment address (install_prealloc only)
304 * %bx : .data16 segment address (install_prealloc only)
306 * %ax : .text16 segment address
307 * %bx : .data16 segment address
308 * %edi : .text physical address (if applicable)
311 ****************************************************************************
313 .section ".prefix.lib"
317 /* Allocate space for .text16 and .data16 */
319 .size install, . - install
320 .globl install_prealloc
322 /* Install .text16 and .data16 */
326 /* Preserve %ds, call init_libkir, restore registers */
329 movw %ax, (init_libkir_vector+2)
330 lcall *init_libkir_vector
333 /* Preserve registers and interrupt status, and disable interrupts */
341 /* Load up %ds and %es, and set up vectors for far calls to .text16 */
345 movw %ax, (init_librm_vector+2)
346 movw %ax, (prot_call_vector+2)
348 /* Install .text and .data to 2MB mark. Use 2MB to avoid
351 call flatten_real_mode
355 /* Set up initial protected-mode GDT, call relocate().
356 * relocate() will return with %esi, %edi and %ecx set up
357 * ready for the copy to the new location.
359 lcall *init_librm_vector
361 lcall *prot_call_vector
364 /* Move code to new location, set up new protected-mode GDT */
365 call flatten_real_mode
369 lcall *init_librm_vector
371 /* Hide Etherboot from BIOS memory map. Note that making this
372 * protected-mode call will also restore normal (non-flat)
373 * real mode, as part of the protected-to-real transition.
375 pushl $hide_etherboot
376 lcall *prot_call_vector
379 /* Restore registers and interrupt status */
387 .size install_prealloc, . - install_prealloc
389 /* Vectors for far calls to .text16 functions */
395 .size init_libkir_vector, . - init_libkir_vector
400 .size init_librm_vector, . - init_librm_vector
404 .size prot_call_vector, . - prot_call_vector