| /* -*- asm -*- |
| * $ $ |
| * |
| */ |
| |
| /* |
| * Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer |
| * |
| * This file is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation; either version 2 of |
| * the License, or (at your option) any later version. |
| * |
| * Originally this code was part of ucl the data compression library |
| * for upx the ``Ultimate Packer of eXecutables''. |
| * |
| * - Converted to gas assembly, and refitted to work with etherboot. |
| * Eric Biederman 20 Aug 2002 |
| * - Merged the nrv2b decompressor into crt0.base of LinuxBIOS |
| * Eric Biederman 26 Sept 2002 |
| */ |
| |
| |
| #include <arch/asm.h> |
| #include <arch/intel.h> |
| #include <console/loglevel.h> |
| |
| /* |
| * This is the entry code the code in .reset section |
| * jumps to this address. |
| * |
| */ |
| .section ".rom.data", "a", @progbits |
| .section ".rom.text", "ax", @progbits |
| |
| intel_chip_post_macro(0x01) /* delay for chipsets */ |
| |
| #include "crt0_includes.h" |
| |
| /* uses: esp, ebx, ax, dx */ |
| #define __CONSOLE_TX_STRING(string) \ |
| mov string, %ebx ; \ |
| CALLSP(console_tx_string) |
| |
| #if ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG |
| #define CONSOLE_DEBUG_TX_STRING(string) __CONSOLE_TX_STRING(string) |
| #else |
| #define CONSOLE_DEBUG_TX_STRING(string) |
| #endif |
| |
| /* clear boot_complete flag */ |
| xorl %ebp, %ebp |
| __main: |
| CONSOLE_DEBUG_TX_STRING($str_copying_to_ram) |
| |
| /* |
| * Copy data into RAM and clear the BSS. Since these segments |
| * isn\'t really that big we just copy/clear using bytes, not |
| * double words. |
| */ |
| intel_chip_post_macro(0x11) /* post 11 */ |
| |
| cld /* clear direction flag */ |
| |
| /* copy linuxBIOS from it's initial load location to |
| * the location it is compiled to run at. |
| * Normally this is copying from FLASH ROM to RAM. |
| */ |
| #if !CONFIG_COMPRESS |
| movl $_liseg, %esi |
| movl $_iseg, %edi |
| movl $_eiseg, %ecx |
| subl %edi, %ecx |
| rep movsb |
| #else |
| leal 4+_liseg, %esi |
| leal _iseg, %edi |
| movl %ebp, %esp /* preserve %ebp */ |
| movl $-1, %ebp /* last_m_off = -1 */ |
| jmp dcl1_n2b |
| |
| /* ------------- DECOMPRESSION ------------- |
| |
| Input: |
| %esi - source |
| %edi - dest |
| %ebp - -1 |
| cld |
| |
| Output: |
| %eax - 0 |
| %ecx - 0 |
| */ |
| |
| .macro getbit bits |
| .if \bits == 1 |
| addl %ebx, %ebx |
| jnz 1f |
| .endif |
| movl (%esi), %ebx |
| subl $-4, %esi /* sets carry flag */ |
| adcl %ebx, %ebx |
| 1: |
| .endm |
| |
| decompr_literals_n2b: |
| movsb |
| |
| decompr_loop_n2b: |
| addl %ebx, %ebx |
| jnz dcl2_n2b |
| dcl1_n2b: |
| getbit 32 |
| dcl2_n2b: |
| jc decompr_literals_n2b |
| xorl %eax, %eax |
| incl %eax /* m_off = 1 */ |
| loop1_n2b: |
| getbit 1 |
| adcl %eax, %eax /* m_off = m_off*2 + getbit() */ |
| getbit 1 |
| jnc loop1_n2b /* while(!getbit()) */ |
| xorl %ecx, %ecx |
| subl $3, %eax |
| jb decompr_ebpeax_n2b /* if (m_off == 2) goto decompr_ebpeax_n2b ? */ |
| shll $8, %eax |
| movb (%esi), %al /* m_off = (m_off - 3)*256 + src[ilen++] */ |
| incl %esi |
| xorl $-1, %eax |
| jz decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */ |
| movl %eax, %ebp /* last_m_off = m_off ?*/ |
| decompr_ebpeax_n2b: |
| getbit 1 |
| adcl %ecx, %ecx /* m_len = getbit() */ |
| getbit 1 |
| adcl %ecx, %ecx /* m_len = m_len*2 + getbit()) */ |
| jnz decompr_got_mlen_n2b /* if (m_len == 0) goto decompr_got_mlen_n2b */ |
| incl %ecx /* m_len++ */ |
| loop2_n2b: |
| getbit 1 |
| adcl %ecx, %ecx /* m_len = m_len*2 + getbit() */ |
| getbit 1 |
| jnc loop2_n2b /* while(!getbit()) */ |
| incl %ecx |
| incl %ecx /* m_len += 2 */ |
| decompr_got_mlen_n2b: |
| cmpl $-0xd00, %ebp |
| adcl $1, %ecx /* m_len = m_len + 1 + (last_m_off > 0xd00) */ |
| movl %esi, %edx |
| leal (%edi,%ebp), %esi /* m_pos = dst + olen + -m_off */ |
| rep |
| movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */ |
| movl %edx, %esi |
| jmp decompr_loop_n2b |
| decompr_end_n2b: |
| intel_chip_post_macro(0x12) /* post 12 */ |
| |
| movl %esp, %ebp |
| #endif |
| |
| CONSOLE_DEBUG_TX_STRING($str_pre_main) |
| leal _iseg, %edi |
| jmp %edi |
| |
| .Lhlt: |
| intel_chip_post_macro(0xee) /* post fe */ |
| hlt |
| jmp .Lhlt |
| |
| #if ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG |
| /* Uses esp, ebx, ax, dx */ |
| console_tx_string: |
| mov (%ebx), %al |
| inc %ebx |
| cmp $0, %al |
| jne 9f |
| RETSP |
| 9: |
| /* Base Address */ |
| #ifndef TTYS0_BASE |
| #define TTYS0_BASE 0x3f8 |
| #endif |
| /* Data */ |
| #define TTYS0_RBR (TTYS0_BASE+0x00) |
| |
| /* Control */ |
| #define TTYS0_TBR TTYS0_RBR |
| #define TTYS0_IER (TTYS0_BASE+0x01) |
| #define TTYS0_IIR (TTYS0_BASE+0x02) |
| #define TTYS0_FCR TTYS0_IIR |
| #define TTYS0_LCR (TTYS0_BASE+0x03) |
| #define TTYS0_MCR (TTYS0_BASE+0x04) |
| #define TTYS0_DLL TTYS0_RBR |
| #define TTYS0_DLM TTYS0_IER |
| |
| /* Status */ |
| #define TTYS0_LSR (TTYS0_BASE+0x05) |
| #define TTYS0_MSR (TTYS0_BASE+0x06) |
| #define TTYS0_SCR (TTYS0_BASE+0x07) |
| |
| mov %al, %ah |
| 10: mov $TTYS0_LSR, %dx |
| inb %dx, %al |
| test $0x20, %al |
| je 10b |
| mov $TTYS0_TBR, %dx |
| mov %ah, %al |
| outb %al, %dx |
| |
| jmp console_tx_string |
| |
| .section ".rom.data" |
| str_copying_to_ram: .string "Copying LinuxBIOS to ram.\r\n" |
| str_pre_main: .string "Jumping to LinuxBIOS.\r\n" |
| .previous |
| |
| #endif /* ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG */ |