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

📄 freebsd_loader.c

📁 linux下从网卡远程启动
💻 C
字号:
/* bootinfo */#define BOOTINFO_VERSION 1#define NODEV           (-1)    /* non-existent device */#define PAGE_SHIFT      12              /* LOG2(PAGE_SIZE) */#define PAGE_SIZE       (1<<PAGE_SHIFT) /* bytes/page */#define PAGE_MASK       (PAGE_SIZE-1)#define N_BIOS_GEOM     8struct bootinfo {        unsigned int            bi_version;        const unsigned char     *bi_kernelname;        struct nfs_diskless     *bi_nfs_diskless;                                /* End of fields that are always present. */#define bi_endcommon            bi_n_bios_used        unsigned int            bi_n_bios_used;        unsigned long           bi_bios_geom[N_BIOS_GEOM];        unsigned int            bi_size;        unsigned char           bi_memsizes_valid;        unsigned char           bi_pad[3];        unsigned long           bi_basemem;        unsigned long           bi_extmem;        unsigned long           bi_symtab;        unsigned long           bi_esymtab;	/* Note that these are in the FreeBSD headers but were not here... */	unsigned long           bi_kernend;		/* end of kernel space */	unsigned long           bi_envp;		/* environment */	unsigned long           bi_modulep;		/* preloaded modules */};static struct bootinfo bsdinfo;#ifdef ELF_IMAGEstatic Elf32_Shdr *shdr;	/* To support the FreeBSD kludge! */static Address symtab_load;static Address symstr_load;static int symtabindex;static int symstrindex;#endifstatic enum {	Unknown, Tagged, Aout, Elf, Aout_FreeBSD, Elf_FreeBSD,} image_type = Unknown;static unsigned int off;#ifdef ELF_IMAGEstatic void elf_freebsd_probe(void){	image_type = Elf;	if (estate.e.elf32.e_entry & 0xf0000000) {		image_type = Elf_FreeBSD;		printf("/FreeBSD");		off = -(estate.e.elf32.e_entry & 0xff000000);		estate.e.elf32.e_entry += off;	}	/* Make sure we have a null to start with... */	shdr = 0;		/* Clear the symbol index values... */	symtabindex = -1;	symstrindex = -1;		/* ...and the load addresses of the symbols  */	symtab_load = 0;	symstr_load = 0;}static void elf_freebsd_fixup_segment(void){	if (image_type == Elf_FreeBSD) {		estate.p.phdr32[estate.segment].p_paddr += off;	}}static void elf_freebsd_find_segment_end(void){	/* Count the bytes read even for the last block	 * as we will need to know where the last block	 * ends in order to load the symbols correctly.	 * (plus it could be useful elsewhere...)	 * Note that we need to count the actual size,	 * not just the end of the disk image size.	 */	estate.curaddr += 		(estate.p.phdr32[estate.segment].p_memsz - 		estate.p.phdr32[estate.segment].p_filesz);}static int elf_freebsd_debug_loader(unsigned int offset){	/* No more segments to be loaded - time to start the	 * nasty state machine to support the loading of	 * FreeBSD debug symbols due to the fact that FreeBSD	 * uses/exports the kernel's debug symbols in order	 * to make much of the system work!  Amazing (arg!)	 *	 * We depend on the fact that for the FreeBSD kernel,	 * there is only one section of debug symbols and that	 * the section is after all of the loaded sections in	 * the file.  This assumes a lot but is somewhat required	 * to make this code not be too annoying.  (Where do you	 * load symbols when the code has not loaded yet?)	 * Since this function is actually just a callback from	 * the network data transfer code, we need to be able to	 * work with the data as it comes in.  There is no chance	 * for doing a seek other than forwards.	 *	 * The process we use is to first load the section	 * headers.  Once they are loaded (shdr != 0) we then	 * look for where the symbol table and symbol table	 * strings are and setup some state that we found	 * them and fall into processing the first one (which	 * is the symbol table) and after that has been loaded,	 * we try the symbol strings.  Note that the order is	 * actually required as the memory image depends on	 * the symbol strings being loaded starting at the	 * end of the symbol table.  The kernel assumes this	 * layout of the image.	 *	 * At any point, if we get to the end of the load file	 * or the section requested is earlier in the file than	 * the current file pointer, we just end up falling	 * out of this and booting the kernel without this	 * information.	 */	/* Make sure that the next address is long aligned... */	/* Assumes size of long is a power of 2... */	estate.curaddr = (estate.curaddr + sizeof(long) - 1) & ~(sizeof(long) - 1);		/* If we have not yet gotten the shdr loaded, try that */	if (shdr == 0)	{		estate.toread = estate.e.elf32.e_shnum * estate.e.elf32.e_shentsize;		estate.skip = estate.e.elf32.e_shoff - (estate.loc + offset);		if (estate.toread)		{#if ELF_DEBUG			printf("shdr *, size %lX, curaddr %lX\n", 				estate.toread, estate.curaddr);#endif						/* Start reading at the curaddr and make that the shdr */			shdr = (Elf32_Shdr *)phys_to_virt(estate.curaddr);						/* Start to read... */			return 1;		}	}	else	{		/* We have the shdr loaded, check if we have found		 * the indexs where the symbols are supposed to be */		if ((symtabindex == -1) && (symstrindex == -1))		{			int i;			/* Make sure that the address is page aligned... */			/* Symbols need to start in their own page(s)... */			estate.curaddr = (estate.curaddr + 4095) & ~4095;						/* Need to make new indexes... */			for (i=0; i < estate.e.elf32.e_shnum; i++)			{				if (shdr[i].sh_type == SHT_SYMTAB)				{					int j;					for (j=0; j < estate.e.elf32.e_phnum; j++)					{						/* Check only for loaded sections */						if ((estate.p.phdr32[i].p_type | 0x80) == (PT_LOAD | 0x80))						{							/* Only the extra symbols */							if ((shdr[i].sh_offset >= estate.p.phdr32[j].p_offset) &&								((shdr[i].sh_offset + shdr[i].sh_size) <=									(estate.p.phdr32[j].p_offset + estate.p.phdr32[j].p_filesz)))							{								shdr[i].sh_offset=0;								shdr[i].sh_size=0;								break;							}						}					}					if ((shdr[i].sh_offset != 0) && (shdr[i].sh_size != 0))					{						symtabindex = i;						symstrindex = shdr[i].sh_link;					}				}			}		}				/* Check if we have a symbol table index and have not loaded it */		if ((symtab_load == 0) && (symtabindex >= 0))		{			/* No symbol table yet?  Load it first... */						/* This happens to work out in a strange way.			 * If we are past the point in the file already,			 * we will skip a *large* number of bytes which			 * ends up bringing us to the end of the file and			 * an old (default) boot.  Less code and lets			 * the state machine work in a cleaner way but this			 * is a nasty side-effect trick... */			estate.skip = shdr[symtabindex].sh_offset - (estate.loc + offset);						/* And we need to read this many bytes... */			estate.toread = shdr[symtabindex].sh_size;						if (estate.toread)			{#if ELF_DEBUG				printf("db sym, size %lX, curaddr %lX\n", 					estate.toread, estate.curaddr);#endif				/* Save where we are loading this... */				symtab_load = estate.curaddr;								*((long *)phys_to_virt(estate.curaddr)) = estate.toread;				estate.curaddr += sizeof(long);								/* Start to read... */				return 1;			}		}		else if ((symstr_load == 0) && (symstrindex >= 0))		{			/* We have already loaded the symbol table, so			 * now on to the symbol strings... */									/* Same nasty trick as above... */			estate.skip = shdr[symstrindex].sh_offset - (estate.loc + offset);						/* And we need to read this many bytes... */			estate.toread = shdr[symstrindex].sh_size;						if (estate.toread)			{#if ELF_DEBUG				printf("db str, size %lX, curaddr %lX\n", 					estate.toread, estate.curaddr);#endif				/* Save where we are loading this... */				symstr_load = estate.curaddr;								*((long *)phys_to_virt(estate.curaddr)) = estate.toread;				estate.curaddr += sizeof(long);								/* Start to read... */				return 1;			}		}	}	/* all done */	return 0;}static void elf_freebsd_boot(unsigned long entry) {	if (image_type != Elf_FreeBSD)		return;	memset(&bsdinfo, 0, sizeof(bsdinfo));	bsdinfo.bi_basemem = meminfo.basememsize;	bsdinfo.bi_extmem = meminfo.memsize;	bsdinfo.bi_memsizes_valid = 1;	bsdinfo.bi_version = BOOTINFO_VERSION;	bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF);	bsdinfo.bi_nfs_diskless = NULL;	bsdinfo.bi_size = sizeof(bsdinfo);#define RB_BOOTINFO     0x80000000      /* have `struct bootinfo *' arg */  	if(freebsd_kernel_env[0] != '\0'){		freebsd_howto |= RB_BOOTINFO;		bsdinfo.bi_envp = (unsigned long)freebsd_kernel_env;	}		/* Check if we have symbols loaded, and if so,	 * made the meta_data needed to pass those to	 * the kernel. */	if ((symtab_load !=0) && (symstr_load != 0))	{		unsigned long *t;				bsdinfo.bi_symtab = symtab_load;				/* End of symbols (long aligned...) */		/* Assumes size of long is a power of 2... */		bsdinfo.bi_esymtab = (symstr_load +			sizeof(long) +			*((long *)symstr_load) +			sizeof(long) - 1) & ~(sizeof(long) - 1);				/* Where we will build the meta data... */		t = phys_to_virt(bsdinfo.bi_esymtab);		#if ELF_DEBUG		printf("Metadata at %lX\n",t);#endif				/* Set up the pointer to the memory... */		bsdinfo.bi_modulep = virt_to_phys(t);				/* The metadata structure is an array of 32-bit		 * words where we store some information about the		 * system.  This is critical, as FreeBSD now looks		 * only for the metadata for the extended symbol		 * information rather than in the bootinfo.		 */		/* First, do the kernel name and the kernel type */		/* Note that this assumed x86 byte order... */				/* 'kernel\0\0' */		*t++=MODINFO_NAME; *t++= 7; *t++=0x6E72656B; *t++=0x00006C65;				/* 'elf kernel\0\0' */		*t++=MODINFO_TYPE; *t++=11; *t++=0x20666C65; *t++=0x6E72656B; *t++ = 0x00006C65;				/* Now the symbol start/end - note that they are		 * here in local/physical address - the Kernel		 * boot process will relocate the addresses. */		*t++=MODINFOMD_SSYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_symtab;		*t++=MODINFOMD_ESYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_esymtab;				*t++=MODINFO_END; *t++=0; /* end of metadata */				/* Since we have symbols we need to make		 * sure that the kernel knows its own end		 * of memory...  It is not _end but after		 * the symbols and the metadata... */		bsdinfo.bi_kernend = virt_to_phys(t);				/* Signal locore.s that we have a valid bootinfo		 * structure that was completely filled in. */		freebsd_howto |= 0x80000000;	}		xstart32(entry, freebsd_howto, NODEV, 0, 0, 0, 		virt_to_phys(&bsdinfo), 0, 0, 0);	longjmp(restart_etherboot, -2);}#endif#ifdef AOUT_IMAGEstatic void aout_freebsd_probe(void){	image_type = Aout;	if (((astate.head.a_midmag >> 16) & 0xffff) == 0) {		/* Some other a.out variants have a different		 * value, and use other alignments (e.g. 1K),		 * not the 4K used by FreeBSD.  */		image_type = Aout_FreeBSD;		printf("/FreeBSD");		off = -(astate.head.a_entry & 0xff000000);		astate.head.a_entry += off;	}}static void aout_freebsd_boot(void){	if (image_type == Aout_FreeBSD) {		memset(&bsdinfo, 0, sizeof(bsdinfo));		bsdinfo.bi_basemem = meminfo.basememsize;		bsdinfo.bi_extmem = meminfo.memsize;		bsdinfo.bi_memsizes_valid = 1;		bsdinfo.bi_version = BOOTINFO_VERSION;		bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF);		bsdinfo.bi_nfs_diskless = NULL;		bsdinfo.bi_size = sizeof(bsdinfo);		xstart32(astate.head.a_entry, freebsd_howto, NODEV, 0, 0, 0, 			virt_to_phys(&bsdinfo), 0, 0, 0);		longjmp(restart_etherboot, -2);	}}#endif

⌨️ 快捷键说明

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