# HG changeset patch # User Pascal Bellard # Date 1355405607 -3600 # Node ID 7d300004a3b8e234416e611b55690985b1f2f23c # Parent 351e5fac42ac165d789b8aee4a32cdcb3782eeaf syslinux: add iso2exe diff -r 351e5fac42ac -r 7d300004a3b8 syslinux-extra/receipt --- a/syslinux-extra/receipt Wed Dec 12 16:59:24 2012 -0500 +++ b/syslinux-extra/receipt Thu Dec 13 14:33:27 2012 +0100 @@ -8,7 +8,7 @@ WANTED="syslinux" WEB_SITE="http://syslinux.zytor.com/" -DEPENDS="syslinux" +DEPENDS="syslinux posixovl" BUILD_DEPENDS="lzma" # Rules to gen a SliTaz package suitable for Tazpkg. @@ -24,5 +24,6 @@ cp -a $src/linux/syslinux-nomtools $fs/bin/syslinux cp -a $src/extlinux/extlinux $fs/bin cp -a $src/isohybrid.sh $fs/usr/bin/isohybrid + cp -a $src/iso2exe/iso2exe $fs/usr/bin/iso2exe chown root.root $fs/usr/share/boot/* $fs/bin/* $fs/usr/bin/* } diff -r 351e5fac42ac -r 7d300004a3b8 syslinux/receipt --- a/syslinux/receipt Wed Dec 12 16:59:24 2012 -0500 +++ b/syslinux/receipt Thu Dec 13 14:33:27 2012 +0100 @@ -8,7 +8,7 @@ TARBALL="$PACKAGE-$VERSION.tar.xz" WEB_SITE="http://syslinux.zytor.com/" WGET_URL="ftp://ftp.kernel.org/pub/linux/utils/boot/syslinux/$TARBALL" -BUILD_DEPENDS="kbd-base perl nasm" +BUILD_DEPENDS="kbd-base perl nasm dev86 lzma" DEPENDS="gpxe memtest" CONFIG_FILES="/boot/isolinux" @@ -16,6 +16,8 @@ compile_rules() { cd $src + cp -a $stuff/iso2exe . + make -C iso2exe cp $stuff/tools/isohybrid.sh . cp $stuff/tools/keytab-lilo.pl . cp $stuff/extra/md5sum.c com32/modules diff -r 351e5fac42ac -r 7d300004a3b8 syslinux/stuff/iso2exe/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syslinux/stuff/iso2exe/Makefile Thu Dec 13 14:33:27 2012 +0100 @@ -0,0 +1,34 @@ +GCC=gcc -m32 +BCC=bcc -ansi -O -0 -C-t +BCCFLAGS=-D__MSDOS__ -Md + +iso2exe: iso2exe.sh bootiso.bin lzcom.bin boot.com init + cp iso2exe.sh $@ + chmod +x $@ + lzma e boot.com boot.com.lzma -eos + ./$@ --build bootiso.bin lzcom.bin boot.com.lzma init + +OBJS = boot.o iso9660.o libdos.o bootlinux.o +boot.com: $(OBJS) + $(BCC) $(BCCFLAGS) -o $@ $(OBJS) + +boot.o: boot.c iso9660.h bootlinux.h libdos.h + +bootlinux.o: bootlinux.c iso9660.h bootlinux.h + +iso9660.o: iso9660.c iso9660.h + +libdos.o: libdos.c libdos.h + +lzcom.bin: lzcom.S unlzma.S + +%.o: %.c + $(BCC) $(BCCFLAGS) -A-l -A$*.lst -c -o $@ $< + +%.bin: %.S + $(GCC) -D__ASSEMBLY__ -Wa,-acghlnm=$*.lst -c -o $*.o $< + objcopy -O binary $*.o $@ + chmod +x $@ + +clean: + rm -f *.bin *.o *~ diff -r 351e5fac42ac -r 7d300004a3b8 syslinux/stuff/iso2exe/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syslinux/stuff/iso2exe/README Thu Dec 13 14:33:27 2012 +0100 @@ -0,0 +1,84 @@ +The iso2exe tool inserts a DOS .EXE header in an ISO image. +The ISO image can be launched by DOS : + +C:\> ren slitaz-5.0.iso slitaz.exe +C:\> slitaz + + +Why ? + +According to the SliTaz forum, some new users have problems to burn CD-ROM, +create USB Keys, and boot these devices with the BIOS. Others are lost during +installation process or partitionning. + +The slitaz.exe program boots the SliTaz ISO image with a text menu: + +- to start SliTaz in RAM (live) in graphic mode or text mode. + +- to install SliTaz "a la UMSDOS" in the \slitaz\ subdirectory. The simplest + way install to SliTaz. No partionning. No questions. + + +Usage: + + C:\> progname [mode] + +Default mode is menu. mode can be: + +- menu start with an interactive menu +- live launch SliTaz in RAM with graphics +- text launch SliTaz in RAM with text mode +- install SliTaz UMSDOS like installation + +If the progname name includes one of the supported mode, the according mode is +assumed. Example 'C:\> slitazlive.exe' starts SliTaz in RAM with graphics. + + +Implementation: + +ISO9660 format begins with 32Kb unused (16 sectors). Some programs may use it: + +- isolinux uses the first 512 bytes for hybrid iso boot (ISO image in a + partition). +- tazlito stores flavor extra infos at the 2nd Kb for 'tazlito iso2flavor'. + +The iso2exe tool moves the isolinux boot sector, installs its own boot sector +with a DOS .EXE header, and adds a DOS .COM Linux loader and an initramfs in +the end of the first 32Kb. + + +-----------------+ + | untouched | ISO9660 files including /boot/bzImage and /boot/rootfs* +32K +-----------------+ + | ISO initramfs | Live loader and UMSDOS like install script + +-----------------+ + | DOS .COM loader | Load bzImage, the last rootfs*.gz and the ISO initramfs + +-----------------+ + unused + +-----------------+ + | tazlito info | Flavor missing datas for 'tazlito iso2flavor' + 1K +-----------------+ + | isohybrid boot | Starts isolinux.bin +512 +-----------------+ + | iso2exe boot | Boot starts isohybrid (*), .EXE starts DOS .COM loader + 0 +-----------------+ + +* Eltorito boot (i.e. bootable CD-ROM by BIOS) is not concerned by iso2exe. + + +Limitations: + +- Real mode support only. VM86 is not (yet?) supported + +- Image/zImage format not supported. bzImage only. Can't boot memtest or gpxe. + +- The tiny Linux loader can't load more than 15Mb of files. (not really a + problem since many-in-1 ISO format). + +- The DOS Linux loader and the ISO initramfs must fit in ~30Kb. + +- Old Linux kernels don't support multiple initramfs load. They will not + find the /init.exe file. As workaround, you can add the "text" argument: + C:\> slitaz.exe text + +- The ISO image must include the files /boot/bzImage and /boot/rootfs* + diff -r 351e5fac42ac -r 7d300004a3b8 syslinux/stuff/iso2exe/boot.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syslinux/stuff/iso2exe/boot.c Thu Dec 13 14:33:27 2012 +0100 @@ -0,0 +1,162 @@ +#include +#include +#include +#include +#include +#include "iso9660.h" +#include "bootlinux.h" +#include "libdos.h" + +static void usage(char *iso) +{ + printf("Usage: %s [[@commands]|[kernel=] \ +[initrd=[,...]] [iso=] ...]\n\n\ +Defaults: %s @tazboot.cmd or %s kernel=bzImage auto\n\n\ +Examples for tazboot.cmd:\n\n\ + iso=\\isos\\slitaz-4.0.iso\n\ + kernel=boot/bzImage\n\ + initrd=boot/rootfs4.gz,boot/rootfs3.gz,boot/rootfs2.gz,boot/rootfs1.gz\n\ + rw root=/dev/null vga=normal autologin\n\n\ + kernel=\\slitaz\\vmlinuz\n\ + root=/dev/sda5 ro\n",iso,iso,iso); + exit(1); +} + +static void bootiso(char **iso) +{ + char *init = "rdinit=/init.exe", *mode="menu"; + char c, *s, rootfs[16], cmdline[256]; + int fd, restart; + unsigned long magic; + + if (isoreset(*iso) || isoopen("boot")) return; + if (iso[1] && !strcmp(mode = iso[1], "text")) + init = ""; + for (c = 0, restart = 1; isoreaddir(restart) == 0; restart = 0) { + if (strncmp(isofilename, "rootfs", 6) || c > s[6]) continue; + strcpy(rootfs, isofilename); + c = s[6]; + } + if (isoopen(mode)) + isoopen("bzImage"); + loadkernel(); + isoopen(rootfs); + loadinitrd(); + lseek(isofd, 28, SEEK_SET); + read(isofd, &magic, 4); + isofilesize = magic & 0xFFFF; + isofileofs = 0x8000 - isofilesize; + loadinitrd(); + close(isofd); + sprintf(cmdline,"rw root=/dev/null %s iso=%s magic=%lu mode=%s", + init, *iso, magic, mode); + bootlinux(cmdline); +} + +static int stricmp(char *ref, char *s) +{ + char c; + while (*ref) { + c = *s++; + if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; + c -= *ref++; + if (c) return c; + } + return 0; +} + +static char *iso; +static int fakeopen(char *file) +{ + if (iso) { + isoreset(iso); + return isoopen(file); + } + close(isofd); + isofd = open(file, O_RDONLY); + if (isofd != -1) { + isofileofs = 0; + isofilesize = LONG_MAX; + } + return isofd; +} + +static char args[2048]; +int main(int argc, char *argv[]) +{ + char *kernel, *initrd, *cmdline, *cmdfile, *s; + + argv[0] = progname(); + bootiso(argv); // iso ? parsing is /init.exe stuff ! + + chdirname(*argv); + cmdfile = "tazboot.cmd"; + kernel = "bzImage"; + initrd = NULL; + cmdline = "auto"; + if (argc > 1) { + if (argv[1][0] == '@') + cmdfile = argv[1] + 1; + else { + cmdfile = NULL; +#asm + push ds + push ds + pop es + push cs + pop ds + mov si, #0x82 + mov di, #_args + mov cx, #0x7E/2 + rep + movsw + pop ds +#endasm + } + } + if (cmdfile) { + int fd; + fd = open(cmdfile, O_RDONLY);; + if (fd != -1) { + read(fd, args, sizeof(args)); + close(fd); + for (s = args; s < args + sizeof(args) -1; s++) { + if (*s == '\r') *s++ = ' '; + if (*s == '\n') *s = ' '; + } + } + } + for (s = args; s < args + sizeof(args); s++) { + if (*s == ' ') continue; + if (stricmp("kernel=", s) == 0) + kernel = s + 7; + else if (stricmp("initrd=", s) == 0) + initrd = s + 7; + else if (stricmp("iso=", s) == 0) + iso = s + 4; + else { + cmdline = s; + break; + } + while (*s && *s != ' ') s++; + *s = 0; + } + if (fakeopen(kernel) == -1) + usage(argv[0]); + loadkernel(); + if (initrd) { + char *p, *q = initrd; + while (1) { + char c; + for (p = q; *p && *p != ','; p++); + c = *p; + *p = 0; + if (fakeopen(q) != -1) + loadinitrd(); + if (c == 0) + break; + q = ++p; + } + } + bootlinux(cmdline); +} diff -r 351e5fac42ac -r 7d300004a3b8 syslinux/stuff/iso2exe/bootiso.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syslinux/stuff/iso2exe/bootiso.S Thu Dec 13 14:33:27 2012 +0100 @@ -0,0 +1,262 @@ + .text + .code16 + .org 0 + +CODESZ = 0x8000 // 16 sectors = 32Kb +#define EXEADRS(x) x+0xE0 +#define EXESTR(x) x-0x20 + + .globl _start +_start: + decw %bp // Magic number: MZ + popw %dx + jmp start // Bytes on last page of file + .word (CODESZ+511)/512 // Pages in file + .word 0 // Relocations + .word (end_header-_start)/16 // Size of header in paragraphs + .word 4064-(CODESZ/16) // Minimum extra paragraphs needed + .word 4064-(CODESZ/16) // Maximum extra paragraphs needed + .word 0xFFF0 // Initial (relative) SS value + .word 0xFFFE // Initial SP value + .word 0 // Checksum + .word EXEADRS(fixseg) // Initial IP value + .word 0xFFF0 // Initial (relative) CS value + .word 0x001C // File address of relocation table + .word 0 // Overlay number +initramfssize: + .word 0 +id: + .word 0 +end_header: + +chksum: + .long 0 +comstart: + .word 0 + +/////////////////////// Master Boot Record code ////////////////////////////// + +start: + incw %bp + pushw %dx // restore SP + pushaw + movw %sp, %bp + pushf + pushw %ds + pushw %es + pushw $0 + popw %ds + call setreg + rep + movsw + ljmp $0, $0x0600+start2 + +setreg: + cld + pushw %ds + popw %es + movw $0x7C00, %si + movw %si, %bx + movw $0x0600, %di + movw $0x0100, %cx +return: + ret +start2: + movw $0x80, %dx +dxloop: + movw $1, %cx + movw $0x201, %ax + int $0x13 + jc next + call setreg + repe + cmpsw + je dxfound +next: + addb $0x7D, %dl // try every hard disk + andb $0x83, %dl // and floppy disk + cmpb $0x80, %dl + jnz dxloop +fail: + int $0x19 +dxfound: + movw %dx, 10(%bp) + movb $2, %cl // %ch = 0 + movw $0x201, %ax + int $0x13 + jc fail + cmpw $0xAA55, 0x7DFE + jne fail + popw %es + popw %ds + popf + popa + ljmp $0, $0x7C00 + +////////////////////////////// DOS EXE code /////////////////////////////////// + +no386: + .ascii "No 386+$" +noDOS3: + .ascii "No DOS 3.0+$" +rmPaging: + .ascii "Broken paging.$" +ERRvcpi: + .ascii "No VCPI 4.0+$" +chkerr: + .ascii "Broken ISO.$" +realmodemsg: + .ascii "Real mode\r$" +vm86modemsg: + .ascii "Vm86\r$" +help: + .ascii "Linux kickstarter.\r\n$" +fixseg: +#if 1 + movb $EXESTR(help), %dl + movw 0x82, %ax + cmpw $0x3F2F, %ax # /? + je abort +#endif + pushf + popw %ax + movw $0xF0F0, %cx + orb %ah, %ch + andb $0xF, %ah + + pushw %ax + popf + pushf + popw %ax + andb %cl, %ah + + cmp %cl, %ah + je NotSupported // 8086 family + + pushw %cx + popf + pushf + popw %ax + andb %cl, %ah + + jnz is386 // 80286 family +NotSupported: + movb $EXESTR(no386), %dl +abort: +puts: + movb $1, %dh + movb $9, %ah + int $0x21 + ret + +is386: + movb $0x30, %ah + int $0x21 + cmpb $3, %al + movb $EXESTR(noDOS3), %dl + jb abort + smsw %ax + andb $1, %al + jne tstvcpi + movl %cr0, %eax + movb $EXESTR(rmPaging), %dl + shll $1, %eax + jc abort + jmp realmode + +tstvcpi: + pushw %ds + pushw $0 + popw %ds + movw 0x67*4+2, %ds + std + movw $14, %si + lodsl + cmpl $0x30585858, %eax // 0XXX + lodsl + cld + popw %ds +NoVCPI: + movb $EXESTR(ERRvcpi), %dl +goabort: + jne abort + shll $8, %eax + cmpl $0x4D4D4500, %eax // [XQ]MME +#if 1 + movw $EXEADRS(CmdVCPI), %si +ChkVCPI: + jne NoVCPI + lodsb + shlw $8, %ax + je VersionVCPI + int $0x67 + jmp ChkVCPI +CmdVCPI: + .byte 0x40 // status + .byte 0xDE // vcpi present ? + .byte 0x46 // version + .byte 0 +VersionVCPI: + cmpb $0x40, %al // >= 4.0 ? + jb NoVCPI +#else + jne NoVCPI + movb $0x40, %ah // status + int $0x67 + testb %ah, %ah + jne NoVCPI + movb $0x46, %ah // version + int $0x67 + testb %ah, %ah + jne NoVCPI + cmpb $0x40, %al // >= 4.0 ? + jb NoVCPI + movw $0xDE00, %ax // vcpi present ? + int $0x67 + testb %ah, %ah + jne NoVCPI +#endif +realmode: + movw $0x100, %si + lodsl + xchgl %eax, %edx + orl %edx, %edx + jz skip + movw $0x7FDC/4, %cx +chklp: + lodsl + addl %eax, %edx + loop chklp + orl %edx, %edx + movb $EXESTR(chkerr), %dl + jne goabort +skip: + movb $EXESTR(realmodemsg), %dl + smsww %ax + andb $1, %al + jz isrealmode + movb $EXESTR(vm86modemsg), %dl +isrealmode: + call puts + movw EXEADRS(comstart), %ax // .com address + + cld + movw $moveend-move, %cx + movw $EXEADRS(move), %si + movw $0xC000, %di + jmp move2 + +move: + movb $0x80, %ch + xchgw %ax, %si + movw $0x0100, %di +move2: + pushw %di + rep + movsb + ret +moveend: + + .org 440 +//////////////////////////// partition table ////////////////////////////////// + diff -r 351e5fac42ac -r 7d300004a3b8 syslinux/stuff/iso2exe/bootlinux.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syslinux/stuff/iso2exe/bootlinux.c Thu Dec 13 14:33:27 2012 +0100 @@ -0,0 +1,258 @@ +#include +#include "iso9660.h" + +static unsigned version; +#define SETUPSECTORS 0x1F1 +#define ROFLAG 0x1F2 +#define SYSSIZE 0x1F4 +#define VIDEOMODE 0x1FA +#define BOOTFLAG 0x1FE +#define HEADER 0x202 +#define VERSION 0x206 +#define RMSWOFS 0x208 +#define RMSWSEG 0x20A +#define LOADERTYPE 0x210 +#define LOADFLAGS 0x211 +#define SYSTEMCODE 0x214 +#define INITRDCODE 0x218 +#define INITRDSIZE 0x21C +#define HEAPPTR 0x224 +#define CMDLINE 0x228 + +#define SETUP_SEGMENT 0x9000 +#define CMDLINE_OFFSET 0x9E00 + +#define BUFFERSZ 2*1024 +static char buffer[BUFFERSZ]; +static unsigned long initrd_addr, initrd_size; + +static int may_exit_dos = 1; +static void die(char *msg) +{ + printf("%s.\n", msg); + if (may_exit_dos) + exit(1); + while (1); +} + +static int vm86(void) +{ +#asm + smsw ax + and ax, #1 // 0:realmode 1:vm86 +#endasm +} + +static struct mem { + unsigned long base; + int align; +} kernelmem = { 0x100000, 0 }; + +#define initrdmem kernelmem + +static void movehi(void) +{ +#asm + pusha + xor di, di // 30 + mov cx, #9 // 2E..1E +zero1: + push di + loop zero1 + push dword [_kernelmem] // 1A p->base + push #-1 // 18 + push di // 16 + xor eax, eax + cdq + mov dx, ds + shl edx, #4 + mov ax, #_buffer + add edx, eax + push edx // 12 linear_address(buffer) + push #-1 // 10 + mov cl, #8 // 0E..00 +zero2: + push di + loop zero2 + mov ch, #BUFFERSZ/512 + push ss + pop es + mov si, sp + mov ax, #0x8793 + mov [si+0x15], al + xchg [si+0x1D], al + mov [si+0x1F], al // bits 24..31, doesn't work for me :( + int 0x15 + add sp, #0x30 + popa +#endasm +} + +static void load(struct mem *p, unsigned long size) +{ + if (vm86()) + die("Need real mode"); + switch (p->align) { + case 0: // kernel + p->align = 4096; + break; + case 4096: // first initrd + initrd_addr = p->base; + p->align = 4; + } + while (size) { + int n, s = sizeof(buffer); + for (n = 0; n < s; n++) buffer[n] = 0; + if (s > size) s = size; + n = isoread(buffer, s); + movehi(); + if (n != -1) { + p->base += n; + size -= n; + } + if (s != n) break; + } + initrd_size = p->base - initrd_addr; + p->base += p->align - 1; + p->base &= - p->align; +} + +static unsigned setupofs = 0; + +void movesetup(void) +{ +#asm + pusha + push #SETUP_SEGMENT + pop es + mov si, #_buffer + mov di, _setupofs + mov cx, #BUFFERSZ/2 + rep + movsw + mov _setupofs, di + popa +#endasm +} + +void loadkernel(void) +{ + unsigned setup, n = BUFFERSZ; + unsigned long syssize = 0; + + do { + isoread(buffer, n); + if (setupofs == 0) { + if (* (unsigned short *) (buffer + BOOTFLAG) != 0xAA55) + die("The kernel is not bootable"); + setup = (1 + buffer[SETUPSECTORS]) << 9; + if (setup == 512) setup = 5 << 9; + syssize = * (unsigned long *) (buffer + SYSSIZE) << 4; + version = * (unsigned short *) (buffer + VERSION); +#define HDRS 0x53726448 + if (* (unsigned long *) (buffer + HEADER) != HDRS) + version = 0; + if (!version || !(buffer[LOADFLAGS] & 1)) { +#undef ZIMAGE_SUPPORT /* Does not work... */ +#ifdef ZIMAGE_SUPPORT +#asm + pusha + mov cx, #0x8000 + mov es, cx + xor si, si + xor di, di + rep + movsw + push es + pop ds + push es + pop ss + popa + jmpi relocated, #0x8000 +relocated: +#endasm + kernelmem.base = 0x10000; + if (syssize > 0x70000) +#endif + die("Not a bzImage format"); + } + if (version < 0x204) + syssize &= 0x000FFFFFUL; + if (version) { +#ifdef REALMODE_SWITCH + * (unsigned short *) (buffer + RMSWOFS) = + realmode_switch; + * (unsigned short *) (buffer + RMSWSEG) = + getcs(); +#endif + * (unsigned short *) (buffer + HEAPPTR) = + 0x9B00; + // buffer[LOADFLAGS] |= 0x80; + * (unsigned short *) (buffer + LOADERTYPE) |= + 0x80FF; + } + } + movesetup(); + setup -= n; + n = (setup > BUFFERSZ) ? BUFFERSZ : setup; + } while (setup > 0); + + load(&kernelmem, syssize); +} + +void loadinitrd(void) +{ + if (version) + load(&initrdmem, isofilesize); +} + +void bootlinux(char *cmdline) +{ +#asm + push #SETUP_SEGMENT + pop es + mov eax, _initrd_addr + or eax, eax + jz no_initrd + mov di, #0x218 + stosd + mov eax, _initrd_size + stosd +no_initrd: +#endasm + if (cmdline) { + if (version <= 0x201) { +#asm + mov di, #0x0020 + mov ax, #0xA33F + stosw + mov ax, #CMDLINE_OFFSET + stosw +#endasm + } + else { +#asm + mov di, #0x0228 + mov eax, #SETUP_SEGMENT*16+CMDLINE_OFFSET + stosd +#endasm + } +#asm + xchg ax, di + mov si, .bootlinux.cmdline[bp] +copy: + lodsb + stosb + or al,al + jne copy +#endasm + } +#asm + push es + pop ds + push ds + pop ss + mov sp, #CMDLINE_OFFSET + jmpi 0, #0x9020 +#endasm +} diff -r 351e5fac42ac -r 7d300004a3b8 syslinux/stuff/iso2exe/bootlinux.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syslinux/stuff/iso2exe/bootlinux.h Thu Dec 13 14:33:27 2012 +0100 @@ -0,0 +1,6 @@ +#ifndef __BOOTLINUX_H +#define __BOOTLINUX_H +extern void loadkernel(void); +extern void loadinitrd(void); +extern void bootlinux(char *cmdline); +#endif diff -r 351e5fac42ac -r 7d300004a3b8 syslinux/stuff/iso2exe/init --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syslinux/stuff/iso2exe/init Thu Dec 13 14:33:27 2012 +0100 @@ -0,0 +1,251 @@ +#!/bin/sh + +DIALOG=dialog + +get() +{ + od -j $1 -N ${3:-4} -t u${3:-4} -An $2 +} + +getarg() +{ + sed "/$1=/!d;s/.*$1=\\([^ ]*\\).*/\\1/" /proc/cmdline +} + +gettazboot() +{ + echo "Create $(basename $1) ..." + O=$(($(get 36 /mnt/$ISO 2) - 0xE0)) + L=$((0x8000 - $(get 28 /mnt/$ISO 2) - $O)) + S=$((32+$L)) + P=$((($S+511)/512)) + E=$((4096-(32*$P))) + for i in 0x5A4D $(($S%512)) $P 0 2 $E -1 $((${2:-0}-16)) \ + -2 0 256 -16 28 0x6C53 0x5469 0x7A61; do + printf '\\\\x%02X\\\\x%02X' $(($i&255)) $((($i>>8)&255)) | \ + xargs echo -en + done > $1 + dd bs=1 count=$L skip=$(echo $O) if=/mnt/$ISO >> $1 2> /dev/null +} + +checkmagic() +{ + [ -s $1 ] && [ $(getarg magic) == $(get 28 $1) ] +} + +getiso() +{ + blkid | while read dev info ; do + case "$info" in + *dos*|*fat*|*ntfs*) + mount ${dev%:} /mnt + if checkmagic /mnt/$ISO; then + mount -o loop,ro /mnt/$ISO /media/cdrom + echo "Found $ISO on ${dev%:}" + break + fi + umount /mnt ;; + esac + done +} + +uncpio() +{ + echo "Extracting $(basename $1) ..." + case $(get 0 $1 2) in + *35615) zcat $1 ;; + *\ 93) unlzma -c $1 ;; + *) cat $1 ;; + esac | ( cd ${2:-/} ; cpio -idmu > /dev/null 2>&1 ) +} + +getuuid() +{ + dev=$(mount | sed '/ \/mnt /!d;s/ .*//;s|/dev/||;q') + blkid | sed "/$dev:/!d;s/.*UUID=.\\([^ ]*\\)\".*/\\1/" +} + +mkinitrd() +{ + echo "Create $(basename $1) ..." + for i in bin lib dev proc tmp mnt etc ; do + mkdir -p /tmp/fs/$i + done + for i in /dev/console /dev/null /dev/tty /dev/tty1 /dev/fuse \ + /dev/hd* /dev/sd* ; do + cp -a $i /tmp/fs$i + done + for i in /bin/busybox /usr/sbin/mount.posixovl $(which blkid); do + cp $(LD_TRACE_LOADED_OBJECTS=1 /lib/ld*.so $i | \ + sed 's|.*=> \(.*/lib/l[^ ]*\).*|\1|;/^\//!d') /tmp/fs/lib + cp $i /tmp/fs/bin + done + cp -a /lib/ld-* /tmp/fs/lib + for i in $(busybox | sed '/Current/,$!d'); do + ln -s busybox /tmp/fs/bin/${i%,} + done + ln -s /proc/mounts /tmp/fs/etc/mtab + cat > /tmp/fs/init < /dev/null + rm -rf /tmp/fs +} + +doinstall() +{ + mkdir /mnt/slitaz + mount.posixovl /mnt/slitaz || return + mkdir -p /mnt/slitaz/boot /mnt/slitaz/mnt/dos + for i in $(ls -r /media/cdrom/boot/rootfs*); do + uncpio $i /mnt/slitaz + done + for i in /media/cdrom/boot/bzImage /media/cdrom/boot/*pxe* \ + /media/cdrom/boot/isolinux/he* /media/cdrom/boot/isolinux/opt* \ + /media/cdrom/README /media/cdrom/boot/memtest* ; do + [ -s $i ] && cp $i /mnt/slitaz/boot + done + umount -d /media/cdrom + gettazboot /mnt/slitaz/boot/tazboot.exe + mkinitrd /mnt/slitaz/boot/initrd + cat > /mnt/slitaz/boot/tazboot.cmd <> /mnt/boot.ini <> /mnt/config.sys <] +[initrd=[,...]] [iso=] cmdline args ...]\n\n +Defaults: tazboot @tazboot.cmd or tazboot kernel=bzImage auto\n\n\ +Examples for tazboot.cmd:\n\n\ + iso=\\isos\\slitaz-4.0.iso\n\ + kernel=boot/bzImage\n\ + initrd=boot/rootfs4.gz,boot/rootfs3.gz,boot/rootfs2.gz,boot/rootfs1.gz\n\ + rw root=/dev/null autologin\n\n\ + kernel=\\slitaz\\vmlinuz root=/dev/sda5 ro\n\n +Unlike GRUB4DOS, it doesn't require unfragmented ISO image files.\n +" 24 78 + [ $? -eq 0 ] || return + gettazboot /mnt/tazboot.exe +} + +text() +{ + umount -d /media/cdrom + umount /mnt + umount /proc + exec /init +} + +live() +{ + n=0 + for i in $(ls -r /media/cdrom/boot/rootfs*); do + [ $((n++)) -eq 0 ] || uncpio $i + done + text +} + +reboot() +{ + umount -d /media/cdrom + umount /mnt + /sbin/reboot -f +} + +poweroff() +{ + umount -d /media/cdrom + umount /mnt + /sbin/poweroff -f +} + +[ -x /usr/sbin/mount.posixovl ] || +mv /usr/sbin/mount.posixovl.iso2exe /usr/sbin/mount.posixovl +mount -t proc /proc /proc +ISO="$(getarg iso | sed 's/.://;s|\\|/|g')" +getiso +case "$(basename $ISO | tr [A-Z] [a-z])$(getarg mode)" in +*install*) install ;; +*live*) live ;; +*text*) text ;; +esac + +while true; do + exec 3>&1 + value=`$DIALOG --clear \ + --title " Welcome to SliTaz " \ + --menu "\nPlease select" 15 70 7 \ + "live" "SliTaz RAM boot" \ + "text" "SliTaz RAM boot (text mode only)" \ + "install" "Hard disk installation" \ + "tazboot" "Get tazboot.exe Linux loader" \ + "reboot" "Restart the computer" \ + "poweroff" "Power off" \ + "ash" "Shell prompt" \ + 2>&1 1>&3` + retval=$? + exec 3>&- + [ $retval -eq 0 ] || continue + $value +done diff -r 351e5fac42ac -r 7d300004a3b8 syslinux/stuff/iso2exe/iso2exe.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syslinux/stuff/iso2exe/iso2exe.sh Thu Dec 13 14:33:27 2012 +0100 @@ -0,0 +1,73 @@ +#!/bin/sh +if [ "$1" == "--build" ]; then + shift + [ $(tar cf - $@ | wc -c) -gt $((32 * 1024)) ] && + echo "The file set $@ is too large (31K max) :" && + ls -l $@ && exit 1 + cat >> $0 < /dev/null +} + +store() +{ + n=$2; for i in $(seq 8 8 ${4:-16}); do + printf '\\\\x%02X' $(($n & 255)) + n=$(($n >> 8)) + done | xargs echo -en | ddq bs=1 conv=notrunc of=$3 seek=$(($1)) +} + +main() +{ + case "$1" in + --get) shift + uudecode | unlzma | tar xOf - $@ + exit ;; + *) cat > /dev/null + esac + + [ ! -s "$1" ] && echo "usage: $0 image.iso" 1>&2 && exit 1 + case "$(od -N 2 -t x2 -An $1)" in + *5a4d) echo "The file $1 is already an EXE file." 1>&2 && exit 1;; + *0000) [ -x /usr/bin/isohybrid ] && isohybrid $1 + esac + [ ! -x /usr/sbin/mount.posixovl ] && + echo "No file mount.posixovl. Abort." 1>&2 && exit 1 + + echo "Move syslinux hybrid boot record..." + ddq if=$1 bs=512 count=1 | ddq of=$1 bs=512 count=1 seek=1 conv=notrunc + + echo "Insert EXE boot record..." + $0 --get bootiso.bin | ddq of=$1 conv=notrunc + + # keep the largest room for the tazlito info file + TMP=/tmp/iso2exe$$ + mkdir -p $TMP/usr/sbin + cp /usr/sbin/mount.posixovl $TMP/usr/sbin/mount.posixovl.iso2exe + $0 --get init > $TMP/init.exe + chmod +x $TMP/init.exe $TMP/usr/sbin/mount.posixov* + ( cd $TMP ; ls init.exe usr/sbin/mount.posixov* | cpio -o -H newc ) | \ + lzma e $TMP/rootfs.gz -si 2> /dev/null + SIZE=$(wc -c < $TMP/rootfs.gz) + store 28 $SIZE $1 + OFS=$(( 0x8000 - $SIZE )) + printf "Add rootfs.gz file at %04X...\n" $OFS + cat $TMP/rootfs.gz | ddq of=$1 bs=1 seek=$OFS conv=notrunc + rm -rf $TMP + SIZE=$($0 --get lzcom.bin boot.com.lzma | wc -c) + OFS=$(( $OFS - $SIZE )) + printf "Add DOS boot file at %04X...\n" $OFS + $0 --get lzcom.bin boot.com.lzma | ddq of=$1 bs=1 seek=$OFS conv=notrunc + store 36 $(($OFS+0xE0)) $1 + store 30 ${RANDOM:-0} $1 +} + +main $@ < +#include +#include +#include "iso9660.h" +#define __ROCKRIDGE + +char *isofilename; +unsigned long isofileofs, isofilesize; +unsigned short isofilemod; +int isofd; + +#define SECTORSZ 2048 +#define SECTORBITS 11 +static char buffer[SECTORSZ]; + +static int readsector(unsigned long offset) +{ + return (lseek(isofd, offset, SEEK_SET) != -1 + && read(isofd, buffer, SECTORSZ) == SECTORSZ); +} + +int isoread(char *data, unsigned size) +{ + int get, n; + + if (size > isofilesize) + size = isofilesize; + if (lseek(isofd, isofileofs, SEEK_SET) == -1) + return -1; + for (get = size; get; get -= n, data += n) { + n = read(isofd,data,get); + if (n < 0) + return n; + if (n == 0) + break; + isofileofs += n; + isofilesize -= n; + } + return size - get; +} + +static unsigned long isodirofs, isodirsize; +int isoreset(char *name) +{ + if (name) + isofd = open(name, O_RDONLY); + if (!readsector(16UL * 2048) || strncmp(buffer+1,"CD001",5)) + return -1; + isodirofs = * (unsigned long *) (buffer + 0x9E); + isodirofs <<= SECTORBITS; + isodirsize = * (unsigned long *) (buffer + 0xA6); + return 0; +} + +int isoreaddir(int restart) +{ + static unsigned long pos, dirofs, dirsize; + static char dots[] = ".."; + int size, n; +#ifdef __ROCKRIDGE + char *endname; +#endif + + if (restart) { + dirofs = isodirofs; + dirsize = isodirsize; + pos = SECTORSZ; + } + if (pos >= SECTORSZ) { + if (dirsize < SECTORSZ) return -1; + readsector(dirofs); + dirofs += SECTORSZ; + dirsize -= SECTORSZ; + pos = 0; + } + size = * (short *) (buffer + pos); + if (size == 0) + return -1; + isofileofs = (* (unsigned long *) (buffer + pos + 2)) << SECTORBITS; + isofilesize = * (unsigned long *) (buffer + pos + 10); + isofilemod = (buffer[pos + 25] & 2) ? 0040755 : 0100755; +#ifdef __ROCKRIDGE + endname = NULL; + n = (buffer[pos + 32] + pos + 34) & -2; + do { + int len = buffer[n + 2]; + switch (* (short *) (buffer + n)) { + case 0x4D4E: // NM + isofilename = buffer + n + 5; + endname = buffer + n + len; + break; + case 0x5850: // PX + isofilemod = * (short *) (buffer + n + 4); + break; + } + n += len; + } + while (n + 2 < pos + size); + if (endname) + *endname = 0; + else +#endif + { + isofilename = buffer + pos + 33; + switch (* (short *) (isofilename - 1)) { + case 0x0101: + isofilename = dots; + break; + case 0x0001: + isofilename = dots + 1; + break; + default: + n = isofilename[-1]; + if (* (short *) (isofilename + n - 2) == 0x313B) + n -= 2; // remove ;1 + if (isofilename[n - 1] == '.') n--; + isofilename[n] = 0; + } + } + pos += size; + return 0; +} + +#define IS_DIR(x)( ((x) & ~0777) == 040000) +int isoopen(char *name) +{ + int restart; + char *s, c; + + while (*name == '/') { + name++; + isoreset(NULL); + } + s = name; + while (1) { + while (*s && *s != '/') s++; + c = *s; + *s = 0; + for (restart = 1; isoreaddir(restart) == 0; restart = 0) { + if (strcmp(name, isofilename)) continue; + if (IS_DIR(isofilemod)) { + isodirofs = isofileofs; + isodirsize = isofilesize; + if (c) { + *s++ = c; + name = s; + goto next; + } + } + return 0; + } + return -1; + next: ; + } +} diff -r 351e5fac42ac -r 7d300004a3b8 syslinux/stuff/iso2exe/iso9660.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syslinux/stuff/iso2exe/iso9660.h Thu Dec 13 14:33:27 2012 +0100 @@ -0,0 +1,12 @@ +#ifndef __ISO9660_H +#define __ISO9660_H +extern char *isofilename; +extern unsigned long isofileofs, isofilesize; +extern unsigned short isofilemod; +extern int isofd; +extern int isoreset(char *name); +extern int isoopen(char *name); +extern int isoreaddir(int restart); +extern int isoread(char *data, unsigned size); +#define isolabel() do { isofileofs=0x8028; isofilesize=32; } while (0) +#endif diff -r 351e5fac42ac -r 7d300004a3b8 syslinux/stuff/iso2exe/libdos.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syslinux/stuff/iso2exe/libdos.c Thu Dec 13 14:33:27 2012 +0100 @@ -0,0 +1,130 @@ +#include "libdos.h" + +char *progname(void) +{ +#asm + .bss +._name lcomm 80 + .text + push es + seg cs + mov es, [0x2C] + mov cx, #-1 + xor di, di + xor al, al +loop1: + repne + scasb + scasb + jne loop1 + lea si, [di+2] + push ds + push ds + push es + pop ds + pop es + mov di, ._name + push di +loop2: + lodsb + stosb + or al, al + jnz loop2 + pop ax + pop ds + pop es +#endasm +} + +#ifdef __SLEEP +void sleep(int seconds) +{ + unsigned long n; + + n = (seconds * 182) / 10; +#asm + push es + push #0 + pop es + mov di, #0x46C +sleeplp: + mov cx, #0x8000 + or dx, dx + jne siok + mov cx, ax + jcxz done +siok: + sub ax, cx + sbb dx, #0 + seg es + add cx, [di] +zzz: + seg es + cmp cx, [di] + jne zzz + jmp sleeplp +done: + pop es +#endasm +} +#endif + +int chdirname(char *path) +{ +#asm + pop ax + pop bx + push bx + push ax + cmp byte ptr [bx+1], #0x3A + jne nodisk + mov dl, [bx] + or dl, #0x20 + sub dl, #0x61 + mov ah, #0x0E + push bx + int 0x21 + pop bx + inc bx + inc bx +nodisk: + mov dx, bx + xor cx, cx +next: + mov al, [bx] + cmp al, #0x5C + jne tsteos + mov cx, bx +tsteos: + inc bx + or al, al + jnz next + cbw + jcxz quit + mov bx, cx + push [bx] + mov [bx], al + push bx + call chdir + pop bx + pop [bx] +quit: + ret + +// int chdir(char *path) +_chdir: + pop ax + pop dx + push dx + push ax +chdir: + stc + mov ax, #0x713B + int 0x21 + jnc chdireturn + mov ah, #0x3B + int 0x21 +chdireturn: + sbb ax, ax +#endasm +} diff -r 351e5fac42ac -r 7d300004a3b8 syslinux/stuff/iso2exe/libdos.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syslinux/stuff/iso2exe/libdos.h Thu Dec 13 14:33:27 2012 +0100 @@ -0,0 +1,13 @@ +#ifndef __LIBDOS_H +#define __LIBDOS_H +#undef __SLEEP +# ifdef __MSDOS__ +// extern void sleep(int seconds); +extern char *progname(void); +extern int chdir(char *path); +extern int chdirname(char *path); +# else +#define progname() argv[0] +#define chdirname(x) chdir(dirname(x)) +# endif +#endif diff -r 351e5fac42ac -r 7d300004a3b8 syslinux/stuff/iso2exe/lzcom.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syslinux/stuff/iso2exe/lzcom.S Thu Dec 13 14:33:27 2012 +0100 @@ -0,0 +1,36 @@ + .text + .code16 + +ORGCOM = 0x100 +STKSZ = 0x4000 // unlzma needs 16Kb +CODESZ = (0x10000-STKSZ)/2 // max < 16 sectors = 32Kb + + .org 0 + + .globl _start +_start: + cld + movw $packedcode-unpack, %ax + movw $packedcode+ORGCOM, %si + movw $-STKSZ-CODESZ, %di + subw %ax, %di + pushw %di + movw $CODESZ/2, %cx + rep + movsw // packed code + movw $unpack+ORGCOM, %si + movw %di, %bx + xchgw %ax, %cx + rep + movsb // decompressor + movw $ORGCOM, %di + popw %si + pushw %di + pushw %bx + ret + +unpack: +#define FLAT16 +#include "unlzma.S" + +packedcode: diff -r 351e5fac42ac -r 7d300004a3b8 syslinux/stuff/iso2exe/unlzma.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syslinux/stuff/iso2exe/unlzma.S Thu Dec 13 14:33:27 2012 +0100 @@ -0,0 +1,826 @@ +// #define RC_NORMALIZE if (Range < kTopValue) { Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } +// +// #define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) +// #define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; +// #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; +// +//#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ +// { UpdateBit0(p); mi <<= 1; A0; } else \ +// { UpdateBit1(p); mi = (mi + mi) + 1; A1; } +// +// #define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) +// +// #define RangeDecoderBitTreeDecode(probs, numLevels, res) \ +// { int i = numLevels; res = 1; \ +// do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \ +// res -= (1 << numLevels); } +/* + * Compression with : lzma e src dst -eos -pb2 -lp0 -lc3 + */ + +#define PROP_PB 2 +#define PROP_LP 0 +#define PROP_LC 3 +#define PROPS (PROP_LC+(PROP_LP*9)+(PROP_PB*45)) + +// static const Byte *Buffer; +// static UInt32 bound, Code, Range; + +/* + * Buffer register DS:SI + * all var based ws=ss:bp + */ + +rep0 = -4 // long +rep1 = rep0-4 // long +rep2 = rep0-8 // long +rep3 = rep0-12 // long +state = -17 // byte, 0..11 +posState = state-1 // byte, 0..15 +posState2 = posState-1 // byte, 0..15 +scratched = rep0-16 // byte = 1 +Code = -24 // long +outStream = -28 // long +nowPos = outStream // long +Range = Code-8 // long +#define LOCALS 32 + +// int LzmaDecode(CLzmaDecoderState *vs, +// const unsigned char *inStream, +// unsigned char *outStream) +// { +// CProb *p = vs->Probs; +// SizeT nowPos = 0; +// #define posStateMask = (1 << (vs->Properties.pb)) - 1; +// #define literalPosMask = (1 << (vs->Properties.lp)) - 1; +// int lc = vs->Properties.lc, state = 0, len = 0; +// UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; +// +// { +// UInt32 i, numProbs = Literal /*1846*/ +// + ((UInt32)LZMA_LIT_SIZE /*768*/ << (lc + vs->Properties.lp)); +// for (i = 0; i < numProbs; i++) p[i] = kBitModelTotal /*2048*/ >> 1; + +#define WS (1846+(768<<(PROP_LC+PROP_LP))) +#if (WS+WS+LOCALS) >= 65000 +/* MAX WS = (1846+(768<<(8+4))) > 3MB! */ +#error invalid (lc,lp,pb) : out of memory +#endif + +ws1 = WS +ws2 = ws1*2 +ws = ws2+LOCALS+15 + +#ifndef FLAT16 +#define INC incl +#else +#define INC incw +#endif +#ifndef FLAT32 +#define AX %ax +#define BX %bx +#define CX %cx +#define DX %dx +#define SI %si +#define DI %di +#define BP %bp +#define SP %sp +#define CWD cwd +#else +#define AX %eax +#define BX %ebx +#define CX %ecx +#define DX %edx +#define SI %esi +#define DI %edi +#define BP %ebp +#define SP %esp +#define CWD cdq +#endif +/* + * LzmaDecode: +#ifndef FLAT32 + * input ds:si=inStream, es:di=outStream + * output outStream[], ds:si, es:di + .code 16 +#else + * input esi=inStream, edi=outStream + * output outStream[], esi, edi + .code 32 +#endif + */ + + mov $ws1, CX +lzd1: + pushw $2048/2 + loop lzd1 + mov SP, BP + movb $((LOCALS+3)/4)*2, %cl +initlocals: + pushl $1 + loop initlocals + +#if !defined(FLAT32) && !defined(FLAT16) + movb $4, %cl + movw %es, %bx + shrw %cl, %bx + movw %es, %dx + shlw %cl, %dx + addw %dx, %di + movw %di, outStream(%bp) + adcb %bh, outStream+2(%bp) + incw %cx +#else + movb $5, %cl + mov DI, outStream(BP) +#endif + +// Byte previousByte = 0; + xor BX, BX + +// #define RC_INIT(buffer) +// Buffer = buffer; Code = 0; Range = 0xFFFFFFFF; +// { int i; for(i=0; i<5; i++) { Code = (Code<<8) | RC_READ_BYTE; }} +// } +// RC_INIT(inStream); + + add $13, SI // skip header +setrep: + call RC_LOAD_BYTE + decb Range(BP) + loop setrep + +lzdmainlp: +// while(1) { +// CProb *prob; +// int posState = (int)((nowPos) & posStateMask); +// +// prob = p + IsMatch /*0*/ + (state << kNumPosBitsMax /*4*/) + posState; +// if (Bit0(prob)) { /* char */ + + xor DX, DX + call Bit1state // Bit1(dx + (state << kNumPosBitsMax /*4*/) + posState) + mov $state, DI + jc lzdstring + +// prob = p + Literal /*1846*/ + (LZMA_LIT_SIZE /*768*/ * +// ((((nowPos) & literalPosMask) << lc) + (previousByte >> (8 - lc)))); + +#if PROP_LC != 0 + shrb $8-PROP_LC, %bl +#endif + +#if PROP_LP != 0 + movb posState2(BP), %dl + shl $PROP_LC, DX + movb $0, %bh + add BX, DX +#endif + + movb $3, %ah + mul BX // dx = 3*bh + add $1846, AX + +// int symbol = 1; + + CWD + inc DX // symbol = 1 + xchg AX, CX // save prob + +// if (state >= kNumLitStates /*7*/) { /* previous was string */ +// if (state < 4) state = 0; + +lzd6z: + subb $3, (BP, DI) + +// if (state < 4) state = 0; + + jnc lzd6 + movb %dh, (BP, DI) // %dh = 0 + +lzd6: +// else if (state < 10) state -= 3; + + cmpb $10-3, (BP, DI) + +// else state -= 6; + + jnb lzd6z + cmpb $7-3-1, (BP, DI) + jbe lzd3 + +// int matchByte = outStream[nowPos - rep0]; + + call DicoRep02ESDI // %bl = outStream[nowPos - rep0]; + +// do { +// int bit; +// CProb *probLit; +// matchByte <<= 1; bit = (matchByte & 0x100); + + movb $1, %bh +lzd4: + shlb $1, %bl // matchByte <<= 1 + sbb DI, DI // save bit=C + +// probLit = prob + 0x100 + bit + symbol; + + mov CX, AX // restore prob + adcb %bh, %ah // + bit + 0x100 + +// RC_GET_BIT2(probLit, symbol, if (bit) break, if (!bit) break) + + call Bit1axdx // C,%ax = Bit1(prob+%ax) + rclb $1, %dl // symbol <<= 1; symbol |= C + jc lzd5 // if symbol >= 0x100 + cmp DI, AX + jz lzd4 // if bit == Bit1(prob+%ax) + +// } while (symbol < 0x100); +// } +lzd3: +// while (symbol < 0x100) { +// CProb *probLit = prob + symbol; +// RC_GET_BIT(probLit, symbol) +// } + + xor BX, BX + jmp lzd4 +lzd5: + +// outStream[nowPos++] = previousByte = (Byte)symbol; + + xchg AX, DX + call outchar // %bl = outStream[nowPos++] = %al; + jmp lzdmainlp + +// } + +lzdstring: + mov $1, CX + +// else { /* string */ +// prob = p + IsRep /*192*/ + state; + + movb $192, %dl + addb (BP, DI), %dl + mov $rep0, DI + +// if (Bit0(prob)) { + + call Bit1dx // Bit1(prob) + jc lzd8 + +// rep3 = rep2; rep2 = rep1; rep1 = rep0; +// state = (state < kNumLitStates /*7*/) ? 0 : 3; + + stc + +// prob = p + LenCoder /*818*/; + + mov $818, DX + +// } + + jmp lzd11a + +// else { +lzd8: +// prob += kNumStates /*12*/; +// if (Bit0(prob)) { + call Bit1dx12 // prob += 12; Bit1(prob) + jc lzd11 +// prob = p + IsRep0Long /*240*/ + (state << kNumPosBitsMax /*4*/) +// + posState; + movb $240, %dl // dh=0 + +// if (Bit0(prob)) { + + call Bit1state // Bit1(dx + (state << kNumPosBitsMax /*4*/) + posState) + jc lzd12 + +// // if (nowPos == 0) return LZMA_RESULT_DATA_ERROR; +// state = (state < kNumLitStates /*7*/) ? 9 : 11; + + movb $9, %dl + +// len++; goto string; + jmp lzd13string // ax = 0 +// } +// } +// else { +lzd11: +// UInt32 distance = rep1; +// prob += kNumStates /*12*/; +// if (!Bit0(prob)) { + + call Bit1dx12 // prob += 12; Bit1(prob) + jnc lzd11z + +// prob += kNumStates /*12*/; +// if (Bit0(prob)) distance = rep2; + + call Bit1dx12 // prob += 12; Bit1(prob) +lzd11a: + adcb %cl, %cl + +// else { distance = rep3; rep3 = rep2; } +// rep2 = rep1; +// } +// rep1 = rep0; rep0 = distance; + +lzd11z: + shl $2, CX // 8->32 bits + sub CX, DI // &rep[cx] + movl (BP, DI), %eax +rotreplp: + movb 4(BP, DI), %bl + movb %bl, (BP, DI) + inc DI + loop rotreplp + testb %dh, %dh + jnz lzd10 + movl %eax, (BP, DI) + +// } +lzd12: +// state = (state < kNumLitStates /*7*/) ? 8 : 11; + + movb $0x08, %cl + +// prob = p + RepLenCoder /*1332*/; + + mov $1332, DX + +// } +lzd10: + push CX // CX = 0 + +// { /* get len */ +// int numBits, offset; +// CProb *probLen = prob + LenChoice /*0*/; +// numBits = kLenNumLowBits /*3*/; + + movb $8, %cl // numBits : 3,3,8 + +// if (Bit0(probLen)) { + + call Bit1dx // Bit1(prob) + xchg AX, BX + inc DX + jnc lzd15 // bx=0 + +// probLen = prob + LenLow/*2*/ + (posState << kLenNumLowBits/*3*/); +// offset = 0; +// } +// else { +// probLen = prob + LenChoice2 /*1*/; + + call Bit1dx // Bit1(prob) + add AX, BX + +#if PROP_PB != 0 + inc AX // ah=0 +#endif + jc lzd16 // %ax=0, %bx=-2 +lzd15: +#if PROP_PB != 0 + movb $8, %al + mulb posState(BP) +#endif + +// if (Bit0(probLen)) { +// probLen = prob + LenMid/*130*/ + (posState << kLenNumMidBits/*3*/); + + movb $3, %cl // numBits : 3,3,8 +lzd16: +#if PROP_PB != 0 + add $2-128-1, AX // probLen : 2,130,258 +#else + mov $2-128-1, AX // probLen : 2,130,258 +#endif + add DX, AX + mov $-8+1, DX // offset : 0,8,16 +lzdargslp: + add $8, DX + add $128, AX + inc BX + jle lzdargslp // leave with bx=1 + +// offset = kLenNumLowSymbols /*8*/; +// //numBits = kLenNumMidBits /*3*/; +// } +// else { +// probLen = prob + LenHigh /*258*/; +// offset = kLenNumLowSymbols /*8*/ + kLenNumMidSymbols /*8*/; +// numBits = kLenNumHighBits /*8*/; +// } +// } +// RangeDecoderBitTreeDecode(probLen, numBits, len); len += offset; + + push DX + call RangeDecoder // %ax=probs, %cx=numLevels, %ax=res + pop DX + add DX, AX // offset + pop DX // 0 +lzd13string: + push AX + +// state = (state < kNumLitStates /*7*/) ? dl : dl|3; + + movb $7, %cl + cmpb %cl, state(BP) + jb new_state + orb $3, %dl +new_state: + movb %dl, state(BP) + +// } /* get len */ +// if (state < 4) { + + cmpb $4-1, %dl + ja lzd19 + +// int posSlot; +// state += kNumLitStates /*7*/; + + addb %cl, state(BP) + +// prob = p + PosSlot /*432*/ + (((len < kNumLenToPosStates /*4*/) ? +// len : kNumLenToPosStates - 1) << kNumPosSlotBits /*6*/); + + cmp $4+1, AX + jb lzd21 + mov $3+1, AX + +lzd21: + + dec CX // cx = 6 + shl %cl, AX + add $432-64, AX + +// RangeDecoderBitTreeDecode(prob, kNumPosSlotBits /*6*/, posSlot); + + call RangeDecoder // %ax=probs, %cx=numLevels, %ax=res + +// if (posSlot >= kStartPosModelIndex /*4*/) { +// int numDirectBits = ((posSlot >> 1) - 1); + +#ifndef FLAT32 + movw %cx, 2(%bp, %di) // %cx = 0 +#endif + mov AX, (BP, DI) + mov AX, CX + shrw $1, CX + dec CX + cmpb $4, %al + jb lzd22 + +// rep0 = (2 | ((UInt32)posSlot & 1)); + + andb %bl, (BP, DI) // %bx=1 + orb $2, (BP, DI) + +// if (posSlot < kEndPosModelIndex /*14*/) { + + cmpb $14, %al + jnb lzd23 + +// rep0 <<= numDirectBits; + + neg AX + shll %cl, (BP, DI) + add (BP, DI), AX + +// prob = p + SpecPos /*688*/ + rep0 - posSlot - 1; + + add $687, AX + jmp lzd24 + +// } +// else { +lzd23: +// numDirectBits -= kNumAlignBits /*4*/; +// do { +// RC_NORMALIZE; Range >>= 1; rep0 <<= 1; +// if (Code >= Range) { Code -= Range; rep0 |= 1; } + +lzd23z: + call RC_NORMALIZE + shrl $1, Range(BP) + movl Range(BP), %eax + cmpl Code(BP), %eax + ja lzd25 + subl %eax, Code(BP) + stc +lzd25: + rcll $1, (BP, DI) + +// } while (--numDirectBits != 0); + + cmpb $4+1, %cl + loopne lzd23z + +// prob = p + Align /* 802 */; numDirectBits = kNumAlignBits /*4*/; +// rep0 <<= numDirectBits; + + shll %cl, (BP, DI) + mov $802, AX +// } + +lzd24: + call RangeDecoder // %ax=probs, %cx=numLevels, %ax=res + +// { +// int i = 1, mi = 1; +// do { +// CProb *prob3 = prob + mi; +// RC_GET_BIT2(prob3, mi, ; , rep0 |= i); + + orb %dh, (BP, DI) // update rep0 with DirectBits + +// i <<= 1; +// } while(--numDirectBits != 0); +// } +// } else rep0 = posSlot; +lzd22: +// if (++rep0 == (UInt32)(0)) break; /* EOF */ + + incl (BP, DI) + +lzd19: + pop CX + jz lzdone + +// } +// len += kMatchMinLen;/*2*/ + + inc CX + +// string: // if (rep0 > nowPos) return LZMA_RESULT_DATA_ERROR; +// do { +lzd13z: +// previousByte = outStream[nowPos - rep0]; +// outStream[nowPos++] = previousByte; + + call outcharDico // %bl = outStream[nowPos++] = outStream[nowPos - rep0] + +// } while(--len != 0); + + loop lzd13z + +// } /* char/string */ +// } + + jmp lzdmainlp + +lzdone: +// //RC_NORMALIZE; +// //*inSizeProcessed = (SizeT)(Buffer - inStream); *outSizeProcessed = nowPos; +// return LZMA_RESULT_OK; + call Dico2ESDI // set es & di (rep0 = 0) + lea ws2(BP), SP // dealloc + ret +// } + +// al = outStream[nowPos - rep0]; + +/* + * output es:di, al + * scratch bh, cl, flags + */ + +DicoRep02ESDI: + stc + +// bl = outStream[nowPos]; + +/* + * output es:di, bl + * scratch bh, cl, flags + */ + +Dico2ESDI: +#if !defined(FLAT32) && !defined(FLAT16) + movl nowPos(%bp), %ebx + jnc Dico2ESDIz + subl rep0(%bp), %ebx +Dico2ESDIz: + movw %bx, %di + xorw %bx, %bx + shrl $4, %ebx + movw %bx, %es + movb %es:(%di), %bl +#else + mov nowPos(BP), DI + jnc Dico2ESDIz + sub rep0(BP), DI +Dico2ESDIz: + movb (DI), %bl +#endif + ret + +outcharDico: + +// bl = outStream[nowPos++] = outStream[nowPos - rep0] + +/* + * output es:di, bl + * update nowPos + * scratch ax, dx, bh, cl, flags + */ + + call DicoRep02ESDI // %bl = outStream[nowPos - rep0] + xchg AX, BX +outchar: + +// bl = outStream[nowPos++] = previousByte = al; + +/* + * output bl + * update nowPos + * scratch ax, dx, bh, di, cl, flags + */ + + clc + call Dico2ESDI + stosb + xchg AX, BX // previous byte + +// int posState = (int)((nowPos) & posStateMask); + +#if PROP_PB != 0 && PROP_LP != 0 + addw $0x0101, posState2(BP) + andb $(((1 << PROP_PB) -1)<<8)+((1 << PROP_LP) -1), posState2(BP) +#else +# if PROP_PB != 0 + incb posState(BP) + andb $((1 << PROP_PB) -1), posState(BP) +# endif +# if PROP_LP != 0 + incb posState2(BP) + andb $((1 << PROP_LP) -1), posState2(BP) +# endif +#endif + INC nowPos(BP) + ret + +// +// #define RC_NORMALIZE if (Range < kTopValue) +// { Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } + +/* + * update Range, Code, ds:si + * scratch flags + */ + +RC_NORMALIZE: + cmpb $0, Range+3(BP) + jne RC_NORMALIZE_1 +RC_LOAD_BYTE: + push AX + shll $8, Range(BP) + shll $8, Code(BP) +#if !defined(FLAT32) && !defined(FLAT16) + testw %si, %si + jns RC_READ_BYTE + movw %ds, %ax + incw %ax + movw %ax, %ds + addw $-16, %si +RC_READ_BYTE: +#endif + lodsb + movb %al, Code(BP) + pop AX +RC_NORMALIZE_1: + ret + +// Bit1(dx + (state << kNumPosBitsMax /*4*/) + posState) + +Bit1state: + movb $16, %al + mulb state(BP) +# if PROP_PB != 0 + addb posState(BP), %al +# endif +Bit1axdx: + add DX, AX + jmp Bit1 + +// prob += 12; Bit1(prob) + +Bit1dx12: + add $12, DX +Bit1dx: + mov DX, AX + +// static int Bit1(CProb *p) + +Bit1: +/* + * input ax=p + * output C, ax + * update bound, Range, Code, ds:si + * scratch flags + */ + +// { +// RC_NORMALIZE; + + call RC_NORMALIZE // kill %ax, update %si + + pushal + + xchg AX, DI + add DI, DI // short * + + +// bound = (Range>>kNumBitModelTotalBits /*11*/) * *(p); + + movl Range(BP), %eax + shrl $11, %eax + movzwl (BP, DI), %edx + mull %edx + +// if (Code < bound) { + + cmpl Code(BP), %eax + jbe Bit1_1 + +// Range = bound; + + movl %eax, Range(BP) + +// *(p) += (kBitModelTotal /*2048*/ - *(p)) >> kNumMoveBits /*5*/; + + movw $2048, %ax + +// return 0; + + jmp Bit1_2 + +// } +// else { + +Bit1_1: + +// Range -= bound; Code -= bound; + + subl %eax, Range(BP) + subl %eax, Code(BP) + +// *(p) -= (*(p)) >> kNumMoveBits /*5*/; + + movw $31, %ax + +// return 1; + + stc +Bit1_2: + pushf + subw (BP, DI), %ax + sarw $5, %ax + addw %ax, (BP, DI) + popf + popal + sbb AX, AX + +// } +// } + + ret + +RangeDecoder: + +/* + * input ax=probs cx=numLevels (< 8) bx=1 + * output ax=res (backward), dh (forward) + * update bound, Range, Code, ds:si + * scratch flags, cx=0, dl + */ + + push BX + +// { int i = numLevels; res = 1; + mov BX, DX // res = 1 + +// do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); + +RangeDecoder_1: + push AX + call Bit1axdx // C,%ax = Bit1(prob+%ax) + rclb $1, %dl // res <<= 1; res |= C + andb %bl, %al // current bit + orb %al, %bh // store in bh + shlb $1, %bl // update max + pop AX + loop RangeDecoder_1 + +// res -= (1 << numLevels); } + + xchg AX, BX // move bh to dh + xchg AX, DX // and dl to al + sub %dl, %al // sub max + pop BX + ret