; limlz: Copyright (C) 2026 Kamila Szewczyk ; limine: Copyright (C) 2019-2026 Mintsuki and contributors. ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions are met: ; ; 1. Redistributions of source code must retain the above copyright notice, this ; list of conditions and the following disclaimer. ; ; 2. Redistributions in binary form must reproduce the above copyright notice, ; this list of conditions and the following disclaimer in the documentation ; and/or other materials provided with the distribution. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE ; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. org 0x70000 bits 32 global _start _start: cld ; On stack (cdecl): [esp+4]=compressed_stage2, [esp+8]=stage2_size, ; [esp+12]=boot_drive (byte), [esp+16]=pxe mov ebx, dword [esp+0x4] ; compressed_stage2 mov ebp, dword [ebx] ; expected_crc = *(uint32_t *)compressed_stage2 lea edx, [ebx+0x4] ; ip = compressed_stage2 + 4 add ebx, dword [esp+0x8] ; ipe = compressed_stage2 + stage2_size mov edi, 0xf000 ; op = dest ; LZ decompression loop .Ltoken: movzx ecx, byte [edx] lea esi, [edx+0x1] mov eax, ecx ; save token shr ecx, 0x3 and ecx, 0xf ; literal length = (token >> 3) & 15 cmp ecx, 0xf jne .Llitcopy movzx ecx, byte [edx+0x1] lea esi, [edx+0x2] add ecx, 0xf ; length += extra byte + 15 .Llitcopy: rep movsb ; copy literals cmp esi, ebx jae .Lcrc ; if ip >= ipe, done test al, al jns .Loffset1 ; bit 7 clear => 1-byte offset lea edx, [esi+0x2] movzx esi, word [esi] ; 2-byte offset jmp .Lmatchlen .Loffset1: lea edx, [esi+0x1] movzx esi, byte [esi] ; 1-byte offset .Lmatchlen: and al, 0x7 cmp al, 0x7 je .Lmatchextra movzx eax, al jmp .Ldomatch .Lmatchextra: movzx eax, byte [edx] inc edx add eax, 0x7 ; matchlen += extra byte + 7 .Ldomatch: mov ecx, edi sub ecx, esi ; match = op - offset mov esi, ecx lea ecx, [eax+0x4] ; count = matchlen + 4 rep movsb ; copy match cmp edx, ebx ; guard against streams that end on a match jae .Lcrc jmp .Ltoken ; CRC32 verification .Lcrc: mov edx, 0xf000 ; ptr = dest mov esi, edx ; (also reused for esp later) xor eax, eax dec eax .Lcrc_byte: cmp edx, edi je .Lcrc_done lea ecx, [edx+0x1] movzx edx, byte [edx] xor eax, edx push 0x08 pop edx ; 8 bits per byte .Lcrc_bit: mov ebx, eax and eax, 0x1 shr ebx, 1 neg eax and eax, 0xedb88320 xor eax, ebx dec edx jne .Lcrc_bit mov edx, ecx jmp .Lcrc_byte .Lcrc_done: not eax cmp eax, ebp jne .Lerror ; Jump to decompressed stage2 movzx eax, byte [esp+0xc] ; boot_drive mov ecx, dword [esp+0x10] ; pxe mov esp, esi xor ebp, ebp push ecx push eax push ebp push esi ret ; jump to 0xf000 ; Error: display message and cli/hlt .Lerror: mov edx, errmsg mov eax, 0xb8000 .Lerror_loop: movzx ecx, byte [edx] add eax, 0x2 inc edx or ch, 0x4f mov word [eax-0x2], cx cmp eax, 0xB8000 + errmsg.len * 2 jne .Lerror_loop cli hlt errmsg: db "limine integrity error" .len: equ $ - errmsg