|
| 1 | +; limlz: Copyright (C) 2026 Kamila Szewczyk <k@iczelia.net> |
| 2 | +; limine: Copyright (C) 2019-2026 Mintsuki and contributors. |
| 3 | +; |
| 4 | +; Redistribution and use in source and binary forms, with or without |
| 5 | +; modification, are permitted provided that the following conditions are met: |
| 6 | +; |
| 7 | +; 1. Redistributions of source code must retain the above copyright notice, this |
| 8 | +; list of conditions and the following disclaimer. |
| 9 | +; |
| 10 | +; 2. Redistributions in binary form must reproduce the above copyright notice, |
| 11 | +; this list of conditions and the following disclaimer in the documentation |
| 12 | +; and/or other materials provided with the distribution. |
| 13 | +; |
| 14 | +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| 15 | +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 16 | +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 17 | +; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
| 18 | +; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 19 | +; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| 20 | +; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| 21 | +; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| 22 | +; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 23 | +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 | + |
| 25 | +bits 32 |
| 26 | + |
| 27 | +section .entry progbits alloc exec nowrite align=16 |
| 28 | + |
| 29 | +global _start |
| 30 | +_start: |
| 31 | + cld |
| 32 | + ; On stack (cdecl): [esp+4]=compressed_stage2, [esp+8]=stage2_size, |
| 33 | + ; [esp+12]=boot_drive (byte), [esp+16]=pxe |
| 34 | + mov ebx, dword [esp+0x4] ; compressed_stage2 |
| 35 | + mov ebp, dword [ebx] ; expected_crc = *(uint32_t *)compressed_stage2 |
| 36 | + lea edx, [ebx+0x4] ; ip = compressed_stage2 + 4 |
| 37 | + add ebx, dword [esp+0x8] ; ipe = compressed_stage2 + stage2_size |
| 38 | + mov edi, 0xf000 ; op = dest |
| 39 | + ; LZ decompression loop |
| 40 | +.Ltoken: |
| 41 | + movzx ecx, byte [edx] |
| 42 | + lea esi, [edx+0x1] |
| 43 | + mov eax, ecx ; save token |
| 44 | + shr ecx, 0x3 |
| 45 | + and ecx, 0xf ; literal length = (token >> 3) & 15 |
| 46 | + cmp ecx, 0xf |
| 47 | + jne .Llitcopy |
| 48 | + movzx ecx, byte [edx+0x1] |
| 49 | + lea esi, [edx+0x2] |
| 50 | + add ecx, 0xf ; length += extra byte + 15 |
| 51 | +.Llitcopy: |
| 52 | + rep movsb ; copy literals |
| 53 | + cmp esi, ebx |
| 54 | + jae .Lcrc ; if ip >= ipe, done |
| 55 | + test al, al |
| 56 | + jns .Loffset1 ; bit 7 clear => 1-byte offset |
| 57 | + lea edx, [esi+0x2] |
| 58 | + movzx esi, word [esi] ; 2-byte offset |
| 59 | + jmp .Lmatchlen |
| 60 | +.Loffset1: |
| 61 | + lea edx, [esi+0x1] |
| 62 | + movzx esi, byte [esi] ; 1-byte offset |
| 63 | +.Lmatchlen: |
| 64 | + and al, 0x7 |
| 65 | + cmp al, 0x7 |
| 66 | + je .Lmatchextra |
| 67 | + movzx eax, al |
| 68 | + jmp .Ldomatch |
| 69 | +.Lmatchextra: |
| 70 | + movzx eax, byte [edx] |
| 71 | + inc edx |
| 72 | + add eax, 0x7 ; matchlen += extra byte + 7 |
| 73 | +.Ldomatch: |
| 74 | + mov ecx, edi |
| 75 | + sub ecx, esi ; match = op - offset |
| 76 | + mov esi, ecx |
| 77 | + lea ecx, [eax+0x4] ; count = matchlen + 4 |
| 78 | + rep movsb ; copy match |
| 79 | + jmp .Ltoken |
| 80 | + ; CRC32 verification |
| 81 | +.Lcrc: |
| 82 | + mov edx, 0xf000 ; ptr = dest |
| 83 | + mov esi, edx ; (also reused for esp later) |
| 84 | + xor eax, eax |
| 85 | + dec eax |
| 86 | +.Lcrc_byte: |
| 87 | + cmp edx, edi |
| 88 | + je .Lcrc_done |
| 89 | + lea ecx, [edx+0x1] |
| 90 | + movzx edx, byte [edx] |
| 91 | + xor eax, edx |
| 92 | + push 0x08 |
| 93 | + pop edx ; 8 bits per byte |
| 94 | +.Lcrc_bit: |
| 95 | + mov ebx, eax |
| 96 | + and eax, 0x1 |
| 97 | + shr ebx, 1 |
| 98 | + neg eax |
| 99 | + and eax, 0xedb88320 |
| 100 | + xor eax, ebx |
| 101 | + dec edx |
| 102 | + jne .Lcrc_bit |
| 103 | + mov edx, ecx |
| 104 | + jmp .Lcrc_byte |
| 105 | +.Lcrc_done: |
| 106 | + not eax |
| 107 | + cmp eax, ebp |
| 108 | + jne .Lerror |
| 109 | + ; Jump to decompressed stage2 |
| 110 | + movzx eax, byte [esp+0xc] ; boot_drive |
| 111 | + mov ecx, dword [esp+0x10] ; pxe |
| 112 | + mov esp, esi |
| 113 | + xor ebp, ebp |
| 114 | + push ecx |
| 115 | + push eax |
| 116 | + push ebp |
| 117 | + push esi |
| 118 | + ret ; jump to 0xf000 |
| 119 | + ; Error: display message and cli/hlt |
| 120 | +.Lerror: |
| 121 | + mov edx, errmsg |
| 122 | + mov eax, 0xb8000 |
| 123 | +.Lerror_loop: |
| 124 | + movzx ecx, byte [edx] |
| 125 | + add eax, 0x2 |
| 126 | + inc edx |
| 127 | + or ch, 0x4f |
| 128 | + mov word [eax-0x2], cx |
| 129 | + cmp eax, 0xB8000 + errmsg.len * 2 |
| 130 | + jne .Lerror_loop |
| 131 | + cli |
| 132 | + hlt |
| 133 | + |
| 134 | +section .rodata progbits alloc noexec nowrite align=1 |
| 135 | + |
| 136 | +errmsg: db "limine integrity error" |
| 137 | +.len: equ $ - errmsg - 1 |
| 138 | + |
| 139 | +section .note.GNU-stack noalloc noexec nowrite progbits |
0 commit comments