Got it to run on the test laptop
This commit is contained in:
parent
8dbeccbe75
commit
98da895f18
9 changed files with 1234 additions and 3 deletions
5
Makefile
5
Makefile
|
|
@ -6,6 +6,7 @@ OBJS=\
|
||||||
src/pxe.o \
|
src/pxe.o \
|
||||||
src/std.o \
|
src/std.o \
|
||||||
src/main.o \
|
src/main.o \
|
||||||
|
src/tinflate.o \
|
||||||
# end of object list
|
# end of object list
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
@ -23,10 +24,12 @@ boot.bin: boot.elf
|
||||||
wc -c $@
|
wc -c $@
|
||||||
|
|
||||||
boot.elf: $(OBJS) src/nbp.ld
|
boot.elf: $(OBJS) src/nbp.ld
|
||||||
$(LD) $(LDFLAGS) -T src/nbp.ld -o $@ $(OBJS)
|
$(CC) -m32 -fno-pic -fno-pie -T src/nbp.ld -o $@ $(OBJS) -ffreestanding -nostdlib
|
||||||
|
|
||||||
%.o: %.S
|
%.o: %.S
|
||||||
$(CC) $(CFLAGS) -c -o $@ $(@:.o=.S) $(CPPFLAGS)
|
$(CC) $(CFLAGS) -c -o $@ $(@:.o=.S) $(CPPFLAGS)
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(CFLAGS) -O0 -c -o $@ $(@:.o=.c) $(CPPFLAGS)
|
$(CC) $(CFLAGS) -O0 -c -o $@ $(@:.o=.c) $(CPPFLAGS)
|
||||||
|
|
||||||
|
# TODO header dependencies
|
||||||
|
|
|
||||||
|
|
@ -5,4 +5,4 @@ LD = ld
|
||||||
|
|
||||||
CFLAGS = -no-pie -fno-pic -fno-stack-protector -nostdinc -ffreestanding -m32
|
CFLAGS = -no-pie -fno-pic -fno-stack-protector -nostdinc -ffreestanding -m32
|
||||||
CPPFLAGS = -I3rdparty/include
|
CPPFLAGS = -I3rdparty/include
|
||||||
LDFLAGS = -m elf_i386
|
LDFLAGS = -m elf_i386 -fno-pic
|
||||||
|
|
|
||||||
20
eth-dnsmasq.conf
Normal file
20
eth-dnsmasq.conf
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#listen-address=10.0.0.1
|
||||||
|
#bind-dynamic
|
||||||
|
#bind-interfaces
|
||||||
|
#except-interface=lo
|
||||||
|
interface=enp6s0f3u1
|
||||||
|
|
||||||
|
dhcp-range=10.0.0.2,10.0.0.100,255.255.255.0,6h
|
||||||
|
dhcp-boot=/boot.bin
|
||||||
|
#dhcp-option=66,"10.0.0.1"
|
||||||
|
#dhcp-option=67,"/boot.bin"
|
||||||
|
#dhcp-option=67,"/pxelinux.0"
|
||||||
|
|
||||||
|
log-async
|
||||||
|
|
||||||
|
# Disable DNS server
|
||||||
|
port=0
|
||||||
|
|
||||||
|
enable-tftp
|
||||||
|
tftp-root=/home/thomas/karlos/fernlader2/serve
|
||||||
|
|
||||||
364
src/fs.h
Normal file
364
src/fs.h
Normal file
|
|
@ -0,0 +1,364 @@
|
||||||
|
/*
|
||||||
|
* x86_64-cb/fs.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* This file is part of the BOOTBOOT Protocol package.
|
||||||
|
* @brief Filesystem drivers for initial ramdisk.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/**
|
||||||
|
* FS/Z initrd (OS/Z's native file system)
|
||||||
|
*/
|
||||||
|
file_t fsz_initrd(unsigned char *initrd_p, char *kernel)
|
||||||
|
{
|
||||||
|
file_t ret = { NULL, 0 };
|
||||||
|
if(initrd_p==NULL || memcmp(initrd_p + 512,"FS/Z",4) || kernel==NULL){
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
unsigned char passphrase[256],chk[32],iv[32];
|
||||||
|
unsigned int i,j,k,l,ss=1<<(initrd_p[518]+11);
|
||||||
|
unsigned char *ent, *in=(initrd_p+*((uint64_t*)(initrd_p+560))*ss);
|
||||||
|
SHA256_CTX ctx;
|
||||||
|
PRINTFS("FS/Z",kernel);
|
||||||
|
//decrypt initrd
|
||||||
|
if(*((uint32_t*)(initrd_p+520))!=0 && (initrd_p[519]&&0xF0)!=0) {
|
||||||
|
printf("BOOTBOOT-PANIC: Unsupported cipher\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
while(*((uint32_t*)(initrd_p+520))!=0) {
|
||||||
|
printf(" * Passphrase? ");
|
||||||
|
l=ReadLine(passphrase,sizeof(passphrase));
|
||||||
|
if(!l) {
|
||||||
|
printf("\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if(*((uint32_t*)(initrd_p+520))!=crc32_calc((char*)passphrase,l)) {
|
||||||
|
printf("\rBOOTBOOT-ERROR: Bad passphrase\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("\r * Decrypting...\r");
|
||||||
|
SHA256_Init(&ctx);
|
||||||
|
SHA256_Update(&ctx,passphrase,l);
|
||||||
|
SHA256_Update(&ctx,initrd_p+512,6);
|
||||||
|
SHA256_Final(chk,&ctx);
|
||||||
|
for(i=0;i<32;i++) initrd_p[i+680]^=chk[i];
|
||||||
|
SHA256_Init(&ctx);
|
||||||
|
SHA256_Update(&ctx,initrd_p+680,32);
|
||||||
|
SHA256_Final(iv,&ctx);
|
||||||
|
// FSZ_SB_EALG_SHACBC
|
||||||
|
for(k=ss,j=1;j<*((uint32_t*)(initrd_p+528));j++) {
|
||||||
|
memcpy(chk,iv,32);
|
||||||
|
for(i=0;i<ss;i++) {
|
||||||
|
if(i%32==0) {
|
||||||
|
SHA256_Init(&ctx);
|
||||||
|
SHA256_Update(&ctx,&chk,32);
|
||||||
|
SHA256_Update(&ctx,&j,4);
|
||||||
|
SHA256_Final(chk,&ctx);
|
||||||
|
}
|
||||||
|
initrd_p[k++]^=chk[i%32]^iv[i%32];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset(initrd_p+680,0,32); *((uint32_t*)(initrd_p+520)) = 0;
|
||||||
|
*((uint32_t*)(initrd_p+1020))=crc32_calc((char *)initrd_p+512,508);
|
||||||
|
printf(" \r");
|
||||||
|
}
|
||||||
|
// Get the inode
|
||||||
|
char *s,*e;
|
||||||
|
s=e=kernel;
|
||||||
|
i=0;
|
||||||
|
again:
|
||||||
|
while(*e!='/'&&*e!=0){e++;}
|
||||||
|
if(*e=='/'){e++;}
|
||||||
|
if(!memcmp(in,"FSIN",4)){
|
||||||
|
//is it inlined?
|
||||||
|
if(!memcmp(initrd_p[520]&1? in + 2048 : in + 1024,"FSDR",4)){
|
||||||
|
ent=(initrd_p[520]&1? in + 2048 : in + 1024);
|
||||||
|
} else if(!memcmp(initrd_p+*((uint64_t*)(in+448))*ss,"FSDR",4)){
|
||||||
|
// go, get the sector pointed
|
||||||
|
ent=(initrd_p+*((uint64_t*)(in+448))*ss);
|
||||||
|
} else {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
//skip header
|
||||||
|
unsigned char *hdr=ent; ent+=128;
|
||||||
|
//iterate on directory entries
|
||||||
|
int j=*((uint64_t*)(hdr+16));
|
||||||
|
while(j-->0){
|
||||||
|
if(!memcmp(ent + 16,s,e-s)) {
|
||||||
|
if(*e==0) {
|
||||||
|
i=*((uint64_t*)(ent+0));
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
s=e;
|
||||||
|
in=(initrd_p+*((uint64_t*)(ent+0))*ss);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ent+=128;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
i=0;
|
||||||
|
}
|
||||||
|
if(i!=0) {
|
||||||
|
// fid -> inode ptr -> data ptr
|
||||||
|
unsigned char *in=(initrd_p+i*ss);
|
||||||
|
if(!memcmp(in,"FSIN",4)){
|
||||||
|
ret.size=*((uint64_t*)(in+464));
|
||||||
|
if(*((uint64_t*)(in+448)) == i) {
|
||||||
|
if(!(in[488]&31)) {
|
||||||
|
// inline data
|
||||||
|
ret.ptr=(uint8_t*)(initrd_p+i*ss+(initrd_p[520]&1? 2048 : 1024));
|
||||||
|
} else {
|
||||||
|
// sector directory or list inlined
|
||||||
|
ret.ptr=(uint8_t*)(initrd_p + *((uint64_t*)(initrd_p[520]&1? in + 2048 : in + 1024))*ss);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if(*((uint64_t*)(in+448))) {
|
||||||
|
switch((in[488]&15) + (in[488]&16 ? 1 : 0)) {
|
||||||
|
case 0: // direct data
|
||||||
|
ret.ptr=(uint8_t*)(initrd_p + *((uint64_t*)(in+448)) * ss);
|
||||||
|
break;
|
||||||
|
case 1: // sector directory or list (only one level supported here, and no holes in files)
|
||||||
|
ret.ptr=(uint8_t*)(initrd_p + *((uint64_t*)(initrd_p + *((uint64_t*)(in+448))*ss)) * ss);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else ret.size=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minix3 file system
|
||||||
|
* directories only checked for their first block, and kernel must be defragmented
|
||||||
|
*/
|
||||||
|
file_t mfs_initrd(unsigned char *initrd_p, char *kernel)
|
||||||
|
{
|
||||||
|
uint32_t o, bs, ino_tbl;
|
||||||
|
uint8_t *ino, *d;
|
||||||
|
char *s = kernel, *e;
|
||||||
|
file_t ret = { NULL, 0 };
|
||||||
|
if(initrd_p[1048] != 'Z' || initrd_p[1049] != 'M') return ret;
|
||||||
|
PRINTFS("MFS",kernel);
|
||||||
|
bs = *((uint16_t*)(initrd_p + 1052));
|
||||||
|
ino_tbl = (2 + *((uint16_t*)(initrd_p + 1030)) + *((uint16_t*)(initrd_p + 1032))) * bs;
|
||||||
|
ino = initrd_p + ino_tbl;
|
||||||
|
again:
|
||||||
|
for(e = s; *e && *e != '/'; e++);
|
||||||
|
d = initrd_p + *((uint32_t*)(ino + 24)) * bs;
|
||||||
|
for(o = 0; o < *((uint32_t*)(ino + 8)) && o < bs; o += 64, d += 64) {
|
||||||
|
if(*((uint32_t*)d) && !memcmp(s, d + 4, e - s) && !d[e - s]) {
|
||||||
|
ino = initrd_p + ino_tbl + (*((uint32_t*)d) - 1) * 64;
|
||||||
|
d = initrd_p + *((uint32_t*)(ino + 24)) * bs;
|
||||||
|
if(!*e) { ret.ptr = d; ret.size = *((uint32_t*)(ino + 8)); return ret; }
|
||||||
|
s = e + 1; goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cpio archive
|
||||||
|
*/
|
||||||
|
file_t cpio_initrd(unsigned char *initrd_p, char *kernel)
|
||||||
|
{
|
||||||
|
unsigned char *ptr=initrd_p;
|
||||||
|
int k;
|
||||||
|
file_t ret = { NULL, 0 };
|
||||||
|
if(initrd_p==NULL || kernel==NULL ||
|
||||||
|
(memcmp(initrd_p,"070701",6) && memcmp(initrd_p,"070702",6) && memcmp(initrd_p,"070707",6)))
|
||||||
|
return ret;
|
||||||
|
PRINTFS("cpio",kernel);
|
||||||
|
k=strlen(kernel);
|
||||||
|
// hpodc archive
|
||||||
|
while(!memcmp(ptr,"070707",6)){
|
||||||
|
int ns=octbin(ptr+8*6+11,6);
|
||||||
|
int fs=octbin(ptr+8*6+11+6,11);
|
||||||
|
if(!memcmp(ptr+9*6+2*11,kernel,k+1) ||
|
||||||
|
(ptr[9*6+2*11] == '.' && ptr[9*6+2*11+1] == '/' && !memcmp(ptr+9*6+2*11+2,kernel,k+1))) {
|
||||||
|
ret.size=fs;
|
||||||
|
ret.ptr=(uint8_t*)(ptr+9*6+2*11+ns);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ptr+=(76+ns+fs);
|
||||||
|
}
|
||||||
|
// newc and crc archive
|
||||||
|
while(!memcmp(ptr,"07070",5)){
|
||||||
|
int fs=hexbin(ptr+8*6+6,8);
|
||||||
|
int ns=hexbin(ptr+8*11+6,8);
|
||||||
|
if(!memcmp(ptr+110,kernel,k+1) || (ptr[110] == '.' && ptr[111] == '/' && !memcmp(ptr+112,kernel,k+1))) {
|
||||||
|
ret.size=fs;
|
||||||
|
ret.ptr=(uint8_t*)(ptr+((110+ns+3)/4)*4);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ptr+=((110+ns+3)/4)*4 + ((fs+3)/4)*4;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ustar tarball archive
|
||||||
|
*/
|
||||||
|
file_t tar_initrd(unsigned char *initrd_p, char *kernel)
|
||||||
|
{
|
||||||
|
unsigned char *ptr=initrd_p;
|
||||||
|
int k;
|
||||||
|
file_t ret = { NULL, 0 };
|
||||||
|
if(initrd_p==NULL || kernel==NULL || memcmp(initrd_p+257,"ustar",5))
|
||||||
|
return ret;
|
||||||
|
PRINTFS("tar",kernel);
|
||||||
|
k=strlen(kernel);
|
||||||
|
while(!memcmp(ptr+257,"ustar",5)){
|
||||||
|
int fs=octbin(ptr+0x7c,11);
|
||||||
|
if(!memcmp(ptr,kernel,k+1) || (ptr[0] == '.' && ptr[1] == '/' && !memcmp(ptr+2,kernel,k+1))) {
|
||||||
|
ret.size=fs;
|
||||||
|
ret.ptr=(uint8_t*)(ptr+512);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ptr+=(((fs+511)/512)+1)*512;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple File System
|
||||||
|
*/
|
||||||
|
file_t sfs_initrd(unsigned char *initrd_p, char *kernel)
|
||||||
|
{
|
||||||
|
unsigned char *ptr, *end;
|
||||||
|
int k,bs,ver;
|
||||||
|
file_t ret = { NULL, 0 };
|
||||||
|
if(initrd_p==NULL || kernel==NULL || (memcmp(initrd_p+0x1AC,"SFS",3) && memcmp(initrd_p+0x1A6,"SFS",3)))
|
||||||
|
return ret;
|
||||||
|
// 1.0 Brendan's version, 1.10 BenLunt's version
|
||||||
|
ver=!memcmp(initrd_p+0x1A6,"SFS",3)?10:0;
|
||||||
|
bs=1<<(7+(uint8_t)initrd_p[ver?0x1B6:0x1BC]);
|
||||||
|
end=initrd_p + *((uint64_t *)&initrd_p[ver?0x1AA:0x1B0]) * bs; // base + total_number_of_blocks * blocksize
|
||||||
|
// get index area
|
||||||
|
ptr=end - *((uint64_t *)&initrd_p[ver?0x19E:0x1A4]); // end - size of index area
|
||||||
|
// got a Starting Marker Entry?
|
||||||
|
if(ptr[0]!=2)
|
||||||
|
return ret;
|
||||||
|
if (ver) {
|
||||||
|
PRINTFS("SFS 1.10",kernel);
|
||||||
|
} else {
|
||||||
|
PRINTFS("SFS 1.0",kernel);
|
||||||
|
}
|
||||||
|
k=strlen(kernel);
|
||||||
|
// iterate on index until we reach the end or Volume Identifier
|
||||||
|
while(ptr<end && ptr[0]!=0x01){
|
||||||
|
ptr+=64;
|
||||||
|
// file entry?
|
||||||
|
if(ptr[0]!=0x12)
|
||||||
|
continue;
|
||||||
|
// filename match?
|
||||||
|
if(!memcmp(ptr+(ver?0x23:0x22),kernel,k+1)){
|
||||||
|
ret.size=*((uint64_t*)&ptr[ver?0x1B:0x1A]); // file_length
|
||||||
|
ret.ptr=initrd_p + *((uint64_t*)&ptr[ver?0x0B:0x0A]) * bs; // base + start_block * blocksize
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* James Molloy's initrd (for some reason it's popular among hobby OS developers)
|
||||||
|
* http://www.jamesmolloy.co.uk/tutorial_html
|
||||||
|
*/
|
||||||
|
file_t jamesm_initrd(unsigned char *initrd_p, char *kernel)
|
||||||
|
{
|
||||||
|
unsigned char *ptr=initrd_p+4;
|
||||||
|
int i,k,nf=*((int*)initrd_p);
|
||||||
|
file_t ret = { NULL, 0 };
|
||||||
|
// no real magic, so we assume initrd contains at least one file...
|
||||||
|
if(initrd_p==NULL || kernel==NULL || initrd_p[2]!=0 || initrd_p[3]!=0 || initrd_p[4]!=0xBF)
|
||||||
|
return ret;
|
||||||
|
PRINTFS("JamesM",kernel);
|
||||||
|
k=strlen(kernel);
|
||||||
|
for(i=0;i<nf && ptr[0]==0xBF;i++) {
|
||||||
|
if(!memcmp(ptr+1,kernel,k+1)){
|
||||||
|
ret.ptr=*((uint32_t*)(ptr+65)) + initrd_p;
|
||||||
|
ret.size=*((uint32_t*)(ptr+69));
|
||||||
|
}
|
||||||
|
ptr+=73;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/**
|
||||||
|
* EchFS
|
||||||
|
* http://github.com/echfs/echfs
|
||||||
|
*/
|
||||||
|
file_t ech_initrd(unsigned char *initrd_p, char *kernel)
|
||||||
|
{
|
||||||
|
uint64_t parent = 0xffffffffffffffffUL, n;
|
||||||
|
unsigned char *ptr;
|
||||||
|
char *end, *fn;
|
||||||
|
int k = 0;
|
||||||
|
file_t ret = { NULL, 0 };
|
||||||
|
if(initrd_p==NULL || kernel==NULL || memcmp(initrd_p+4,"_ECH_FS_",8))
|
||||||
|
return ret;
|
||||||
|
PRINTFS("EchFS",kernel);
|
||||||
|
memcpy(&k, initrd_p + 28, 4);
|
||||||
|
memcpy(&n, initrd_p + 12, 8);
|
||||||
|
ptr = initrd_p + (((n * 8 + k - 1) / k) + 16) * k;
|
||||||
|
for(end = fn = kernel; *end && *end != '/'; end++);
|
||||||
|
while(*((uint64_t*)ptr)) {
|
||||||
|
if(*((uint64_t*)ptr) == parent && !memcmp(ptr + 9, fn, end - fn) && !ptr[9 + end - fn]) {
|
||||||
|
parent = *((uint64_t*)(ptr + 240));
|
||||||
|
if(!*end) {
|
||||||
|
ret.size=*((uint64_t*)(ptr + 248));
|
||||||
|
ret.ptr=(uint8_t*)(initrd_p + parent * k);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
end++;
|
||||||
|
for(fn = end; *end && *end != '/'; end++);
|
||||||
|
}
|
||||||
|
ptr += 256;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static file system drivers registry
|
||||||
|
*/
|
||||||
|
file_t (*fsdrivers[]) (unsigned char *, char *) = {
|
||||||
|
#if 0
|
||||||
|
fsz_initrd,
|
||||||
|
#endif
|
||||||
|
mfs_initrd,
|
||||||
|
cpio_initrd,
|
||||||
|
tar_initrd,
|
||||||
|
sfs_initrd,
|
||||||
|
jamesm_initrd,
|
||||||
|
#if 0
|
||||||
|
ech_initrd,
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
49
src/main.c
49
src/main.c
|
|
@ -205,6 +205,55 @@ typedef struct __attribute__((packed)) s_PXENV_TFTP_OPEN {
|
||||||
uint16_t packet_size;
|
uint16_t packet_size;
|
||||||
} t_PXENV_TFTP_OPEN;
|
} t_PXENV_TFTP_OPEN;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return type for fs drivers
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t *ptr;
|
||||||
|
uint32_t size;
|
||||||
|
} file_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert ascii octal number to binary number
|
||||||
|
*/
|
||||||
|
int octbin(unsigned char *str,int size)
|
||||||
|
{
|
||||||
|
int s=0;
|
||||||
|
unsigned char *c=str;
|
||||||
|
while(size-->0){
|
||||||
|
s*=8;
|
||||||
|
s+=*c-'0';
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert ascii hex number to binary number
|
||||||
|
*/
|
||||||
|
int hexbin(unsigned char *str, int size)
|
||||||
|
{
|
||||||
|
int v=0;
|
||||||
|
while(size-->0){
|
||||||
|
v <<= 4;
|
||||||
|
if(*str>='0' && *str<='9')
|
||||||
|
v += (int)((unsigned char)(*str)-'0');
|
||||||
|
else if(*str >= 'A' && *str <= 'F')
|
||||||
|
v += (int)((unsigned char)(*str)-'A'+10);
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PRINTFS(fsname,kernel) do {\
|
||||||
|
debug_write(fsname);\
|
||||||
|
debug_write(" ");\
|
||||||
|
debug_write(kernel);\
|
||||||
|
debug_write("\r\n");\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#include "fs.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ _start: cli
|
||||||
|
|
||||||
// initialize our own BSS section
|
// initialize our own BSS section
|
||||||
mov $_bss_start, %di
|
mov $_bss_start, %di
|
||||||
mov $_bss_end, %cx
|
mov $_bss_end, %ecx
|
||||||
sub %di, %cx
|
sub %di, %cx
|
||||||
xor %al, %al
|
xor %al, %al
|
||||||
rep stosb
|
rep stosb
|
||||||
|
|
|
||||||
203
src/smp.S
Normal file
203
src/smp.S
Normal file
|
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
* x86_64-cb/smp.S
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* This file is part of the BOOTBOOT Protocol package.
|
||||||
|
* @brief SMP and long mode initialization code.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
.globl ap_trampoline
|
||||||
|
.globl bsp_init
|
||||||
|
.globl bsp64_init
|
||||||
|
.extern lapic_ids
|
||||||
|
.extern lapic_addr
|
||||||
|
.extern initstack
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* things to do on the APs *
|
||||||
|
*****************************************************************************/
|
||||||
|
.balign 128
|
||||||
|
.code16
|
||||||
|
/* this code will be relocated to 0x1000 - 0x1100 */
|
||||||
|
ap_trampoline:
|
||||||
|
cli
|
||||||
|
cld
|
||||||
|
ljmp $0, $0x1040
|
||||||
|
.balign 16
|
||||||
|
// prot mode GDT
|
||||||
|
_L1010_GDT_table:
|
||||||
|
.long 0, 0
|
||||||
|
.long 0x0000FFFF, 0x00CF9A00 // flat code
|
||||||
|
.long 0x0000FFFF, 0x008F9200 // flat data
|
||||||
|
.long 0x00000068, 0x00CF8900 // tss, not used but required by VB's vt-x
|
||||||
|
_L1030_GDT_value:
|
||||||
|
.word _L1030_GDT_value - _L1010_GDT_table - 1
|
||||||
|
.long 0x1010
|
||||||
|
.long 0, 0
|
||||||
|
.balign 64
|
||||||
|
_L1040:
|
||||||
|
xorw %ax, %ax
|
||||||
|
movw %ax, %ds
|
||||||
|
lgdtl 0x1030
|
||||||
|
movl %cr0, %eax
|
||||||
|
orl $1, %eax
|
||||||
|
movl %eax, %cr0
|
||||||
|
ljmp $8, $0x1060
|
||||||
|
.balign 32
|
||||||
|
.code32
|
||||||
|
_L1060:
|
||||||
|
movw $16, %ax
|
||||||
|
movw %ax, %ds
|
||||||
|
incb 0x1011
|
||||||
|
// spinlock until BSP finishes
|
||||||
|
1: pause
|
||||||
|
cmpb $0, 0x1010
|
||||||
|
jz 1b
|
||||||
|
// jump back to non-relocated code segment
|
||||||
|
ljmp $8, $longmode_init
|
||||||
|
.balign 128
|
||||||
|
ap_trampoline_end:
|
||||||
|
|
||||||
|
// long mode GDT (here it is aligned and out of execution flow)
|
||||||
|
GDT_table:
|
||||||
|
.long 0, 0
|
||||||
|
.long 0x0000FFFF, 0x00209800 // flat code, ring 0
|
||||||
|
.long 0x0000FFFF, 0x00809200 // flat data
|
||||||
|
.long 0x00000068, 0x00008900 // tss, required by vt-x
|
||||||
|
.long 0, 0
|
||||||
|
GDT_value:
|
||||||
|
.word GDT_value - GDT_table - 1
|
||||||
|
.long GDT_table, 0, 0
|
||||||
|
.word 0
|
||||||
|
.balign 8
|
||||||
|
stack64:
|
||||||
|
.long bootboot_startcore
|
||||||
|
.long 0
|
||||||
|
.quad 8
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* things to do on BSP *
|
||||||
|
*****************************************************************************/
|
||||||
|
/* these are 32 bit encoded instructions */
|
||||||
|
bsp_init:
|
||||||
|
cli
|
||||||
|
cld
|
||||||
|
movb $0xFF, %al // disable PIC
|
||||||
|
outb %al, $0x21
|
||||||
|
outb %al, $0xA1
|
||||||
|
inb $0x70, %al // disable NMI
|
||||||
|
orb $0x80, %al
|
||||||
|
outb %al, $0x70
|
||||||
|
incb 0x1010 // release AP spin lock
|
||||||
|
// fall into long mode initialization code
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* common code for all cores, enable long mode and start kernel *
|
||||||
|
*****************************************************************************/
|
||||||
|
longmode_init:
|
||||||
|
// enable lapic and find our lapic id
|
||||||
|
movl lapic_addr, %edi
|
||||||
|
or %edi, %edi
|
||||||
|
jz 1f
|
||||||
|
addl $0xF0, %edi
|
||||||
|
movl (%edi), %eax
|
||||||
|
or $0x1, %ah
|
||||||
|
movl %eax, (%edi)
|
||||||
|
subl $0xD0, %edi
|
||||||
|
movl (%edi), %edi
|
||||||
|
shrl $24, %edi
|
||||||
|
1: // do not clobber di
|
||||||
|
|
||||||
|
movl $0x368, %eax // Set PAE, MCE, PGE; OSFXSR, OSXMMEXCPT (enable SSE)
|
||||||
|
movl %eax, %cr4
|
||||||
|
movl $0x4000, %eax
|
||||||
|
movl %eax, %cr3
|
||||||
|
movl $0x0C0000080, %ecx // EFR MSR
|
||||||
|
rdmsr
|
||||||
|
orl $0x100, %eax // enable long mode
|
||||||
|
wrmsr
|
||||||
|
|
||||||
|
movl $0x0C0000011, %eax // clear EM, MP (enable SSE) and WP
|
||||||
|
movl %eax, %cr0
|
||||||
|
lgdt GDT_value
|
||||||
|
ljmp $8, $bootboot_startcore
|
||||||
|
|
||||||
|
.code64
|
||||||
|
/* similar code to above, but these are 64 bit encoded, only needed on BSP if coreboot is compiled for x86_64 */
|
||||||
|
bsp64_init:
|
||||||
|
// do not clobber di
|
||||||
|
cli
|
||||||
|
cld
|
||||||
|
movb $0xFF, %al // disable PIC
|
||||||
|
outb %al, $0x21
|
||||||
|
outb %al, $0xA1
|
||||||
|
inb $0x70, %al // disable NMI
|
||||||
|
orb $0x80, %al
|
||||||
|
outb %al, $0x70
|
||||||
|
incb 0x1010 // release AP spin lock
|
||||||
|
|
||||||
|
xorq %rax, %rax
|
||||||
|
movl $0xC0000011, %eax // enable SSE
|
||||||
|
movq %rax, %cr0
|
||||||
|
movq %cr4, %rax
|
||||||
|
orw $3 << 8, %ax
|
||||||
|
mov %rax, %cr4
|
||||||
|
movl $0x4000, %eax // set up paging
|
||||||
|
movq %rax, %cr3
|
||||||
|
xorq %rax, %rax
|
||||||
|
movl $GDT_value, %eax
|
||||||
|
lgdt (%rax)
|
||||||
|
movl $stack64, %eax // reload CS, that's tricky in long mode because ljmp doesn't work
|
||||||
|
movq %rax, %rsp
|
||||||
|
lretq
|
||||||
|
|
||||||
|
/* IN: di = apic id of current core */
|
||||||
|
bootboot_startcore:
|
||||||
|
movl $0x10, %eax // load long mode segments
|
||||||
|
movw %ax, %ds
|
||||||
|
movw %ax, %es
|
||||||
|
movw %ax, %ss
|
||||||
|
movw %ax, %fs
|
||||||
|
movw %ax, %gs
|
||||||
|
movzwq %di, %rbx
|
||||||
|
shll $1, %ebx // ebx = lapic id * 2
|
||||||
|
addl $lapic_ids, %ebx
|
||||||
|
xorq %rax, %rax
|
||||||
|
movw (%rbx), %ax // ax = word[lapic_ids + lapic id * 2]
|
||||||
|
movl $initstack, %ebx
|
||||||
|
movl (%rbx), %ebx
|
||||||
|
movzwq %ax, %rdi
|
||||||
|
mulq %rbx // 1k stack for each core
|
||||||
|
|
||||||
|
// set stack and call _start() in sys/core
|
||||||
|
xorq %rsp, %rsp // sp = core_num * -initstack
|
||||||
|
subq %rax, %rsp
|
||||||
|
xorq %rsi, %rsi
|
||||||
|
movl $entrypoint, %esi // GAS does not allow "jmp qword[entrypoint]"
|
||||||
|
lodsq
|
||||||
|
jmp *%rax
|
||||||
|
hlt
|
||||||
117
src/tinf.h
Normal file
117
src/tinf.h
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* uzlib - tiny deflate/inflate library (deflate, gzip, zlib)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2003 by Joergen Ibsen / Jibz
|
||||||
|
* All Rights Reserved
|
||||||
|
* http://www.ibsensoftware.com/
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-2016 by Paul Sokolovsky
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TINF_H_INCLUDED
|
||||||
|
#define TINF_H_INCLUDED
|
||||||
|
|
||||||
|
#include "std.h"
|
||||||
|
|
||||||
|
/* calling convention */
|
||||||
|
#ifndef TINFCC
|
||||||
|
#ifdef __WATCOMC__
|
||||||
|
#define TINFCC __cdecl
|
||||||
|
#else
|
||||||
|
#define TINFCC
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ok status, more data produced */
|
||||||
|
#define TINF_OK 0
|
||||||
|
/* end of compressed stream reached */
|
||||||
|
#define TINF_DONE 1
|
||||||
|
#define TINF_DATA_ERROR (-3)
|
||||||
|
#define TINF_CHKSUM_ERROR (-4)
|
||||||
|
#define TINF_DICT_ERROR (-5)
|
||||||
|
|
||||||
|
/* checksum types */
|
||||||
|
#define TINF_CHKSUM_NONE 0
|
||||||
|
#define TINF_CHKSUM_ADLER 1
|
||||||
|
#define TINF_CHKSUM_CRC 2
|
||||||
|
|
||||||
|
/* data structures */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned short table[16]; /* table of code length counts */
|
||||||
|
unsigned short trans[288]; /* code -> symbol translation table */
|
||||||
|
} TINF_TREE;
|
||||||
|
|
||||||
|
struct TINF_DATA;
|
||||||
|
typedef struct TINF_DATA {
|
||||||
|
const unsigned char *source;
|
||||||
|
/* If source above is NULL, this function will be used to read
|
||||||
|
next byte from source stream */
|
||||||
|
unsigned char (*readSource)(struct TINF_DATA *data);
|
||||||
|
|
||||||
|
unsigned int tag;
|
||||||
|
unsigned int bitcount;
|
||||||
|
|
||||||
|
/* Buffer start */
|
||||||
|
unsigned char *destStart;
|
||||||
|
/* Buffer total size */
|
||||||
|
unsigned int destSize;
|
||||||
|
/* Current pointer in buffer */
|
||||||
|
unsigned char *dest;
|
||||||
|
/* Remaining bytes in buffer */
|
||||||
|
unsigned int destRemaining;
|
||||||
|
|
||||||
|
/* Accumulating checksum */
|
||||||
|
unsigned int checksum;
|
||||||
|
char checksum_type;
|
||||||
|
|
||||||
|
int btype;
|
||||||
|
int bfinal;
|
||||||
|
unsigned int curlen;
|
||||||
|
int lzOff;
|
||||||
|
unsigned char *dict_ring;
|
||||||
|
unsigned int dict_size;
|
||||||
|
unsigned int dict_idx;
|
||||||
|
|
||||||
|
TINF_TREE ltree; /* dynamic length/symbol tree */
|
||||||
|
TINF_TREE dtree; /* dynamic distance tree */
|
||||||
|
} TINF_DATA;
|
||||||
|
|
||||||
|
#define TINF_PUT(d, c) \
|
||||||
|
{ \
|
||||||
|
*d->dest++ = c; \
|
||||||
|
if (d->dict_ring) { d->dict_ring[d->dict_idx++] = c; if (d->dict_idx == d->dict_size) d->dict_idx = 0; } \
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char TINFCC uzlib_get_byte(TINF_DATA *d);
|
||||||
|
|
||||||
|
/* Decompression API */
|
||||||
|
|
||||||
|
void TINFCC uzlib_init(void);
|
||||||
|
void TINFCC uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen);
|
||||||
|
int TINFCC uzlib_uncompress(TINF_DATA *d);
|
||||||
|
int TINFCC uzlib_uncompress_chksum(TINF_DATA *d);
|
||||||
|
|
||||||
|
int TINFCC uzlib_zlib_parse_header(TINF_DATA *d);
|
||||||
|
int TINFCC uzlib_gzip_parse_header(TINF_DATA *d);
|
||||||
|
|
||||||
|
/* Compression API */
|
||||||
|
|
||||||
|
void TINFCC uzlib_compress(void *data, const uint8_t *src, unsigned slen);
|
||||||
|
|
||||||
|
/* Checksum API */
|
||||||
|
|
||||||
|
/* prev_sum is previous value for incremental computation, 1 initially */
|
||||||
|
uint32_t TINFCC uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum);
|
||||||
|
/* crc is previous value for incremental computation, 0xffffffff initially */
|
||||||
|
uint32_t TINFCC uzlib_crc32(const void *data, unsigned int length, uint32_t crc);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* TINF_H_INCLUDED */
|
||||||
475
src/tinflate.c
Normal file
475
src/tinflate.c
Normal file
|
|
@ -0,0 +1,475 @@
|
||||||
|
/*
|
||||||
|
* tinflate - tiny inflate
|
||||||
|
*
|
||||||
|
* Copyright (c) 2003 by Joergen Ibsen / Jibz
|
||||||
|
* All Rights Reserved
|
||||||
|
* http://www.ibsensoftware.com/
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-2016 by Paul Sokolovsky
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express
|
||||||
|
* or implied warranty. In no event will the authors be
|
||||||
|
* held liable for any damages arising from the use of
|
||||||
|
* this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software
|
||||||
|
* for any purpose, including commercial applications,
|
||||||
|
* and to alter it and redistribute it freely, subject to
|
||||||
|
* the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be
|
||||||
|
* misrepresented; you must not claim that you
|
||||||
|
* wrote the original software. If you use this
|
||||||
|
* software in a product, an acknowledgment in
|
||||||
|
* the product documentation would be appreciated
|
||||||
|
* but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked
|
||||||
|
* as such, and must not be misrepresented as
|
||||||
|
* being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from
|
||||||
|
* any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tinf.h"
|
||||||
|
|
||||||
|
uint32_t tinf_get_le_uint32(TINF_DATA *d);
|
||||||
|
uint32_t tinf_get_be_uint32(TINF_DATA *d);
|
||||||
|
|
||||||
|
/* --------------------------------------------------- *
|
||||||
|
* -- uninitialized global data (static structures) -- *
|
||||||
|
* --------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef RUNTIME_BITS_TABLES
|
||||||
|
|
||||||
|
/* extra bits and base tables for length codes */
|
||||||
|
unsigned char length_bits[30];
|
||||||
|
unsigned short length_base[30];
|
||||||
|
|
||||||
|
/* extra bits and base tables for distance codes */
|
||||||
|
unsigned char dist_bits[30];
|
||||||
|
unsigned short dist_base[30];
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
const unsigned char length_bits[30] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
1, 1, 1, 1, 2, 2, 2, 2,
|
||||||
|
3, 3, 3, 3, 4, 4, 4, 4,
|
||||||
|
5, 5, 5, 5
|
||||||
|
};
|
||||||
|
const unsigned short length_base[30] = {
|
||||||
|
3, 4, 5, 6, 7, 8, 9, 10,
|
||||||
|
11, 13, 15, 17, 19, 23, 27, 31,
|
||||||
|
35, 43, 51, 59, 67, 83, 99, 115,
|
||||||
|
131, 163, 195, 227, 258
|
||||||
|
};
|
||||||
|
|
||||||
|
const unsigned char dist_bits[30] = {
|
||||||
|
0, 0, 0, 0, 1, 1, 2, 2,
|
||||||
|
3, 3, 4, 4, 5, 5, 6, 6,
|
||||||
|
7, 7, 8, 8, 9, 9, 10, 10,
|
||||||
|
11, 11, 12, 12, 13, 13
|
||||||
|
};
|
||||||
|
const unsigned short dist_base[30] = {
|
||||||
|
1, 2, 3, 4, 5, 7, 9, 13,
|
||||||
|
17, 25, 33, 49, 65, 97, 129, 193,
|
||||||
|
257, 385, 513, 769, 1025, 1537, 2049, 3073,
|
||||||
|
4097, 6145, 8193, 12289, 16385, 24577
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* special ordering of code length codes */
|
||||||
|
const unsigned char clcidx[] = {
|
||||||
|
16, 17, 18, 0, 8, 7, 9, 6,
|
||||||
|
10, 5, 11, 4, 12, 3, 13, 2,
|
||||||
|
14, 1, 15
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ----------------------- *
|
||||||
|
* -- utility functions -- *
|
||||||
|
* ----------------------- */
|
||||||
|
|
||||||
|
#ifdef RUNTIME_BITS_TABLES
|
||||||
|
/* build extra bits and base tables */
|
||||||
|
static void tinf_build_bits_base(unsigned char *bits, unsigned short *base, int delta, int first)
|
||||||
|
{
|
||||||
|
int i, sum;
|
||||||
|
|
||||||
|
/* build bits table */
|
||||||
|
for (i = 0; i < delta; ++i) bits[i] = 0;
|
||||||
|
for (i = 0; i < 30 - delta; ++i) bits[i + delta] = i / delta;
|
||||||
|
|
||||||
|
/* build base table */
|
||||||
|
for (sum = first, i = 0; i < 30; ++i)
|
||||||
|
{
|
||||||
|
base[i] = sum;
|
||||||
|
sum += 1 << bits[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* build the fixed huffman trees */
|
||||||
|
static void tinf_build_fixed_trees(TINF_TREE *lt, TINF_TREE *dt)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* build fixed length tree */
|
||||||
|
for (i = 0; i < 7; ++i) lt->table[i] = 0;
|
||||||
|
|
||||||
|
lt->table[7] = 24;
|
||||||
|
lt->table[8] = 152;
|
||||||
|
lt->table[9] = 112;
|
||||||
|
|
||||||
|
for (i = 0; i < 24; ++i) lt->trans[i] = 256 + i;
|
||||||
|
for (i = 0; i < 144; ++i) lt->trans[24 + i] = i;
|
||||||
|
for (i = 0; i < 8; ++i) lt->trans[24 + 144 + i] = 280 + i;
|
||||||
|
for (i = 0; i < 112; ++i) lt->trans[24 + 144 + 8 + i] = 144 + i;
|
||||||
|
|
||||||
|
/* build fixed distance tree */
|
||||||
|
for (i = 0; i < 5; ++i) dt->table[i] = 0;
|
||||||
|
|
||||||
|
dt->table[5] = 32;
|
||||||
|
|
||||||
|
for (i = 0; i < 32; ++i) dt->trans[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* given an array of code lengths, build a tree */
|
||||||
|
static void tinf_build_tree(TINF_TREE *t, const unsigned char *lengths, unsigned int num)
|
||||||
|
{
|
||||||
|
unsigned short offs[16];
|
||||||
|
unsigned int i, sum;
|
||||||
|
|
||||||
|
/* clear code length count table */
|
||||||
|
for (i = 0; i < 16; ++i) t->table[i] = 0;
|
||||||
|
|
||||||
|
/* scan symbol lengths, and sum code length counts */
|
||||||
|
for (i = 0; i < num; ++i) t->table[lengths[i]]++;
|
||||||
|
|
||||||
|
t->table[0] = 0;
|
||||||
|
|
||||||
|
/* compute offset table for distribution sort */
|
||||||
|
for (sum = 0, i = 0; i < 16; ++i)
|
||||||
|
{
|
||||||
|
offs[i] = sum;
|
||||||
|
sum += t->table[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create code->symbol translation table (symbols sorted by code) */
|
||||||
|
for (i = 0; i < num; ++i)
|
||||||
|
{
|
||||||
|
if (lengths[i]) t->trans[offs[lengths[i]]++] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------- *
|
||||||
|
* -- decode functions -- *
|
||||||
|
* ---------------------- */
|
||||||
|
|
||||||
|
unsigned char uzlib_get_byte(TINF_DATA *d)
|
||||||
|
{
|
||||||
|
if (d->source) {
|
||||||
|
return *d->source++;
|
||||||
|
}
|
||||||
|
return d->readSource(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t tinf_get_le_uint32(TINF_DATA *d)
|
||||||
|
{
|
||||||
|
uint32_t val = 0;
|
||||||
|
int i;
|
||||||
|
for (i = 4; i--;) {
|
||||||
|
val = val >> 8 | uzlib_get_byte(d) << 24;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t tinf_get_be_uint32(TINF_DATA *d)
|
||||||
|
{
|
||||||
|
uint32_t val = 0;
|
||||||
|
int i;
|
||||||
|
for (i = 4; i--;) {
|
||||||
|
val = val << 8 | uzlib_get_byte(d);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get one bit from source stream */
|
||||||
|
static int tinf_getbit(TINF_DATA *d)
|
||||||
|
{
|
||||||
|
unsigned int bit;
|
||||||
|
|
||||||
|
/* check if tag is empty */
|
||||||
|
if (!d->bitcount--)
|
||||||
|
{
|
||||||
|
/* load next tag */
|
||||||
|
d->tag = uzlib_get_byte(d);
|
||||||
|
d->bitcount = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* shift bit out of tag */
|
||||||
|
bit = d->tag & 0x01;
|
||||||
|
d->tag >>= 1;
|
||||||
|
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read a num bit value from a stream and add base */
|
||||||
|
static unsigned int tinf_read_bits(TINF_DATA *d, int num, int base)
|
||||||
|
{
|
||||||
|
unsigned int val = 0;
|
||||||
|
|
||||||
|
/* read num bits */
|
||||||
|
if (num)
|
||||||
|
{
|
||||||
|
unsigned int limit = 1 << (num);
|
||||||
|
unsigned int mask;
|
||||||
|
|
||||||
|
for (mask = 1; mask < limit; mask *= 2)
|
||||||
|
if (tinf_getbit(d)) val += mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
return val + base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* given a data stream and a tree, decode a symbol */
|
||||||
|
static int tinf_decode_symbol(TINF_DATA *d, TINF_TREE *t)
|
||||||
|
{
|
||||||
|
int sum = 0, cur = 0, len = 0;
|
||||||
|
|
||||||
|
/* get more bits while code value is above sum */
|
||||||
|
do {
|
||||||
|
|
||||||
|
cur = 2*cur + tinf_getbit(d);
|
||||||
|
|
||||||
|
++len;
|
||||||
|
|
||||||
|
sum += t->table[len];
|
||||||
|
cur -= t->table[len];
|
||||||
|
|
||||||
|
} while (cur >= 0);
|
||||||
|
|
||||||
|
return t->trans[sum + cur];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* given a data stream, decode dynamic trees from it */
|
||||||
|
static void tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||||
|
{
|
||||||
|
unsigned char lengths[288+32];
|
||||||
|
unsigned int hlit, hdist, hclen;
|
||||||
|
unsigned int i, num, length;
|
||||||
|
|
||||||
|
/* get 5 bits HLIT (257-286) */
|
||||||
|
hlit = tinf_read_bits(d, 5, 257);
|
||||||
|
|
||||||
|
/* get 5 bits HDIST (1-32) */
|
||||||
|
hdist = tinf_read_bits(d, 5, 1);
|
||||||
|
|
||||||
|
/* get 4 bits HCLEN (4-19) */
|
||||||
|
hclen = tinf_read_bits(d, 4, 4);
|
||||||
|
|
||||||
|
for (i = 0; i < 19; ++i) lengths[i] = 0;
|
||||||
|
|
||||||
|
/* read code lengths for code length alphabet */
|
||||||
|
for (i = 0; i < hclen; ++i)
|
||||||
|
{
|
||||||
|
/* get 3 bits code length (0-7) */
|
||||||
|
unsigned int clen = tinf_read_bits(d, 3, 0);
|
||||||
|
|
||||||
|
lengths[clcidx[i]] = clen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* build code length tree, temporarily use length tree */
|
||||||
|
tinf_build_tree(lt, lengths, 19);
|
||||||
|
|
||||||
|
/* decode code lengths for the dynamic trees */
|
||||||
|
for (num = 0; num < hlit + hdist; )
|
||||||
|
{
|
||||||
|
int sym = tinf_decode_symbol(d, lt);
|
||||||
|
|
||||||
|
switch (sym)
|
||||||
|
{
|
||||||
|
case 16:
|
||||||
|
/* copy previous code length 3-6 times (read 2 bits) */
|
||||||
|
{
|
||||||
|
unsigned char prev = lengths[num - 1];
|
||||||
|
for (length = tinf_read_bits(d, 2, 3); length; --length)
|
||||||
|
{
|
||||||
|
lengths[num++] = prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
/* repeat code length 0 for 3-10 times (read 3 bits) */
|
||||||
|
for (length = tinf_read_bits(d, 3, 3); length; --length)
|
||||||
|
{
|
||||||
|
lengths[num++] = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 18:
|
||||||
|
/* repeat code length 0 for 11-138 times (read 7 bits) */
|
||||||
|
for (length = tinf_read_bits(d, 7, 11); length; --length)
|
||||||
|
{
|
||||||
|
lengths[num++] = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* values 0-15 represent the actual code lengths */
|
||||||
|
lengths[num++] = sym;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* build dynamic trees */
|
||||||
|
tinf_build_tree(lt, lengths, hlit);
|
||||||
|
tinf_build_tree(dt, lengths + hlit, hdist);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------- *
|
||||||
|
* -- block inflate functions -- *
|
||||||
|
* ----------------------------- */
|
||||||
|
|
||||||
|
/* given a stream and two trees, inflate a block of data */
|
||||||
|
static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||||
|
{
|
||||||
|
if (d->curlen == 0) {
|
||||||
|
unsigned int offs;
|
||||||
|
int dist;
|
||||||
|
int sym = tinf_decode_symbol(d, lt);
|
||||||
|
//printf("huff sym: %02x\n", sym);
|
||||||
|
|
||||||
|
/* literal byte */
|
||||||
|
if (sym < 256) {
|
||||||
|
TINF_PUT(d, sym);
|
||||||
|
return TINF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end of block */
|
||||||
|
if (sym == 256) {
|
||||||
|
return TINF_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* substring from sliding dictionary */
|
||||||
|
sym -= 257;
|
||||||
|
/* possibly get more bits from length code */
|
||||||
|
d->curlen = tinf_read_bits(d, length_bits[sym], length_base[sym]);
|
||||||
|
|
||||||
|
dist = tinf_decode_symbol(d, dt);
|
||||||
|
/* possibly get more bits from distance code */
|
||||||
|
offs = tinf_read_bits(d, dist_bits[dist], dist_base[dist]);
|
||||||
|
d->lzOff = -offs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy next byte from dict substring */
|
||||||
|
d->dest[0] = d->dest[d->lzOff];
|
||||||
|
d->dest++;
|
||||||
|
d->curlen--;
|
||||||
|
return TINF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* inflate an uncompressed block of data */
|
||||||
|
static int tinf_inflate_uncompressed_block(TINF_DATA *d)
|
||||||
|
{
|
||||||
|
if (d->curlen == 0) {
|
||||||
|
unsigned int length, invlength;
|
||||||
|
|
||||||
|
/* get length */
|
||||||
|
length = uzlib_get_byte(d) + 256 * uzlib_get_byte(d);
|
||||||
|
/* get one's complement of length */
|
||||||
|
invlength = uzlib_get_byte(d) + 256 * uzlib_get_byte(d);
|
||||||
|
/* check length */
|
||||||
|
if (length != (~invlength & 0x0000ffff)) return TINF_DATA_ERROR;
|
||||||
|
|
||||||
|
/* increment length to properly return TINF_DONE below, without
|
||||||
|
producing data at the same time */
|
||||||
|
d->curlen = length + 1;
|
||||||
|
|
||||||
|
/* make sure we start next block on a byte boundary */
|
||||||
|
d->bitcount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (--d->curlen == 0) {
|
||||||
|
return TINF_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char c = uzlib_get_byte(d);
|
||||||
|
TINF_PUT(d, c);
|
||||||
|
return TINF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------- *
|
||||||
|
* -- public functions -- *
|
||||||
|
* ---------------------- */
|
||||||
|
|
||||||
|
/* initialize global (static) data */
|
||||||
|
void uzlib_init(void)
|
||||||
|
{
|
||||||
|
#ifdef RUNTIME_BITS_TABLES
|
||||||
|
/* build extra bits and base tables */
|
||||||
|
tinf_build_bits_base(length_bits, length_base, 4, 3);
|
||||||
|
tinf_build_bits_base(dist_bits, dist_base, 2, 1);
|
||||||
|
|
||||||
|
/* fix a special case */
|
||||||
|
length_bits[28] = 0;
|
||||||
|
length_base[28] = 258;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* inflate next byte of compressed stream */
|
||||||
|
int uzlib_uncompress(TINF_DATA *d)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
int res;
|
||||||
|
|
||||||
|
/* start a new block */
|
||||||
|
if (d->btype == -1) {
|
||||||
|
next_blk:
|
||||||
|
/* read final block flag */
|
||||||
|
d->bfinal = tinf_getbit(d);
|
||||||
|
/* read block type (2 bits) */
|
||||||
|
d->btype = tinf_read_bits(d, 2, 0);
|
||||||
|
|
||||||
|
//printf("Started new block: type=%d final=%d\n", d->btype, d->bfinal);
|
||||||
|
|
||||||
|
if (d->btype == 1) {
|
||||||
|
/* build fixed huffman trees */
|
||||||
|
tinf_build_fixed_trees(&d->ltree, &d->dtree);
|
||||||
|
} else if (d->btype == 2) {
|
||||||
|
/* decode trees from stream */
|
||||||
|
tinf_decode_trees(d, &d->ltree, &d->dtree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process current block */
|
||||||
|
switch (d->btype)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
/* decompress uncompressed block */
|
||||||
|
res = tinf_inflate_uncompressed_block(d);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
/* decompress block with fixed/dyanamic huffman trees */
|
||||||
|
/* trees were decoded previously, so it's the same routine for both */
|
||||||
|
res = tinf_inflate_block_data(d, &d->ltree, &d->dtree);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return TINF_DATA_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == TINF_DONE && !d->bfinal) {
|
||||||
|
/* the block has ended (without producing more data), but we
|
||||||
|
can't return without data, so start procesing next block */
|
||||||
|
goto next_blk;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res != TINF_OK) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (--d->destSize);
|
||||||
|
|
||||||
|
return TINF_OK;
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue