These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / arch / i386 / prefix / libprefix.S
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., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  *
23  */
24
25 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
26
27         .arch i386
28
29 /* Image compression enabled */
30 #define COMPRESS 1
31
32 /* Protected mode flag */
33 #define CR0_PE 1
34
35 /* Allow for DBG()-style messages within libprefix */
36 #ifdef NDEBUG
37         .macro  progress message
38         .endm
39 #else
40         .macro  progress message
41         pushfl
42         pushw   %ds
43         pushw   %si
44         pushw   %di
45         pushw   %cs
46         popw    %ds
47         xorw    %di, %di
48         movw    $progress_\@, %si
49         call    print_message
50         popw    %di
51         popw    %si
52         popw    %ds
53         popfl
54         .section ".prefix.data", "aw", @progbits
55 progress_\@:
56         .asciz  "\message"
57         .size   progress_\@, . - progress_\@
58         .previous
59         .endm
60 #endif
61
62 /*****************************************************************************
63  * Utility function: print character (with LF -> LF,CR translation)
64  *
65  * Parameters:
66  *   %al : character to print
67  *   %ds:di : output buffer (or %di=0 to print to console)
68  * Returns:
69  *   %ds:di : next character in output buffer (if applicable)
70  *****************************************************************************
71  */
72         .section ".prefix.lib", "awx", @progbits
73         .code16
74         .globl  print_character
75 print_character:
76         /* Preserve registers */
77         pushw   %ax
78         pushw   %bx
79         pushw   %bp
80         /* If %di is non-zero, write character to buffer and exit */
81         testw   %di, %di
82         jz      1f
83         movb    %al, %ds:(%di)
84         incw    %di
85         jmp     3f
86 1:      /* Print character */
87         movw    $0x0007, %bx            /* page 0, attribute 7 (normal) */
88         movb    $0x0e, %ah              /* write char, tty mode */
89         cmpb    $0x0a, %al              /* '\n'? */
90         jne     2f
91         int     $0x10
92         movb    $0x0d, %al
93 2:      int     $0x10
94         /* Restore registers and return */
95 3:      popw    %bp
96         popw    %bx
97         popw    %ax
98         ret
99         .size   print_character, . - print_character
100
101 /*****************************************************************************
102  * Utility function: print space
103  *
104  * Parameters:
105  *   %ds:di : output buffer (or %di=0 to print to console)
106  * Returns:
107  *   %ds:di : next character in output buffer (if applicable)
108  *****************************************************************************
109  */
110         .section ".prefix.lib", "awx", @progbits
111         .code16
112         .globl  print_space
113 print_space:
114         /* Preserve registers */
115         pushw   %ax
116         /* Print space */
117         movb    $( ' ' ), %al
118         call    print_character
119         /* Restore registers and return */
120         popw    %ax
121         ret
122         .size   print_space, . - print_space
123
124 /*****************************************************************************
125  * Utility function: print a NUL-terminated string
126  *
127  * Parameters:
128  *   %ds:si : string to print
129  *   %ds:di : output buffer (or %di=0 to print to console)
130  * Returns:
131  *   %ds:si : character after terminating NUL
132  *   %ds:di : next character in output buffer (if applicable)
133  *****************************************************************************
134  */
135         .section ".prefix.lib", "awx", @progbits
136         .code16
137         .globl  print_message
138 print_message:
139         /* Preserve registers */
140         pushw   %ax
141         /* Print string */
142 1:      lodsb
143         testb   %al, %al
144         je      2f
145         call    print_character
146         jmp     1b
147 2:      /* Restore registers and return */
148         popw    %ax
149         ret
150         .size   print_message, . - print_message
151
152 /*****************************************************************************
153  * Utility functions: print hex digit/byte/word/dword
154  *
155  * Parameters:
156  *   %al (low nibble) : digit to print
157  *   %al : byte to print
158  *   %ax : word to print
159  *   %eax : dword to print
160  *   %ds:di : output buffer (or %di=0 to print to console)
161  * Returns:
162  *   %ds:di : next character in output buffer (if applicable)
163  *****************************************************************************
164  */
165         .section ".prefix.lib", "awx", @progbits
166         .code16
167         .globl  print_hex_dword
168 print_hex_dword:
169         rorl    $16, %eax
170         call    print_hex_word
171         rorl    $16, %eax
172         /* Fall through */
173         .size   print_hex_dword, . - print_hex_dword
174         .globl  print_hex_word
175 print_hex_word:
176         xchgb   %al, %ah
177         call    print_hex_byte
178         xchgb   %al, %ah
179         /* Fall through */
180         .size   print_hex_word, . - print_hex_word
181         .globl  print_hex_byte
182 print_hex_byte:
183         rorb    $4, %al
184         call    print_hex_nibble
185         rorb    $4, %al
186         /* Fall through */
187         .size   print_hex_byte, . - print_hex_byte
188         .globl  print_hex_nibble
189 print_hex_nibble:
190         /* Preserve registers */
191         pushw   %ax
192         /* Print digit (technique by Norbert Juffa <norbert.juffa@amd.com> */
193         andb    $0x0f, %al
194         cmpb    $10, %al
195         sbbb    $0x69, %al
196         das
197         call    print_character
198         /* Restore registers and return */
199         popw    %ax
200         ret
201         .size   print_hex_nibble, . - print_hex_nibble
202
203 /*****************************************************************************
204  * Utility function: print PCI bus:dev.fn
205  *
206  * Parameters:
207  *   %ax : PCI bus:dev.fn to print
208  *   %ds:di : output buffer (or %di=0 to print to console)
209  * Returns:
210  *   %ds:di : next character in output buffer (if applicable)
211  *****************************************************************************
212  */
213         .section ".prefix.lib", "awx", @progbits
214         .code16
215         .globl  print_pci_busdevfn
216 print_pci_busdevfn:
217         /* Preserve registers */
218         pushw   %ax
219         /* Print bus */
220         xchgb   %al, %ah
221         call    print_hex_byte
222         /* Print ":" */
223         movb    $( ':' ), %al
224         call    print_character
225         /* Print device */
226         movb    %ah, %al
227         shrb    $3, %al
228         call    print_hex_byte
229         /* Print "." */
230         movb    $( '.' ), %al
231         call    print_character
232         /* Print function */
233         movb    %ah, %al
234         andb    $0x07, %al
235         call    print_hex_nibble
236         /* Restore registers and return */
237         popw    %ax
238         ret
239         .size   print_pci_busdevfn, . - print_pci_busdevfn
240
241 /*****************************************************************************
242  * Utility function: clear current line
243  *
244  * Parameters:
245  *   %ds:di : output buffer (or %di=0 to print to console)
246  * Returns:
247  *   %ds:di : next character in output buffer (if applicable)
248  *****************************************************************************
249  */
250         .section ".prefix.lib", "awx", @progbits
251         .code16
252         .globl  print_kill_line
253 print_kill_line:
254         /* Preserve registers */
255         pushw   %ax
256         pushw   %cx
257         /* Print CR */
258         movb    $( '\r' ), %al
259         call    print_character
260         /* Print 79 spaces */
261         movw    $79, %cx
262 1:      call    print_space
263         loop    1b
264         /* Print CR */
265         call    print_character
266         /* Restore registers and return */
267         popw    %cx
268         popw    %ax
269         ret
270         .size   print_kill_line, . - print_kill_line
271
272 /****************************************************************************
273  * copy_bytes
274  *
275  * Copy bytes
276  *
277  * Parameters:
278  *   %ds:esi : source address
279  *   %es:edi : destination address
280  *   %ecx : length
281  * Returns:
282  *   %ds:esi : next source address
283  *   %es:edi : next destination address
284  * Corrupts:
285  *   None
286  ****************************************************************************
287  */
288         .section ".prefix.lib", "awx", @progbits
289         .code16
290 copy_bytes:
291         pushl   %ecx
292         rep addr32 movsb
293         popl    %ecx
294         ret
295         .size   copy_bytes, . - copy_bytes
296
297 /****************************************************************************
298  * zero_bytes
299  *
300  * Zero bytes
301  *
302  * Parameters:
303  *   %es:edi : destination address
304  *   %ecx : length
305  * Returns:
306  *   %es:edi : next destination address
307  * Corrupts:
308  *   None
309  ****************************************************************************
310  */
311         .section ".prefix.lib", "awx", @progbits
312         .code16
313 zero_bytes:
314         pushl   %ecx
315         pushw   %ax
316         xorw    %ax, %ax
317         rep addr32 stosb
318         popw    %ax
319         popl    %ecx
320         ret
321         .size   zero_bytes, . - zero_bytes
322
323 /****************************************************************************
324  * process_bytes
325  *
326  * Call memcpy()-like function
327  *
328  * Parameters:
329  *   %esi : source physical address
330  *   %edi : destination physical address
331  *   %ecx : length
332  *   %bx : memcpy()-like function to call, passing parameters:
333  *           %ds:esi : source address
334  *           %es:edi : destination address
335  *           %ecx : length
336  *         and returning:
337  *           %ds:esi : next source address
338  *           %es:edi : next destination address
339  * Returns:
340  *   %esi : next source physical address
341  *   %edi : next destination physical address
342  * Corrupts:
343  *   None
344  ****************************************************************************
345  */
346         .section ".prefix.lib", "awx", @progbits
347         .code16
348 process_bytes:
349
350 #ifndef KEEP_IT_REAL
351
352         /* Preserve registers */
353         pushl   %eax
354         pushl   %ebp
355
356         /* Construct GDT on stack (since .prefix may not be writable) */
357         .equ    PM_DS, 0x18     /* Flat data segment */
358         pushl   $0x00cf9300
359         pushl   $0x0000ffff
360         .equ    PM_SS, 0x10     /* Stack segment based at %ss:0000 */
361         pushl   $0x008f0930
362         pushw   %ss
363         pushw   $0xffff
364         .equ    PM_CS, 0x08     /* Code segment based at %cs:0000 */
365         pushl   $0x008f09b0
366         pushw   %cs
367         pushw   $0xffff
368         pushl   $0              /* Base and length */
369         pushw   %ss
370         pushw   $0x1f
371         movzwl  %sp, %ebp
372         shll    $4, 0x02(%bp)
373         addl    %ebp, 0x02(%bp)
374         shll    $4, 0x0a(%bp)
375         shll    $4, 0x12(%bp)
376         subw    $8, %sp
377         sgdt    -8(%bp)
378
379         /* Switch to protected mode */
380         pushw   %gs
381         pushw   %fs
382         pushw   %es
383         pushw   %ds
384         pushw   %ss
385         pushw   %cs
386         pushw   $2f
387         cli
388         data32 lgdt (%bp)
389         movl    %cr0, %eax
390         orb     $CR0_PE, %al
391         movl    %eax, %cr0
392         ljmp    $PM_CS, $1f
393 1:      movw    $PM_SS, %ax
394         movw    %ax, %ss
395         movw    $PM_DS, %ax
396         movw    %ax, %ds
397         movw    %ax, %es
398         movw    %ax, %fs
399         movw    %ax, %gs
400
401 #ifdef NDEBUG
402         /* Call memcpy()-like function */
403         call    *%bx
404 #endif
405
406         /* Return to (flat) real mode */
407         movl    %cr0, %eax
408         andb    $0!CR0_PE, %al
409         movl    %eax, %cr0
410         lret
411 2:      /* lret will ljmp to here */
412         popw    %ss
413         popw    %ds
414         popw    %es
415         popw    %fs
416         popw    %gs
417
418 #ifndef NDEBUG
419         /* Call memcpy()-like function in flat real mode (to allow for
420          * debug output via INT 10).
421          */
422         pushw   %ds
423         pushw   %es
424         xorw    %ax, %ax
425         movw    %ax, %ds
426         movw    %ax, %es
427         call    *%bx
428         popw    %es
429         popw    %ds
430 #endif
431
432         /* Restore GDT */
433         data32 lgdt -8(%bp)
434         addw    $( 8 /* saved GDT */ + ( PM_DS + 8 ) /* GDT on stack */ ), %sp
435
436         /* Restore registers and return */
437         popl    %ebp
438         popl    %eax
439         ret
440
441 #else /* KEEP_IT_REAL */
442
443         /* Preserve registers */
444         pushl   %eax
445         pushw   %ds
446         pushw   %es
447         
448         /* Convert %esi and %edi to %ds:esi and %es:edi */
449         shrl    $4, %esi
450         movw    %si, %ds
451         xorw    %si, %si
452         shll    $4, %esi
453         shrl    $4, %edi
454         movw    %di, %es
455         xorw    %di, %di
456         shll    $4, %edi
457
458         /* Call memcpy()-like function */
459         call    *%bx
460
461         /* Convert %ds:esi and %es:edi back to physical addresses */
462         xorl    %eax, %eax
463         movw    %ds, %ax
464         shll    $4, %eax
465         addl    %eax, %esi
466         xorl    %eax, %eax
467         movw    %es, %ax
468         shll    $4, %eax
469         addl    %eax, %edi
470
471         /* Restore registers and return */
472         popw    %es
473         popw    %ds
474         popl    %eax
475         ret
476
477 #endif /* KEEP_IT_REAL */
478
479         .size   process_bytes, . - process_bytes
480
481 /****************************************************************************
482  * install_block
483  *
484  * Install block to specified address
485  *
486  * Parameters:
487  *   %esi : source physical address (must be a multiple of 16)
488  *   %edi : destination physical address (must be a multiple of 16)
489  *   %ecx : length of (decompressed) data
490  *   %edx : total length of block (including any uninitialised data portion)
491  * Returns:
492  *   %esi : next source physical address (will be a multiple of 16)
493  *   %edi : next destination physical address (will be a multiple of 16)
494  * Corrupts:
495  *   none
496  ****************************************************************************
497  */
498         .section ".prefix.lib", "awx", @progbits
499         .code16
500 install_block:
501         /* Preserve registers */
502         pushl   %ecx
503         pushw   %bx
504
505         /* Decompress (or copy) source to destination */
506 #if COMPRESS
507         movw    $decompress16, %bx
508 #else
509         movw    $copy_bytes, %bx
510 #endif
511         call    process_bytes
512
513         /* Zero .bss portion */
514         negl    %ecx
515         addl    %edx, %ecx
516         movw    $zero_bytes, %bx
517         call    process_bytes
518
519         /* Round up %esi and %edi to start of next blocks */
520         addl    $0xf, %esi
521         andl    $~0xf, %esi
522         addl    $0xf, %edi
523         andl    $~0xf, %edi
524
525         /* Restore registers and return */
526         popw    %bx
527         popl    %ecx
528         ret
529         .size install_block, . - install_block
530
531 /****************************************************************************
532  * alloc_basemem
533  *
534  * Allocate space for .text16 and .data16 from top of base memory.
535  * Memory is allocated using the BIOS free base memory counter at
536  * 0x40:13.
537  *
538  * Parameters: 
539  *   none
540  * Returns:
541  *   %ax : .text16 segment address
542  *   %bx : .data16 segment address
543  * Corrupts:
544  *   none
545  ****************************************************************************
546  */
547         .section ".prefix.lib", "awx", @progbits
548         .code16
549         .globl  alloc_basemem
550 alloc_basemem:
551         /* Preserve registers */
552         pushw   %fs
553
554         /* FBMS => %ax as segment address */
555         pushw   $0x40
556         popw    %fs
557         movw    %fs:0x13, %ax
558         shlw    $6, %ax
559
560         /* Calculate .data16 segment address */
561         subw    $_data16_memsz_pgh, %ax
562         pushw   %ax
563
564         /* Calculate .text16 segment address.  Round down to ensure
565          * low bits are zero, to speed up mode transitions under KVM.
566          */
567         subw    $_text16_memsz_pgh, %ax
568         andb    $~0x03, %al
569         pushw   %ax
570
571         /* Update FBMS */
572         shrw    $6, %ax
573         movw    %ax, %fs:0x13
574
575         /* Retrieve .text16 and .data16 segment addresses */
576         popw    %ax
577         popw    %bx
578
579         /* Restore registers and return */
580         popw    %fs
581         ret
582         .size alloc_basemem, . - alloc_basemem
583
584 /****************************************************************************
585  * free_basemem
586  *
587  * Free space allocated with alloc_basemem.
588  *
589  * Parameters:
590  *   none (.text16 segment address is implicit in %cs)
591  * Returns:
592  *   %ax : 0 if successfully freed
593  * Corrupts:
594  *   none
595  ****************************************************************************
596  */
597         .section ".text16", "ax", @progbits
598         .code16
599         .globl  free_basemem
600 free_basemem:
601         /* Preserve registers */
602         pushw   %fs
603         pushw   %ax
604
605         /* Check FBMS counter */
606         movw    %cs, %ax
607         shrw    $6, %ax
608         pushw   $0x40
609         popw    %fs
610         cmpw    %ax, %fs:0x13
611         jne     1f
612
613         /* Check hooked interrupt count */
614         cmpw    $0, %cs:hooked_bios_interrupts
615         jne     1f
616
617         /* OK to free memory */
618         movw    %cs, %ax
619         addw    $_text16_memsz_pgh, %ax
620         addw    $_data16_memsz_pgh, %ax
621         shrw    $6, %ax
622         movw    %ax, %fs:0x13
623         xorw    %ax, %ax
624
625 1:      /* Restore registers and return */
626         popw    %ax
627         popw    %fs
628         ret
629         .size free_basemem, . - free_basemem
630
631         .section ".text16.data", "aw", @progbits
632         .globl  hooked_bios_interrupts
633 hooked_bios_interrupts:
634         .word   0
635         .size   hooked_bios_interrupts, . - hooked_bios_interrupts
636
637 /****************************************************************************
638  * install
639  *
640  * Install all text and data segments.
641  *
642  * Parameters:
643  *   none
644  * Returns:
645  *   %ax  : .text16 segment address
646  *   %bx  : .data16 segment address
647  * Corrupts:
648  *   none
649  ****************************************************************************
650  */
651         .section ".prefix.lib", "awx", @progbits
652         .code16
653         .globl install
654 install:
655         progress "install:\n"
656         /* Preserve registers */
657         pushl   %esi
658         pushl   %edi
659         pushl   %ebp
660         /* Allocate space for .text16 and .data16 */
661         call    alloc_basemem
662         /* Image source = %cs:0000 */
663         xorl    %esi, %esi
664         /* Image destination = default */
665         xorl    %edi, %edi
666         /* Allow arbitrary relocation */
667         orl     $0xffffffff, %ebp
668         /* Install text and data segments */
669         call    install_prealloc
670         /* Restore registers and return */
671         popl    %ebp
672         popl    %edi
673         popl    %esi
674         ret
675         .size install, . - install
676
677 /****************************************************************************
678  * install_prealloc
679  *
680  * Install all text and data segments.
681  *
682  * Parameters:
683  *   %ax  : .text16 segment address
684  *   %bx  : .data16 segment address
685  *   %esi : Image source physical address (or zero for %cs:0000)
686  *   %edi : Decompression temporary area physical address (or zero for default)
687  *   %ebp : Maximum end address for relocation
688  *          - 0xffffffff for no maximum
689  *          - 0x00000000 to inhibit use of INT 15,e820 and INT 15,e801
690  * Corrupts:
691  *   none
692  ****************************************************************************
693  */
694         .section ".prefix.lib", "awx", @progbits
695         .code16
696         .globl install_prealloc
697 install_prealloc:
698         progress "install_prealloc:\n"
699         /* Save registers on external stack */
700         pushal
701         pushw   %ds
702         pushw   %es
703         cld                     /* Sanity: clear the direction flag asap */
704
705         /* Switch to temporary stack in .bss16 */
706         pushw   %ss
707         popw    %ds
708         movl    %esp, %ecx
709         movw    %bx, %ss
710         movl    $_data16_memsz, %esp
711         pushw   %ds
712         pushl   %ecx
713
714         /* Set up %ds for (read-only) access to .prefix */
715         pushw   %cs
716         popw    %ds
717
718         /* Save decompression temporary area physical address */
719         pushl   %edi
720
721         /* Install .text16.early and calculate %ecx as offset to next block */
722         progress "  .text16.early\n"
723         pushl   %esi
724         xorl    %esi, %esi
725         movw    %cs, %si
726         shll    $4, %esi
727         pushl   %esi                    /* Save original %cs:0000 */
728         addl    $_text16_early_lma, %esi
729         movzwl  %ax, %edi
730         shll    $4, %edi
731         movl    $_text16_early_filesz, %ecx
732         movl    $_text16_early_memsz, %edx
733         call    install_block           /* .text16.early */
734         popl    %ecx                    /* Calculate offset to next block */
735         subl    %esi, %ecx
736         negl    %ecx
737         popl    %esi
738
739 #ifndef KEEP_IT_REAL
740
741         /* Access high memory by enabling the A20 gate.  (We will
742          * already have 4GB segment limits as a result of calling
743          * install_block.)
744          */
745         progress "  access_highmem\n"
746         pushw   %cs
747         pushw   $1f
748         pushw   %ax
749         pushw   $access_highmem
750         lret
751 1:      /* Die if we could not access high memory */
752         jnc     3f
753         movw    $a20_death_message, %si
754         xorw    %di, %di
755         call    print_message
756 2:      jmp     2b
757         .section ".prefix.data", "aw", @progbits
758 a20_death_message:
759         .asciz  "\nHigh memory inaccessible - cannot continue\n"
760         .size   a20_death_message, . - a20_death_message
761         .previous
762 3:
763 #endif
764
765         /* Open payload (which may not yet be in memory) */
766         progress "  open_payload\n"
767         pushw   %cs
768         pushw   $1f
769         pushw   %ax
770         pushw   $open_payload
771         lret
772 1:      /* Die if we could not access the payload */
773         jnc     3f
774         xorw    %di, %di
775         movl    %esi, %eax
776         call    print_hex_dword
777         call    print_space
778         movl    %ecx, %eax
779         call    print_hex_dword
780         movw    $payload_death_message, %si
781         call    print_message
782 2:      /* Halt system */
783         cli
784         hlt
785         jmp     2b
786         .section ".prefix.data", "aw", @progbits
787 payload_death_message:
788         .asciz  "\nPayload inaccessible - cannot continue\n"
789         .size   payload_death_message, . - payload_death_message
790         .previous
791 3:
792
793         /* Calculate physical address of payload (i.e. first source) */
794         testl   %esi, %esi
795         jnz     1f
796         movw    %cs, %si
797         shll    $4, %esi
798 1:      addl    %ecx, %esi
799
800         /* Install .text16.late and .data16 */
801         progress "  .text16.late\n"
802         movl    $_text16_late_filesz, %ecx
803         movl    $_text16_late_memsz, %edx
804         call    install_block           /* .text16.late */
805         progress "  .data16\n"
806         movzwl  %bx, %edi
807         shll    $4, %edi
808         movl    $_data16_filesz, %ecx
809         movl    $_data16_filesz, %edx   /* do not zero our temporary stack */
810         call    install_block           /* .data16 */
811
812         /* Set up %ds for access to .data16 */
813         movw    %bx, %ds
814
815         /* Restore decompression temporary area physical address */
816         popl    %edi
817
818 #ifndef KEEP_IT_REAL
819
820         /* Find a suitable decompression temporary area, if none specified */
821         pushl   %eax
822         testl   %edi, %edi
823         jnz     1f
824         /* Use INT 15,88 to find the highest available address via INT
825          * 15,88.  This limits us to around 64MB, which should avoid
826          * all of the POST-time memory map failure modes.
827          */
828         movb    $0x88, %ah
829         int     $0x15
830         movw    %ax, %di
831         addl    $0x400, %edi
832         subl    $_textdata_memsz_kb, %edi
833         shll    $10, %edi
834         /* Sanity check: if we have ended up below 1MB, use 1MB */
835         cmpl    $0x100000, %edi
836         jae     1f
837         movl    $0x100000, %edi
838 1:      popl    %eax
839
840         /* Install .text and .data to temporary area in high memory,
841          * prior to reading the E820 memory map and relocating
842          * properly.
843          */
844         progress "  .textdata\n"
845         pushl   %edi
846         movl    $_textdata_filesz, %ecx
847         movl    $_textdata_memsz, %edx
848         call    install_block
849         popl    %edi
850
851 #endif /* KEEP_IT_REAL */
852
853         /* Switch back to original stack and zero .bss16 */
854         addr32 lss %ss:(%esp), %esp
855         pushl   %edi
856         pushw   %es
857         movw    %bx, %es
858         movl    $_data16_filesz, %edi
859         movl    $_data16_memsz, %ecx
860         subl    %edi, %ecx
861         call    zero_bytes
862         popw    %es
863         popl    %edi
864
865 #ifndef KEEP_IT_REAL
866
867         /* Initialise librm at current location */
868         progress "  init_librm\n"
869         movw    %ax, (init_librm_vector+2)
870         lcall   *init_librm_vector
871
872         /* Inhibit INT 15,e820 and INT 15,e801 if applicable */
873         testl   %ebp, %ebp
874         jnz     1f
875         incb    memmap_post
876         decl    %ebp
877 1:
878         /* Call relocate() to determine target address for relocation.
879          * relocate() will return with %esi, %edi and %ecx set up
880          * ready for the copy to the new location.
881          */
882         progress "  relocate\n"
883         movw    %ax, (prot_call_vector+2)
884         pushl   $relocate
885         lcall   *prot_call_vector
886         popl    %edx /* discard */
887
888         /* Copy code to new location */
889         progress "  copy\n"
890         pushl   %edi
891         pushw   %bx
892         movw    $copy_bytes, %bx
893         call    process_bytes
894         popw    %bx
895         popl    %edi
896
897         /* Initialise librm at new location */
898         progress "  init_librm\n"
899         lcall   *init_librm_vector
900
901 #else /* KEEP_IT_REAL */
902
903         /* Initialise libkir */
904         movw    %ax, (init_libkir_vector+2)
905         lcall   *init_libkir_vector
906
907 #endif /* KEEP_IT_REAL */
908
909         /* Close access to payload */
910         progress "  close_payload\n"
911         movw    %ax, (close_payload_vector+2)
912         lcall   *close_payload_vector
913
914         /* Restore registers */
915         popw    %es
916         popw    %ds
917         popal
918         ret
919         .size install_prealloc, . - install_prealloc
920
921         /* Vectors for far calls to .text16 functions.  Must be in
922          * .data16, since .prefix may not be writable.
923          */
924         .section ".data16", "aw", @progbits
925 #ifdef KEEP_IT_REAL
926 init_libkir_vector:
927         .word init_libkir
928         .word 0
929         .size init_libkir_vector, . - init_libkir_vector
930 #else
931 init_librm_vector:
932         .word init_librm
933         .word 0
934         .size init_librm_vector, . - init_librm_vector
935 prot_call_vector:
936         .word prot_call
937         .word 0
938         .size prot_call_vector, . - prot_call_vector
939 #endif
940 close_payload_vector:
941         .word close_payload
942         .word 0
943         .size close_payload_vector, . - close_payload_vector
944
945         /* Dummy routines to open and close payload */
946         .section ".text16.early.data", "aw", @progbits
947         .weak   open_payload
948         .weak   close_payload
949 open_payload:
950 close_payload:
951         clc
952         lret
953         .size   open_payload, . - open_payload
954         .size   close_payload, . - close_payload
955
956 /****************************************************************************
957  * uninstall
958  *
959  * Uninstall all text and data segments.
960  *
961  * Parameters:
962  *   none (.text16 segment address is implicit in %cs)
963  * Returns:
964  *   none
965  * Corrupts:
966  *   none
967  ****************************************************************************
968  */
969         .section ".text16", "ax", @progbits
970         .code16
971         .globl uninstall
972 uninstall:
973         call    free_basemem
974         ret
975         .size uninstall, . - uninstall
976
977
978
979         /* File split information for the compressor */
980 #if COMPRESS
981 #define PACK_OR_COPY    "PACK"
982 #else
983 #define PACK_OR_COPY    "COPY"
984 #endif
985         .section ".zinfo", "a", @progbits
986         .ascii  "COPY"
987         .long   _prefix_lma
988         .long   _prefix_filesz
989         .long   _max_align
990         .ascii  PACK_OR_COPY
991         .long   _text16_early_lma
992         .long   _text16_early_filesz
993         .long   _max_align
994         .ascii  "PAYL"
995         .long   0
996         .long   0
997         .long   _payload_align
998         .ascii  "COPY"
999         .long   _pprefix_lma
1000         .long   _pprefix_filesz
1001         .long   _max_align
1002         .ascii  PACK_OR_COPY
1003         .long   _text16_late_lma
1004         .long   _text16_late_filesz
1005         .long   _max_align
1006         .ascii  PACK_OR_COPY
1007         .long   _data16_lma
1008         .long   _data16_filesz
1009         .long   _max_align
1010         .ascii  PACK_OR_COPY
1011         .long   _textdata_lma
1012         .long   _textdata_filesz
1013         .long   _max_align
1014
1015         .weak   _payload_align
1016         .equ    _payload_align, 1