1 | /* |
---|
2 | * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. |
---|
3 | * |
---|
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. |
---|
8 | * |
---|
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. |
---|
13 | * |
---|
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. |
---|
17 | * |
---|
18 | */ |
---|
19 | |
---|
20 | FILE_LICENCE ( GPL2_OR_LATER ) |
---|
21 | |
---|
22 | .arch i386 |
---|
23 | |
---|
24 | /** |
---|
25 | * High memory temporary load address |
---|
26 | * |
---|
27 | * Temporary buffer into which to copy (or decompress) our runtime |
---|
28 | * image, prior to calling get_memmap() and relocate(). We don't |
---|
29 | * actually leave anything here once install() has returned. |
---|
30 | * |
---|
31 | * We use the start of an even megabyte so that we don't have to worry |
---|
32 | * about the current state of the A20 line. |
---|
33 | * |
---|
34 | * We use 4MB rather than 2MB because some PXE stack / PMM BIOS |
---|
35 | * combinations are known to place data required by other UNDI ROMs |
---|
36 | * loader around the 2MB mark. |
---|
37 | */ |
---|
38 | .globl HIGHMEM_LOADPOINT |
---|
39 | .equ HIGHMEM_LOADPOINT, ( 4 << 20 ) |
---|
40 | |
---|
41 | /* Image compression enabled */ |
---|
42 | #define COMPRESS 1 |
---|
43 | |
---|
44 | #define CR0_PE 1 |
---|
45 | |
---|
46 | /***************************************************************************** |
---|
47 | * Utility function: print character (with LF -> LF,CR translation) |
---|
48 | * |
---|
49 | * Parameters: |
---|
50 | * %al : character to print |
---|
51 | * %ds:di : output buffer (or %di=0 to print to console) |
---|
52 | * Returns: |
---|
53 | * %ds:di : next character in output buffer (if applicable) |
---|
54 | ***************************************************************************** |
---|
55 | */ |
---|
56 | .section ".prefix.lib", "awx", @progbits |
---|
57 | .code16 |
---|
58 | .globl print_character |
---|
59 | print_character: |
---|
60 | /* Preserve registers */ |
---|
61 | pushw %ax |
---|
62 | pushw %bx |
---|
63 | pushw %bp |
---|
64 | /* If %di is non-zero, write character to buffer and exit */ |
---|
65 | testw %di, %di |
---|
66 | jz 1f |
---|
67 | movb %al, %ds:(%di) |
---|
68 | incw %di |
---|
69 | jmp 3f |
---|
70 | 1: /* Print character */ |
---|
71 | movw $0x0007, %bx /* page 0, attribute 7 (normal) */ |
---|
72 | movb $0x0e, %ah /* write char, tty mode */ |
---|
73 | cmpb $0x0a, %al /* '\n'? */ |
---|
74 | jne 2f |
---|
75 | int $0x10 |
---|
76 | movb $0x0d, %al |
---|
77 | 2: int $0x10 |
---|
78 | /* Restore registers and return */ |
---|
79 | 3: popw %bp |
---|
80 | popw %bx |
---|
81 | popw %ax |
---|
82 | ret |
---|
83 | .size print_character, . - print_character |
---|
84 | |
---|
85 | /***************************************************************************** |
---|
86 | * Utility function: print a NUL-terminated string |
---|
87 | * |
---|
88 | * Parameters: |
---|
89 | * %ds:si : string to print |
---|
90 | * %ds:di : output buffer (or %di=0 to print to console) |
---|
91 | * Returns: |
---|
92 | * %ds:si : character after terminating NUL |
---|
93 | * %ds:di : next character in output buffer (if applicable) |
---|
94 | ***************************************************************************** |
---|
95 | */ |
---|
96 | .section ".prefix.lib", "awx", @progbits |
---|
97 | .code16 |
---|
98 | .globl print_message |
---|
99 | print_message: |
---|
100 | /* Preserve registers */ |
---|
101 | pushw %ax |
---|
102 | /* Print string */ |
---|
103 | 1: lodsb |
---|
104 | testb %al, %al |
---|
105 | je 2f |
---|
106 | call print_character |
---|
107 | jmp 1b |
---|
108 | 2: /* Restore registers and return */ |
---|
109 | popw %ax |
---|
110 | ret |
---|
111 | .size print_message, . - print_message |
---|
112 | |
---|
113 | /***************************************************************************** |
---|
114 | * Utility functions: print hex digit/byte/word/dword |
---|
115 | * |
---|
116 | * Parameters: |
---|
117 | * %al (low nibble) : digit to print |
---|
118 | * %al : byte to print |
---|
119 | * %ax : word to print |
---|
120 | * %eax : dword to print |
---|
121 | * %ds:di : output buffer (or %di=0 to print to console) |
---|
122 | * Returns: |
---|
123 | * %ds:di : next character in output buffer (if applicable) |
---|
124 | ***************************************************************************** |
---|
125 | */ |
---|
126 | .section ".prefix.lib", "awx", @progbits |
---|
127 | .code16 |
---|
128 | .globl print_hex_dword |
---|
129 | print_hex_dword: |
---|
130 | rorl $16, %eax |
---|
131 | call print_hex_word |
---|
132 | rorl $16, %eax |
---|
133 | /* Fall through */ |
---|
134 | .size print_hex_dword, . - print_hex_dword |
---|
135 | .globl print_hex_word |
---|
136 | print_hex_word: |
---|
137 | xchgb %al, %ah |
---|
138 | call print_hex_byte |
---|
139 | xchgb %al, %ah |
---|
140 | /* Fall through */ |
---|
141 | .size print_hex_word, . - print_hex_word |
---|
142 | .globl print_hex_byte |
---|
143 | print_hex_byte: |
---|
144 | rorb $4, %al |
---|
145 | call print_hex_nibble |
---|
146 | rorb $4, %al |
---|
147 | /* Fall through */ |
---|
148 | .size print_hex_byte, . - print_hex_byte |
---|
149 | .globl print_hex_nibble |
---|
150 | print_hex_nibble: |
---|
151 | /* Preserve registers */ |
---|
152 | pushw %ax |
---|
153 | /* Print digit (technique by Norbert Juffa <norbert.juffa@amd.com> */ |
---|
154 | andb $0x0f, %al |
---|
155 | cmpb $10, %al |
---|
156 | sbbb $0x69, %al |
---|
157 | das |
---|
158 | call print_character |
---|
159 | /* Restore registers and return */ |
---|
160 | popw %ax |
---|
161 | ret |
---|
162 | .size print_hex_nibble, . - print_hex_nibble |
---|
163 | |
---|
164 | /***************************************************************************** |
---|
165 | * Utility function: print PCI bus:dev.fn |
---|
166 | * |
---|
167 | * Parameters: |
---|
168 | * %ax : PCI bus:dev.fn to print |
---|
169 | * %ds:di : output buffer (or %di=0 to print to console) |
---|
170 | * Returns: |
---|
171 | * %ds:di : next character in output buffer (if applicable) |
---|
172 | ***************************************************************************** |
---|
173 | */ |
---|
174 | .section ".prefix.lib", "awx", @progbits |
---|
175 | .code16 |
---|
176 | .globl print_pci_busdevfn |
---|
177 | print_pci_busdevfn: |
---|
178 | /* Preserve registers */ |
---|
179 | pushw %ax |
---|
180 | /* Print bus */ |
---|
181 | xchgb %al, %ah |
---|
182 | call print_hex_byte |
---|
183 | /* Print ":" */ |
---|
184 | movb $( ':' ), %al |
---|
185 | call print_character |
---|
186 | /* Print device */ |
---|
187 | movb %ah, %al |
---|
188 | shrb $3, %al |
---|
189 | call print_hex_byte |
---|
190 | /* Print "." */ |
---|
191 | movb $( '.' ), %al |
---|
192 | call print_character |
---|
193 | /* Print function */ |
---|
194 | movb %ah, %al |
---|
195 | andb $0x07, %al |
---|
196 | call print_hex_nibble |
---|
197 | /* Restore registers and return */ |
---|
198 | popw %ax |
---|
199 | ret |
---|
200 | .size print_pci_busdevfn, . - print_pci_busdevfn |
---|
201 | |
---|
202 | /***************************************************************************** |
---|
203 | * Utility function: clear current line |
---|
204 | * |
---|
205 | * Parameters: |
---|
206 | * %ds:di : output buffer (or %di=0 to print to console) |
---|
207 | * Returns: |
---|
208 | * %ds:di : next character in output buffer (if applicable) |
---|
209 | ***************************************************************************** |
---|
210 | */ |
---|
211 | .section ".prefix.lib", "awx", @progbits |
---|
212 | .code16 |
---|
213 | .globl print_kill_line |
---|
214 | print_kill_line: |
---|
215 | /* Preserve registers */ |
---|
216 | pushw %ax |
---|
217 | pushw %cx |
---|
218 | /* Print CR */ |
---|
219 | movb $( '\r' ), %al |
---|
220 | call print_character |
---|
221 | /* Print 79 spaces */ |
---|
222 | movb $( ' ' ), %al |
---|
223 | movw $79, %cx |
---|
224 | 1: call print_character |
---|
225 | loop 1b |
---|
226 | /* Print CR */ |
---|
227 | movb $( '\r' ), %al |
---|
228 | call print_character |
---|
229 | /* Restore registers and return */ |
---|
230 | popw %cx |
---|
231 | popw %ax |
---|
232 | ret |
---|
233 | .size print_kill_line, . - print_kill_line |
---|
234 | |
---|
235 | /**************************************************************************** |
---|
236 | * pm_call (real-mode near call) |
---|
237 | * |
---|
238 | * Call routine in 16-bit protected mode for access to extended memory |
---|
239 | * |
---|
240 | * Parameters: |
---|
241 | * %ax : address of routine to call in 16-bit protected mode |
---|
242 | * Returns: |
---|
243 | * none |
---|
244 | * Corrupts: |
---|
245 | * %ax |
---|
246 | * |
---|
247 | * The specified routine is called in 16-bit protected mode, with: |
---|
248 | * |
---|
249 | * %cs : 16-bit code segment with base matching real-mode %cs |
---|
250 | * %ss : 16-bit data segment with base matching real-mode %ss |
---|
251 | * %ds,%es,%fs,%gs : 32-bit data segment with zero base and 4GB limit |
---|
252 | * |
---|
253 | **************************************************************************** |
---|
254 | */ |
---|
255 | |
---|
256 | #ifndef KEEP_IT_REAL |
---|
257 | |
---|
258 | /* GDT for protected-mode calls */ |
---|
259 | .section ".prefix.lib", "awx", @progbits |
---|
260 | .align 16 |
---|
261 | pm_call_vars: |
---|
262 | gdt: |
---|
263 | gdt_limit: .word gdt_length - 1 |
---|
264 | gdt_base: .long 0 |
---|
265 | .word 0 /* padding */ |
---|
266 | pm_cs: /* 16-bit protected-mode code segment */ |
---|
267 | .equ PM_CS, pm_cs - gdt |
---|
268 | .word 0xffff, 0 |
---|
269 | .byte 0, 0x9b, 0x00, 0 |
---|
270 | pm_ss: /* 16-bit protected-mode stack segment */ |
---|
271 | .equ PM_SS, pm_ss - gdt |
---|
272 | .word 0xffff, 0 |
---|
273 | .byte 0, 0x93, 0x00, 0 |
---|
274 | pm_ds: /* 32-bit protected-mode flat data segment */ |
---|
275 | .equ PM_DS, pm_ds - gdt |
---|
276 | .word 0xffff, 0 |
---|
277 | .byte 0, 0x93, 0xcf, 0 |
---|
278 | gdt_end: |
---|
279 | .equ gdt_length, . - gdt |
---|
280 | .size gdt, . - gdt |
---|
281 | |
---|
282 | .section ".prefix.lib", "awx", @progbits |
---|
283 | .align 16 |
---|
284 | pm_saved_gdt: |
---|
285 | .long 0, 0 |
---|
286 | .size pm_saved_gdt, . - pm_saved_gdt |
---|
287 | |
---|
288 | .equ pm_call_vars_size, . - pm_call_vars |
---|
289 | #define PM_CALL_VAR(x) ( -pm_call_vars_size + ( (x) - pm_call_vars ) ) |
---|
290 | |
---|
291 | .section ".prefix.lib", "awx", @progbits |
---|
292 | .code16 |
---|
293 | pm_call: |
---|
294 | /* Preserve registers, flags, and RM return point */ |
---|
295 | pushw %bp |
---|
296 | movw %sp, %bp |
---|
297 | subw $pm_call_vars_size, %sp |
---|
298 | andw $0xfff0, %sp |
---|
299 | pushfl |
---|
300 | pushw %gs |
---|
301 | pushw %fs |
---|
302 | pushw %es |
---|
303 | pushw %ds |
---|
304 | pushw %ss |
---|
305 | pushw %cs |
---|
306 | pushw $99f |
---|
307 | |
---|
308 | /* Set up local variable block, and preserve GDT */ |
---|
309 | pushw %cx |
---|
310 | pushw %si |
---|
311 | pushw %di |
---|
312 | pushw %ss |
---|
313 | popw %es |
---|
314 | movw $pm_call_vars, %si |
---|
315 | leaw PM_CALL_VAR(pm_call_vars)(%bp), %di |
---|
316 | movw $pm_call_vars_size, %cx |
---|
317 | cs rep movsb |
---|
318 | popw %di |
---|
319 | popw %si |
---|
320 | popw %cx |
---|
321 | sgdt PM_CALL_VAR(pm_saved_gdt)(%bp) |
---|
322 | |
---|
323 | /* Set up GDT bases */ |
---|
324 | pushl %eax |
---|
325 | pushl %edi |
---|
326 | xorl %eax, %eax |
---|
327 | movw %ss, %ax |
---|
328 | shll $4, %eax |
---|
329 | movzwl %bp, %edi |
---|
330 | addr32 leal PM_CALL_VAR(gdt)(%eax, %edi), %eax |
---|
331 | movl %eax, PM_CALL_VAR(gdt_base)(%bp) |
---|
332 | movw %cs, %ax |
---|
333 | movw $PM_CALL_VAR(pm_cs), %di |
---|
334 | call set_seg_base |
---|
335 | movw %ss, %ax |
---|
336 | movw $PM_CALL_VAR(pm_ss), %di |
---|
337 | call set_seg_base |
---|
338 | popl %edi |
---|
339 | popl %eax |
---|
340 | |
---|
341 | /* Switch CPU to protected mode and load up segment registers */ |
---|
342 | pushl %eax |
---|
343 | cli |
---|
344 | data32 lgdt PM_CALL_VAR(gdt)(%bp) |
---|
345 | movl %cr0, %eax |
---|
346 | orb $CR0_PE, %al |
---|
347 | movl %eax, %cr0 |
---|
348 | ljmp $PM_CS, $1f |
---|
349 | 1: movw $PM_SS, %ax |
---|
350 | movw %ax, %ss |
---|
351 | movw $PM_DS, %ax |
---|
352 | movw %ax, %ds |
---|
353 | movw %ax, %es |
---|
354 | movw %ax, %fs |
---|
355 | movw %ax, %gs |
---|
356 | popl %eax |
---|
357 | |
---|
358 | /* Call PM routine */ |
---|
359 | call *%ax |
---|
360 | |
---|
361 | /* Set real-mode segment limits on %ds, %es, %fs and %gs */ |
---|
362 | movw %ss, %ax |
---|
363 | movw %ax, %ds |
---|
364 | movw %ax, %es |
---|
365 | movw %ax, %fs |
---|
366 | movw %ax, %gs |
---|
367 | |
---|
368 | /* Return CPU to real mode */ |
---|
369 | movl %cr0, %eax |
---|
370 | andb $0!CR0_PE, %al |
---|
371 | movl %eax, %cr0 |
---|
372 | |
---|
373 | /* Restore registers and flags */ |
---|
374 | lret /* will ljmp to 99f */ |
---|
375 | 99: popw %ss |
---|
376 | popw %ds |
---|
377 | popw %es |
---|
378 | popw %fs |
---|
379 | popw %gs |
---|
380 | data32 lgdt PM_CALL_VAR(pm_saved_gdt)(%bp) |
---|
381 | popfl |
---|
382 | movw %bp, %sp |
---|
383 | popw %bp |
---|
384 | ret |
---|
385 | .size pm_call, . - pm_call |
---|
386 | |
---|
387 | set_seg_base: |
---|
388 | rolw $4, %ax |
---|
389 | movw %ax, 2(%bp,%di) |
---|
390 | andw $0xfff0, 2(%bp,%di) |
---|
391 | movb %al, 4(%bp,%di) |
---|
392 | andb $0x0f, 4(%bp,%di) |
---|
393 | ret |
---|
394 | .size set_seg_base, . - set_seg_base |
---|
395 | |
---|
396 | #endif /* KEEP_IT_REAL */ |
---|
397 | |
---|
398 | /**************************************************************************** |
---|
399 | * copy_bytes (real-mode or 16-bit protected-mode near call) |
---|
400 | * |
---|
401 | * Copy bytes |
---|
402 | * |
---|
403 | * Parameters: |
---|
404 | * %ds:esi : source address |
---|
405 | * %es:edi : destination address |
---|
406 | * %ecx : length |
---|
407 | * Returns: |
---|
408 | * %ds:esi : next source address |
---|
409 | * %es:edi : next destination address |
---|
410 | * Corrupts: |
---|
411 | * None |
---|
412 | **************************************************************************** |
---|
413 | */ |
---|
414 | .section ".prefix.lib", "awx", @progbits |
---|
415 | .code16 |
---|
416 | copy_bytes: |
---|
417 | pushl %ecx |
---|
418 | rep addr32 movsb |
---|
419 | popl %ecx |
---|
420 | ret |
---|
421 | .size copy_bytes, . - copy_bytes |
---|
422 | |
---|
423 | /**************************************************************************** |
---|
424 | * install_block (real-mode near call) |
---|
425 | * |
---|
426 | * Install block to specified address |
---|
427 | * |
---|
428 | * Parameters: |
---|
429 | * %esi : source physical address (must be a multiple of 16) |
---|
430 | * %edi : destination physical address (must be a multiple of 16) |
---|
431 | * %ecx : length of (decompressed) data |
---|
432 | * %edx : total length of block (including any uninitialised data portion) |
---|
433 | * Returns: |
---|
434 | * %esi : next source physical address (will be a multiple of 16) |
---|
435 | * Corrupts: |
---|
436 | * none |
---|
437 | **************************************************************************** |
---|
438 | */ |
---|
439 | .section ".prefix.lib", "awx", @progbits |
---|
440 | .code16 |
---|
441 | install_block: |
---|
442 | |
---|
443 | #ifdef KEEP_IT_REAL |
---|
444 | |
---|
445 | /* Preserve registers */ |
---|
446 | pushw %ds |
---|
447 | pushw %es |
---|
448 | pushl %ecx |
---|
449 | pushl %edi |
---|
450 | |
---|
451 | /* Convert %esi and %edi to segment registers */ |
---|
452 | shrl $4, %esi |
---|
453 | movw %si, %ds |
---|
454 | xorw %si, %si |
---|
455 | shrl $4, %edi |
---|
456 | movw %di, %es |
---|
457 | xorw %di, %di |
---|
458 | |
---|
459 | #else /* KEEP_IT_REAL */ |
---|
460 | |
---|
461 | /* Call self in protected mode */ |
---|
462 | pushw %ax |
---|
463 | movw $1f, %ax |
---|
464 | call pm_call |
---|
465 | popw %ax |
---|
466 | ret |
---|
467 | 1: |
---|
468 | /* Preserve registers */ |
---|
469 | pushl %ecx |
---|
470 | pushl %edi |
---|
471 | |
---|
472 | #endif /* KEEP_IT_REAL */ |
---|
473 | |
---|
474 | |
---|
475 | #if COMPRESS |
---|
476 | /* Decompress source to destination */ |
---|
477 | call decompress16 |
---|
478 | #else |
---|
479 | /* Copy source to destination */ |
---|
480 | call copy_bytes |
---|
481 | #endif |
---|
482 | |
---|
483 | /* Zero .bss portion */ |
---|
484 | negl %ecx |
---|
485 | addl %edx, %ecx |
---|
486 | pushw %ax |
---|
487 | xorw %ax, %ax |
---|
488 | rep addr32 stosb |
---|
489 | popw %ax |
---|
490 | |
---|
491 | /* Round up %esi to start of next source block */ |
---|
492 | addl $0xf, %esi |
---|
493 | andl $~0xf, %esi |
---|
494 | |
---|
495 | |
---|
496 | #ifdef KEEP_IT_REAL |
---|
497 | |
---|
498 | /* Convert %ds:esi back to a physical address */ |
---|
499 | movzwl %ds, %cx |
---|
500 | shll $4, %ecx |
---|
501 | addl %ecx, %esi |
---|
502 | |
---|
503 | /* Restore registers */ |
---|
504 | popl %edi |
---|
505 | popl %ecx |
---|
506 | popw %es |
---|
507 | popw %ds |
---|
508 | |
---|
509 | #else /* KEEP_IT_REAL */ |
---|
510 | |
---|
511 | /* Restore registers */ |
---|
512 | popl %edi |
---|
513 | popl %ecx |
---|
514 | |
---|
515 | #endif |
---|
516 | |
---|
517 | ret |
---|
518 | .size install_block, . - install_block |
---|
519 | |
---|
520 | /**************************************************************************** |
---|
521 | * alloc_basemem (real-mode near call) |
---|
522 | * |
---|
523 | * Allocate space for .text16 and .data16 from top of base memory. |
---|
524 | * Memory is allocated using the BIOS free base memory counter at |
---|
525 | * 0x40:13. |
---|
526 | * |
---|
527 | * Parameters: |
---|
528 | * none |
---|
529 | * Returns: |
---|
530 | * %ax : .text16 segment address |
---|
531 | * %bx : .data16 segment address |
---|
532 | * Corrupts: |
---|
533 | * none |
---|
534 | **************************************************************************** |
---|
535 | */ |
---|
536 | .section ".prefix.lib", "awx", @progbits |
---|
537 | .code16 |
---|
538 | .globl alloc_basemem |
---|
539 | alloc_basemem: |
---|
540 | /* Preserve registers */ |
---|
541 | pushw %fs |
---|
542 | |
---|
543 | /* FBMS => %ax as segment address */ |
---|
544 | pushw $0x40 |
---|
545 | popw %fs |
---|
546 | movw %fs:0x13, %ax |
---|
547 | shlw $6, %ax |
---|
548 | |
---|
549 | /* Calculate .data16 segment address */ |
---|
550 | subw $_data16_memsz_pgh, %ax |
---|
551 | pushw %ax |
---|
552 | |
---|
553 | /* Calculate .text16 segment address */ |
---|
554 | subw $_text16_memsz_pgh, %ax |
---|
555 | pushw %ax |
---|
556 | |
---|
557 | /* Update FBMS */ |
---|
558 | shrw $6, %ax |
---|
559 | movw %ax, %fs:0x13 |
---|
560 | |
---|
561 | /* Retrieve .text16 and .data16 segment addresses */ |
---|
562 | popw %ax |
---|
563 | popw %bx |
---|
564 | |
---|
565 | /* Restore registers and return */ |
---|
566 | popw %fs |
---|
567 | ret |
---|
568 | .size alloc_basemem, . - alloc_basemem |
---|
569 | |
---|
570 | /**************************************************************************** |
---|
571 | * free_basemem (real-mode near call) |
---|
572 | * |
---|
573 | * Free space allocated with alloc_basemem. |
---|
574 | * |
---|
575 | * Parameters: |
---|
576 | * %ax : .text16 segment address |
---|
577 | * %bx : .data16 segment address |
---|
578 | * Returns: |
---|
579 | * %ax : 0 if successfully freed |
---|
580 | * Corrupts: |
---|
581 | * none |
---|
582 | **************************************************************************** |
---|
583 | */ |
---|
584 | .section ".text16", "ax", @progbits |
---|
585 | .code16 |
---|
586 | .globl free_basemem |
---|
587 | free_basemem: |
---|
588 | /* Preserve registers */ |
---|
589 | pushw %fs |
---|
590 | |
---|
591 | /* Check FBMS counter */ |
---|
592 | pushw %ax |
---|
593 | shrw $6, %ax |
---|
594 | pushw $0x40 |
---|
595 | popw %fs |
---|
596 | cmpw %ax, %fs:0x13 |
---|
597 | popw %ax |
---|
598 | jne 1f |
---|
599 | |
---|
600 | /* Check hooked interrupt count */ |
---|
601 | cmpw $0, %cs:hooked_bios_interrupts |
---|
602 | jne 1f |
---|
603 | |
---|
604 | /* OK to free memory */ |
---|
605 | addw $_text16_memsz_pgh, %ax |
---|
606 | addw $_data16_memsz_pgh, %ax |
---|
607 | shrw $6, %ax |
---|
608 | movw %ax, %fs:0x13 |
---|
609 | xorw %ax, %ax |
---|
610 | |
---|
611 | 1: /* Restore registers and return */ |
---|
612 | popw %fs |
---|
613 | ret |
---|
614 | .size free_basemem, . - free_basemem |
---|
615 | |
---|
616 | .section ".text16.data", "aw", @progbits |
---|
617 | .globl hooked_bios_interrupts |
---|
618 | hooked_bios_interrupts: |
---|
619 | .word 0 |
---|
620 | .size hooked_bios_interrupts, . - hooked_bios_interrupts |
---|
621 | |
---|
622 | /**************************************************************************** |
---|
623 | * install (real-mode near call) |
---|
624 | * |
---|
625 | * Install all text and data segments. |
---|
626 | * |
---|
627 | * Parameters: |
---|
628 | * none |
---|
629 | * Returns: |
---|
630 | * %ax : .text16 segment address |
---|
631 | * %bx : .data16 segment address |
---|
632 | * Corrupts: |
---|
633 | * none |
---|
634 | **************************************************************************** |
---|
635 | */ |
---|
636 | .section ".prefix.lib", "awx", @progbits |
---|
637 | .code16 |
---|
638 | .globl install |
---|
639 | install: |
---|
640 | /* Preserve registers */ |
---|
641 | pushl %esi |
---|
642 | pushl %edi |
---|
643 | /* Allocate space for .text16 and .data16 */ |
---|
644 | call alloc_basemem |
---|
645 | /* Image source = %cs:0000 */ |
---|
646 | xorl %esi, %esi |
---|
647 | /* Image destination = HIGHMEM_LOADPOINT */ |
---|
648 | movl $HIGHMEM_LOADPOINT, %edi |
---|
649 | /* Install text and data segments */ |
---|
650 | call install_prealloc |
---|
651 | /* Restore registers and return */ |
---|
652 | popl %edi |
---|
653 | popl %esi |
---|
654 | ret |
---|
655 | .size install, . - install |
---|
656 | |
---|
657 | /**************************************************************************** |
---|
658 | * install_prealloc (real-mode near call) |
---|
659 | * |
---|
660 | * Install all text and data segments. |
---|
661 | * |
---|
662 | * Parameters: |
---|
663 | * %ax : .text16 segment address |
---|
664 | * %bx : .data16 segment address |
---|
665 | * %esi : Image source physical address (or zero for %cs:0000) |
---|
666 | * %edi : Decompression temporary area physical address |
---|
667 | * Corrupts: |
---|
668 | * none |
---|
669 | **************************************************************************** |
---|
670 | */ |
---|
671 | .section ".prefix.lib", "awx", @progbits |
---|
672 | .code16 |
---|
673 | .globl install_prealloc |
---|
674 | install_prealloc: |
---|
675 | /* Save registers */ |
---|
676 | pushal |
---|
677 | pushw %ds |
---|
678 | pushw %es |
---|
679 | |
---|
680 | /* Sanity: clear the direction flag asap */ |
---|
681 | cld |
---|
682 | |
---|
683 | /* Calculate physical address of payload (i.e. first source) */ |
---|
684 | testl %esi, %esi |
---|
685 | jnz 1f |
---|
686 | movw %cs, %si |
---|
687 | shll $4, %esi |
---|
688 | 1: addl $_payload_lma, %esi |
---|
689 | |
---|
690 | /* Install .text16 and .data16 */ |
---|
691 | pushl %edi |
---|
692 | movzwl %ax, %edi |
---|
693 | shll $4, %edi |
---|
694 | movl $_text16_memsz, %ecx |
---|
695 | movl %ecx, %edx |
---|
696 | call install_block /* .text16 */ |
---|
697 | movzwl %bx, %edi |
---|
698 | shll $4, %edi |
---|
699 | movl $_data16_filesz, %ecx |
---|
700 | movl $_data16_memsz, %edx |
---|
701 | call install_block /* .data16 */ |
---|
702 | popl %edi |
---|
703 | |
---|
704 | /* Set up %ds for access to .data16 */ |
---|
705 | movw %bx, %ds |
---|
706 | |
---|
707 | #ifdef KEEP_IT_REAL |
---|
708 | /* Initialise libkir */ |
---|
709 | movw %ax, (init_libkir_vector+2) |
---|
710 | lcall *init_libkir_vector |
---|
711 | #else |
---|
712 | /* Install .text and .data to temporary area in high memory, |
---|
713 | * prior to reading the E820 memory map and relocating |
---|
714 | * properly. |
---|
715 | */ |
---|
716 | movl $_textdata_filesz, %ecx |
---|
717 | movl $_textdata_memsz, %edx |
---|
718 | call install_block |
---|
719 | |
---|
720 | /* Initialise librm at current location */ |
---|
721 | movw %ax, (init_librm_vector+2) |
---|
722 | lcall *init_librm_vector |
---|
723 | |
---|
724 | /* Call relocate() to determine target address for relocation. |
---|
725 | * relocate() will return with %esi, %edi and %ecx set up |
---|
726 | * ready for the copy to the new location. |
---|
727 | */ |
---|
728 | movw %ax, (prot_call_vector+2) |
---|
729 | pushl $relocate |
---|
730 | lcall *prot_call_vector |
---|
731 | popl %edx /* discard */ |
---|
732 | |
---|
733 | /* Copy code to new location */ |
---|
734 | pushl %edi |
---|
735 | pushw %ax |
---|
736 | movw $copy_bytes, %ax |
---|
737 | call pm_call |
---|
738 | popw %ax |
---|
739 | popl %edi |
---|
740 | |
---|
741 | /* Initialise librm at new location */ |
---|
742 | lcall *init_librm_vector |
---|
743 | |
---|
744 | #endif |
---|
745 | /* Restore registers */ |
---|
746 | popw %es |
---|
747 | popw %ds |
---|
748 | popal |
---|
749 | ret |
---|
750 | .size install_prealloc, . - install_prealloc |
---|
751 | |
---|
752 | /* Vectors for far calls to .text16 functions */ |
---|
753 | .section ".data16", "aw", @progbits |
---|
754 | #ifdef KEEP_IT_REAL |
---|
755 | init_libkir_vector: |
---|
756 | .word init_libkir |
---|
757 | .word 0 |
---|
758 | .size init_libkir_vector, . - init_libkir_vector |
---|
759 | #else |
---|
760 | init_librm_vector: |
---|
761 | .word init_librm |
---|
762 | .word 0 |
---|
763 | .size init_librm_vector, . - init_librm_vector |
---|
764 | prot_call_vector: |
---|
765 | .word prot_call |
---|
766 | .word 0 |
---|
767 | .size prot_call_vector, . - prot_call_vector |
---|
768 | #endif |
---|
769 | |
---|
770 | /**************************************************************************** |
---|
771 | * uninstall (real-mode near call) |
---|
772 | * |
---|
773 | * Uninstall all text and data segments. |
---|
774 | * |
---|
775 | * Parameters: |
---|
776 | * %ax : .text16 segment address |
---|
777 | * %bx : .data16 segment address |
---|
778 | * Returns: |
---|
779 | * none |
---|
780 | * Corrupts: |
---|
781 | * none |
---|
782 | **************************************************************************** |
---|
783 | */ |
---|
784 | .section ".text16", "ax", @progbits |
---|
785 | .code16 |
---|
786 | .globl uninstall |
---|
787 | uninstall: |
---|
788 | call free_basemem |
---|
789 | ret |
---|
790 | .size uninstall, . - uninstall |
---|
791 | |
---|
792 | |
---|
793 | |
---|
794 | /* File split information for the compressor */ |
---|
795 | #if COMPRESS |
---|
796 | .section ".zinfo", "a", @progbits |
---|
797 | .ascii "COPY" |
---|
798 | .long _prefix_lma |
---|
799 | .long _prefix_filesz |
---|
800 | .long _max_align |
---|
801 | .ascii "PACK" |
---|
802 | .long _text16_lma |
---|
803 | .long _text16_filesz |
---|
804 | .long _max_align |
---|
805 | .ascii "PACK" |
---|
806 | .long _data16_lma |
---|
807 | .long _data16_filesz |
---|
808 | .long _max_align |
---|
809 | .ascii "PACK" |
---|
810 | .long _textdata_lma |
---|
811 | .long _textdata_filesz |
---|
812 | .long _max_align |
---|
813 | #else /* COMPRESS */ |
---|
814 | .section ".zinfo", "a", @progbits |
---|
815 | .ascii "COPY" |
---|
816 | .long _prefix_lma |
---|
817 | .long _filesz |
---|
818 | .long _max_align |
---|
819 | #endif /* COMPRESS */ |
---|