⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gzip.c

📁 EFI(Extensible Firmware Interface)是下一代BIOS
💻 C
📖 第 1 页 / 共 2 页
字号:
		offs  = bswap64(elf->e_phoff);	phnum = bswap16(elf->e_phnum);	VERB_PRT(3, { 			Print(L"ELF file is %s\n", elf_is_big_endian ? L"big endian" : L"little endian");			Print(L"Entry point 0x%lx\n", bswap64(elf->e_entry));			Print(L"%d program headers\n", phnum);			Print(L"%d segment headers\n", bswap16(elf->e_shnum));		   });	/* XXX: need to check on this */	if (offs + phnum * sizeof(*phdrs) > (unsigned) blocksize) {		ERR_PRT((L"%s : ELF program headers not in first block (%ld)\n", LD_NAME, offs));		return -1;	}	kernel_entry = (void *)bswap64(elf->e_entry);	if (((UINTN)kernel_entry >> 61) != 0) {		ERR_PRT((L"%s:  <<ERROR>> entry point is a virtual address 0x%lx : not supported anymore\n", LD_NAME, kernel_entry));	}	phdrs = (Elf64_Phdr *) (buf + offs);	low_addr = ~0;	max_addr = 0;	/*	 * allocate chunk table	 * Convention: a segment that does not need loading will	 * have chunk[].addr = 0.	 */	chunks = (void *)alloc(sizeof(struct segment)*phnum, 0);    	if (chunks == NULL) {        	ERR_PRT((L"%s : failed alloc chunks %r\n", LD_NAME));		return -1;    	}	nchunks = phnum;	/*	 * find lowest and higest virtual addresses	 * don't assume FULLY sorted !	 */	for (i = 0; i < phnum; ++i) {		/* 		 * record chunk no matter what because no load may happen		 * anywhere in archive, not just as the last segment		 */		paddr = bswap64(phdrs[i].p_paddr);		memsz = bswap64(phdrs[i].p_memsz),		chunks[i].addr   = paddr;		chunks[i].offset = bswap64(phdrs[i].p_offset);		chunks[i].size   = bswap64(phdrs[i].p_filesz);		chunks[i].bss_sz = bswap64(phdrs[i].p_memsz) - bswap64(phdrs[i].p_filesz);		CHUNK_VALIDATE(i);		if (bswap32(phdrs[i].p_type) != PT_LOAD) {			CHUNK_NO_LOAD(i); /* mark no load chunk */			DBG_PRT((L"%s : skipping segment %ld\n", LD_NAME, i));			continue;		}		CHUNK_CAN_LOAD(i); /* mark no load chunk */		VERB_PRT(3, 		Print(L"\n%s : segment %ld vaddr [0x%lx-0x%lx] offset %ld filesz %ld memsz=%ld bss_sz=%ld\n",				LD_NAME,				1+i, 				chunks[i].addr, 				chunks[i].addr+bswap64(phdrs[i].p_filesz), 				chunks[i].offset, 				chunks[i].size,				memsz,				chunks[i].bss_sz));				if (paddr < low_addr) low_addr = paddr;		if (paddr + memsz > max_addr) max_addr = paddr + memsz;	}	if (low_addr & (EFI_PAGE_SIZE - 1)) {		ERR_PRT((L"%s : low_addr not page aligned 0x%lx\n", LD_NAME, low_addr));		goto error;	}	analyze_chunks();	DBG_PRT((L"%s : %d program headers entry=0x%lx\nlowest_addr=0x%lx highest_addr=0x%lx\n", 			LD_NAME,			phnum, kernel_entry, low_addr, max_addr));	total_size = (UINTN)max_addr - (UINTN)low_addr;	pages = EFI_SIZE_TO_PAGES(total_size);	/*	 * Record end of kernel for initrd	 */	kernel_base = (void *)low_addr;	kernel_end  = (void *)(low_addr + (pages << EFI_PAGE_SHIFT));	/* allocate memory for the kernel */	if (alloc_kmem((void *)low_addr, pages) == -1) {		VOID *new_addr;		ERR_PRT((L"%s : AllocatePages(%d, 0x%lx) for kernel failed\n", LD_NAME, pages, low_addr));		if (ia64_can_relocate() == 0) {			ERR_PRT((L"relocation is disabled, cannot load kernel"));			goto error;		}		/*		 * could not allocate at requested spot, try to find a		 * suitable location to relocate the kernel		 *		 * The maximum sized Itanium TLB translation entry is 256 MB.		 * If we relocate the kernel by this amount we know for sure		 * that alignment constraints will be satisified, regardless		 * of the kernel used.		 */		VERB_PRT(1, Print(L"Attempting to relocate kernel.\n"));		if (find_kernel_memory((VOID*) low_addr, (VOID*) max_addr, 256*MB, &new_addr) == -1) {			ERR_PRT((L"%s : find_kernel_memory(0x%lx, 0x%lx, 0x%lx, 0x%lx) failed\n", LD_NAME, low_addr, max_addr, 256*MB, &load_offset));			goto error;		}		/* unsigned arithmetic */                load_offset = (UINTN) (new_addr - ROUNDDOWN((UINTN) low_addr,256*MB));		ERR_PRT((L"low_addr=0x%lx new_addr=0x%lx offset=0x%lx", low_addr, new_addr, load_offset));		/*		 * correct various addresses for non-zero load_offset		 */		kernel_base = (void *) ((UINTN) kernel_base + load_offset);		kernel_end  = (void *) ((UINTN) kernel_end + load_offset);		kernel_entry = (void*) ((UINTN) kernel_entry + load_offset);		for (i = 0; i < phnum; ++i) {			chunks[i].addr += load_offset;			phdrs[i].p_paddr = (Elf64_Addr) ((UINT64) phdrs[i].p_paddr + load_offset);		}		/*		 * try one last time to get memory for the kernel		 */		if (alloc_kmem((void *)low_addr+load_offset, pages) == -1) {			ERR_PRT((L"%s : AllocatePages(%d, 0x%lx) for kernel failed\n", LD_NAME, pages, low_addr+load_offset));			ERR_PRT((L"Relocation by 0x%lx bytes failed.\n", load_offset));			goto error;		}	}	return 0;error:	if (chunks) free(chunks);	return -1;}/* * Determine which chunk in the Elf file will be coming out of the expand * code next. */static voidnextchunk(void){	int i;	segment_t *cp;	cp = NULL;	for(i=0; i < nchunks; i++) {		if (!CHUNK_IS_VALID(i) || !CHUNK_IS_LOAD(i)) continue;		if (file_offset > chunks[i].offset) continue;		if (cp == NULL || chunks[i].offset < cp->offset) cp = &chunks[i];	}	cur_chunk = cp;}/* * Write the output window window[0..outcnt-1] holding uncompressed * data and update crc. */voidflush_window(void){	static const CHAR8 helicopter[4] = { '|' , '/' , '-' , '\\' };	static UINTN heli_count;	struct segment *cp;	char	*src, *dst;	long	cnt;	if (!outcnt) return;	DBG_PRT((L"%s : flush_window outnct=%d file_offset=%ld\n", LD_NAME, outcnt, file_offset));	Print(L"%c\b",helicopter[heli_count++%4]);	updcrc(window, outcnt);	/*	 * first time, we extract the headers	 */	if (!bytes_out) {		if (first_block(window, outcnt) < 0) error("invalid exec header"); 		nextchunk();	}	bytes_out += outcnt;	src = window;tail:	/* check if user wants to abort */	if (check_abort() == EFI_SUCCESS) goto load_abort;	cp = cur_chunk;	if (cp == NULL || file_offset + outcnt <= cp->offset) {		file_offset += outcnt;		return;	}	// Does this window begin before the current chunk?	if (file_offset < cp->offset) {		unsigned long skip = cp->offset - file_offset;		src         += skip;		file_offset += skip;		outcnt      -= skip;	}	dst = (char *)cp->addr + (file_offset - cp->offset);	cnt = cp->offset + cp->size - file_offset;	if (cnt > outcnt) cnt = outcnt;	Memcpy(dst, src, cnt);	file_offset += cnt;	outcnt      -= cnt;	src         += cnt;	/* See if we are at the end of this chunk */	if (file_offset == cp->offset + cp->size) {		if (cp->bss_sz) {			dst = (char *)cp->addr + cp->size;			Memset(dst, 0, cp->bss_sz);		}		nextchunk();		/* handle remaining bytes */		if (outcnt) goto tail; 	}	return;load_abort:	free_kmem();	error_return = ELILO_LOAD_ABORTED;	longjmp(jbuf, 1);}static voiderror(char *x){	ERR_PRT((L"%s : %a", LD_NAME, x));	/* will eventually exit with error from gunzip() */	longjmp(jbuf,1);}INT32decompress_kernel(VOID){	INT32 ret;	clear_bufs();	makecrc();	Print(L"Uncompressing Linux... ");	ret = gunzip();	if (ret == 0) Print(L"done\n");	return ret == 0 ? 0 : -1;}intgunzip_kernel(fops_fd_t fd, kdesc_t *kd){	int ret = -1;	error_return = ELILO_LOAD_ERROR;		window = (void *)alloc(WSIZE, 0);    	if (window == NULL) {        	ERR_PRT((L"%s : allocate output window failed\n", LD_NAME));		return -1;    	}	inbuf = (void *)alloc(INBUFSIZE, 0);    	if (inbuf == NULL) {        	ERR_PRT((L"%s : allocate input window failedr\n", LD_NAME));		goto error;    	}	input_fd   = fd;	insize     = 0;	bytes_out  = 0;	if (setjmp(jbuf) == 1) goto error;	ret = decompress_kernel();error:	if (window) free(window);	if (inbuf) free(inbuf);	if (ret == 0) {		kd->kentry = kernel_entry;		kd->kend   = kernel_end;		kd->kstart = kernel_base;		error_return = ELILO_LOAD_SUCCESS;	}	return error_return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -