#define CBFS_HEADER_PTR 0xfffffffc #define CBFS_HEADER_MAGIC 0 #define CBFS_HEADER_VERSION (CBFS_HEADER_MAGIC + 4) #define CBFS_HEADER_ROMSIZE (CBFS_HEADER_VERSION + 4) #define CBFS_HEADER_BOOTBLOCKSIZE (CBFS_HEADER_ROMSIZE + 4) #define CBFS_HEADER_ALIGN (CBFS_HEADER_BOOTBLOCKSIZE + 4) #define CBFS_HEADER_OFFSET (CBFS_HEADER_ALIGN + 4) #define CBFS_FILE_MAGIC 0 #define CBFS_FILE_LEN (CBFS_FILE_MAGIC + 8) #define CBFS_FILE_TYPE (CBFS_FILE_LEN + 4) #define CBFS_FILE_CHECKSUM (CBFS_FILE_TYPE + 4) #define CBFS_FILE_OFFSET (CBFS_FILE_CHECKSUM + 4) #define CBFS_FILE_STRUCTSIZE (CBFS_FILE_OFFSET + 4) #define CBFS_STAGE_COMPRESSION 0 #define CBFS_STAGE_ENTRY (CBFS_STAGE_COMPRESSION + 4) #define CBFS_STAGE_LOAD (CBFS_STAGE_ENTRY + 8) #define CBFS_STAGE_LEN (CBFS_STAGE_LOAD + 8) #define CBFS_STAGE_MEMLEN (CBFS_STAGE_LEN + 4) /* input %esi: filename input %esp: return address (not pointer to return address!) output %eax: entry point clobbers %ebx, %ecx, %edi */ walkcbfs: cld mov CBFS_HEADER_PTR, %eax mov CBFS_HEADER_ROMSIZE(%eax), %ecx bswap %ecx mov $0, %ebx sub %ecx, %ebx mov CBFS_HEADER_OFFSET(%eax), %ecx bswap %ecx add %ecx, %ebx /* determine filename length */ mov $0, %eax 1: cmpb $0, (%eax,%esi) jz 2f add $1, %eax jmp 1b 2: add $1, %eax walker: mov 0(%ebx), %edi cmp %edi, filemagic jne searchfile mov 4(%ebx), %edi cmp %edi, filemagic+4 jne searchfile mov %ebx, %edi add $CBFS_FILE_STRUCTSIZE, %edi /* edi = address of first byte after struct cbfs_file */ mov %eax, %ecx repe cmpsb # zero flag set if strings are equal jnz tryharder # we found it! mov CBFS_FILE_OFFSET(%ebx), %eax bswap %eax add %ebx, %eax add $CBFS_STAGE_ENTRY, %eax /* eax = ((cbfs_stage* (cbfs_file* ebx)->offset)->entry) */ mov 0(%eax), %eax jmp *%esp tryharder: sub %ebx, %edi sub $CBFS_FILE_STRUCTSIZE, %edi /* edi = # of walked bytes */ sub %edi, %esi /* esi = start of filename */ /* ebx = ecx = (current+offset+len+ALIGN-1) & ~(ALIGN-1) */ mov CBFS_FILE_OFFSET(%ebx), %ecx bswap %ecx add %ebx, %ecx mov CBFS_FILE_LEN(%ebx), %edi bswap %edi add %edi, %ecx mov CBFS_HEADER_PTR, %edi mov CBFS_HEADER_ALIGN(%edi), %edi bswap %edi sub $1, %edi add %edi, %ecx not %edi and %edi, %ecx /* if oldaddr >= addr, leave */ cmp %ebx, %ecx jbe out mov %ecx, %ebx check_for_exit: /* look if we should exit: did we pass into the bootblock already? */ mov CBFS_HEADER_PTR, %ecx mov CBFS_HEADER_BOOTBLOCKSIZE(%ecx), %ecx bswap %ecx not %ecx add $1, %ecx cmp %ecx, %ebx /* if bootblockstart >= addr (==we're still in the data area) , jump back */ jbe walker out: mov $0, %eax jmp *%esp searchfile: /* if filemagic isn't found, move forward cbfs_header->align bytes */ mov CBFS_HEADER_PTR, %edi mov CBFS_HEADER_ALIGN(%edi), %edi bswap %edi add %edi, %ebx jmp check_for_exit filemagic: .ascii "LARCHIVE"