Exemple #1
0
void
jtag_reserve_syspage_addr(paddr_t jtag_syspage_addr) {

	// Save the address to be used later
	jtag_syspage_address = jtag_syspage_addr;

  	// Reserve a block of memory to store the address of the system page
	alloc_ram(jtag_syspage_address, sizeof(syspage_paddr), 1);
}
Exemple #2
0
// Save writeable data section of ELF executables
int rifs_save_elf32data(paddr32_t addr, union image_dirent *dir, int numboot)
{
	Elf32_Phdr 				*phdr;
	
	// Make sure the number of bootable executables isn't greater than the max	
	if(numboot >= RIFS_MAX_BOOTABLE)
		return(-1);
		
	// Read the ELF header	
	if((phdr = rifs_readelf(addr)))
	{
		if(debug_flag > RIFS_DEBUG_LEVEL)	
		{
			kprintf("Found procnto Elf header\n");
			kprintf("bootable exec data: offset %x, size %x\n", phdr->p_offset, phdr->p_filesz );
		}
		// Increment the number of bootable images found and save the related info
		rifs_info->numboot++;
		rifs_info->elfinfo[numboot].offset = dir->file.offset + phdr->p_offset;
		rifs_info->elfinfo[numboot].size = phdr->p_filesz;
	
		// If the image is compressed, save the data 
		if(shdr->flags1 & STARTUP_HDR_FLAGS1_COMPRESS_MASK)
		{
			if(debug_flag > RIFS_DEBUG_LEVEL)	
			{
				kprintf("Compressed image, store data\n");
			}
		
			// Allocate storage space. 
			// NOTE: We assume that the address will be the same everytime.
			// This should OK since the alloc_ram/find_ram algorithm is deterministic.
			rifs_info->elfinfo[numboot].data = alloc_ram(NULL_PADDR, rifs_info->elfinfo[numboot].size, sizeof(uint64_t));
			// Save a copy of the data	
			// NOTE: Use copy_memory to support mini-drivers
			copy_memory(rifs_info->elfinfo[numboot].data, 
					shdr->image_paddr + shdr->startup_size + rifs_info->elfinfo[numboot].offset, 
					rifs_info->elfinfo[numboot].size);
		}
	}
	else
	{
		if(debug_flag > RIFS_DEBUG_LEVEL)	
		{
			kprintf("Invalid ELF header\n");
		}
		// Error reading ELF header
		return(-1);
	}
	
	return(0);
}
Exemple #3
0
void
jtag_reserve_memory(paddr_t resmem_addr, size_t resmem_size, uint8_t resmem_flag) {
	void	*p;

    // Reserve user specified block of memory
	alloc_ram(resmem_addr, resmem_size, 1);
	p = startup_memory_map(resmem_size, resmem_addr, PROT_READ|PROT_WRITE);
	// Determine if reserved memory should be cleared
	if(!resmem_flag) {
		memset(p, 0, resmem_size);
	}
	startup_memory_unmap(p);
}
Exemple #4
0
// Load a secondary (non-bootable) image files system
int rifs_load_ifs2(void)
{
	struct image_header		*ifs2_hdr;

	ifs2_hdr = MAKE_1TO1_PTR(ifs2_paddr_dst);	
	
	// Set the default source location of IFS2 if the user didn't specify 
	if(!(rifs_flag & RIFS_FLAG_IFS2_SRC)) {
		// Look for 2nd IFS following directly after first IFS	
		ifs2_paddr_src = shdr->imagefs_paddr + shdr->stored_size - shdr->startup_size;
	}
	
	if(debug_flag > RIFS_DEBUG_LEVEL)	
	{
		kprintf("ifs2_paddr_src: 0x%X\r\n", ifs2_paddr_src);
		kprintf("ifs2_paddr_src (auto): 0x%X\r\n", shdr->imagefs_paddr + shdr->stored_size - shdr->startup_size);
	}
	
	// Reserve space for our 2nd IFS if it is a user specified location
	if(rifs_flag & RIFS_FLAG_IFS2_DST)
	{
		// Address must be on a 4K page boundary (handled by options parsing)
		alloc_ram(ifs2_paddr_dst, ifs2_size, 0x1000);	
	}

	// Copy 2nd IFS to RAM
	copy_memory(ifs2_paddr_dst, ifs2_paddr_src, ifs2_size);

	// Save the restore info for the next boot with SDRAM in self-refresh
	if(rifs_flag & RIFS_FLAG_IFS2_RESTORE) {
		char		sig[8] = RIFS_SIGNATURE; 
		int			i;
		
		// Initialize the signature	
		for(i = 0; i < 8; i++)
		{
			rifs2_info->signature[i] = sig[i];
		}
		
		// Save the image size to be used for the image checksum
		rifs2_info->image_size = ifs2_hdr->image_size;
		// Must initialize cksum to 0 before we can calculate cksum on data structure
		rifs2_info->cksum = 0;
	
		// Calculate the restore checksum such that a checksum will result in 0
		rifs2_info->cksum = 0xFFFFFFFF & (0x100000000ULL - rifs_checksum(rifs2_info, sizeof(struct restore_ifs2_info)));
	}
	
	return(0);
}
struct syspage_entry *
cpu_alloc_syspage_memory(paddr32_t *cpupagep, paddr32_t *syspagep, unsigned spsize)
{
	struct syspage_entry		*sp = lsp.syspage.p;
	struct system_private_entry	*private;
	unsigned					size;
	unsigned					cpsize;
	paddr32_t					syspage_paddr;
	unsigned					spacing;

	#define	SP_OFFSET(field)	PTR_DIFF(lsp.cpu.field.p, sp)
	#define	INIT_ENTRY(_cpu, _field) \
		sp->un._cpu._field.entry_size = lsp.cpu._cpu##_##_field.size; \
		sp->un._cpu._field.entry_off  = SP_OFFSET(_cpu##_##_field)

	spsize = ROUND(spsize, sizeof(uint64_t));
	if (sp->num_cpu == 1) {
		spacing = sizeof(struct cpupage_entry);
	}
	else {
		/*
		 * WARNING: we assume SMP processor has physical cache.
		 *          We allocate the cpupages in contiguous memory so that
		 *          the kernel's cpypageptr[] pointers point at virtually
		 *          contiguous mappings into the physical pages.
		 *          The user _cpupage_ptr is a different virtual address
		 *          where the same virtual address on each cpu maps the
		 *          different physical address for that cpu's cpupage.
		 */
		spacing = __PAGESIZE;
		spsize = ROUND(spsize, __PAGESIZE);
	}
	cpsize = sp->num_cpu * spacing;

	/*
	 * Allocate the system page (and cpupage entries) and save it away.
	 * The system page must be 4K aligned in a virtual system
	 */
	size = spsize + cpsize;

	syspage_paddr = alloc_ram(NULL_PADDR, size, lsp.system_private.p->pagesize);
	if (syspage_paddr == NULL_PADDR32) {
		crash("could not allocate 0x%l bytes for syspage/cpupage\n", size);
	}

	private = lsp.system_private.p;
Exemple #6
0
// Load a secondary (non-bootable) image file system
void load_ifs2_nonbootable(void)
{
	// Set the location of IFS2 in RAM if the user didn't specify 
	if(!(rifs_flag & RIFS_FLAG_IFS2_DST)) {
		// Find a default location to store our 2nd IFS (must by on a 4K page boundary)
		// NOTE: We assume that the address will be the same everytime.
		// This should OK since the alloc_ram/find_ram algorithm is deterministic.
		ifs2_paddr_dst = alloc_ram(NULL_PADDR, ifs2_size, 0x1000);
	}

	if(debug_flag > RIFS_DEBUG_LEVEL)	
	{
		kprintf("ifs2_paddr_dst: 0x%X\r\n", ifs2_paddr_dst);
	}
	
	// Attempt to restore IFS2 if it is already in RAM	
	if(!(rifs_flag & RIFS_FLAG_IFS2_RESTORE) || rifs_restore_ifs2() == -1) {
		// Normal (full) load of the non-bootable secondary IFS
		rifs_load_ifs2();
	}
}
uintptr_t
load_elf32(paddr32_t addr) {
	Elf32_Ehdr	hdr;
	Elf32_Phdr	*phdr;
	Elf32_Phdr	*phdr_start;
	int			i;
	
	if((phdr_start = is_elf(&hdr, addr)) == NULL) {
		return(~0L);
	}

	if(!(shdr->flags1 & STARTUP_HDR_FLAGS1_VIRTUAL)) {
		phdr = phdr_start;
		for(i = 0; i < hdr.e_phnum; ++i, ++phdr) {
			switch(phdr->p_type) {
			case PT_LOAD:
				if(MAKE_1TO1_PTR(phdr->p_paddr) != (void *)phdr->p_vaddr) {
					alloc_ram(phdr->p_vaddr - shdr->paddr_bias, phdr->p_memsz, 1);
					memmove((void *)phdr->p_vaddr,
						MAKE_1TO1_PTR(addr + phdr->p_offset),
						phdr->p_filesz);
					memset((void *)(phdr->p_vaddr+phdr->p_filesz), 0,
								phdr->p_memsz - phdr->p_filesz);
				}
				break;
			}
		}
#ifdef __X86__
	} else if(load_elf32mmu_4m(addr, &hdr, phdr_start)) {
		// Nothing to do
#endif
	} else {
		load_elf32mmu(addr, &hdr, phdr_start);
	}

	startup_memory_unmap(phdr_start);

	return hdr.e_entry;
}
Exemple #8
0
// Restore a secondary (non-bootable) image files system
int rifs_restore_ifs2(void)
{
	struct image_header		*ifs2_hdr;
	int						status = 0;
	paddr32_t				paddr;
	
	// Allocate memory for the restore IFS2 info.
	// NOTE: We assume that the address will be the same everytime.
	// This should OK since the alloc_ram/find_ram algorithm is deterministic.
	paddr = alloc_ram(NULL_PADDR, sizeof(struct restore_ifs2_info), sizeof(uint64_t));
	rifs2_info = MAKE_1TO1_PTR(paddr);
	
	if(debug_flag > RIFS_DEBUG_LEVEL)	
	{
		kprintf("Restore IFS2 searching for valid IFS in RAM...\n");
		kprintf("rifs2_info PADDR = 0x%X\n", paddr);
		kprintf("rifs2_info ADDR = 0x%X\n", rifs2_info);
	}
	
	// Obtain a pointer to the IFS2 that *may* be in RAM.  At this point, we still 
	// don't know if it is valid or if it is safe to access this data structure.	
	ifs2_hdr = MAKE_1TO1_PTR(ifs2_paddr_dst);	
	
	// Determine if there is already an IFS2 in RAM and if the restore 
	// information stored from the last boot is valid.
	if(check_ifs_signature(ifs2_hdr) == 0 && rifs_checksum(rifs2_info, sizeof(struct restore_ifs2_info)) == 0)
	{
		// At this point, we know that the IFS2 signature is valid and the 
		// restore info is valid.  We still can't be 100% sure that the IFS is
		// valid until we peform a checksum on the IFS2.
		
		if(debug_flag > RIFS_DEBUG_LEVEL)	
		{
			kprintf("FOUND valid IFS2 signature and RIFS2 info in RAM.\n");
		}
		
		// Determine if we should checksum the IFS		
		if((rifs_flag & RIFS_FLAG_IFS2_CKSUM))
		{
			// Checksum the entire IFS to make sure it hasn't been corrupted.
			if(rifs_checksum(ifs2_hdr, rifs2_info->image_size) != 0)
			{
				if(debug_flag > RIFS_DEBUG_LEVEL)	
				{
					kprintf("WARNING: Checksum failed on IFS2!\n");
				}
				// Checksum failed - IFS is corrupt
				status = -1;
			}
		}
		else
		{
			if(debug_flag > RIFS_DEBUG_LEVEL)	
			{
				kprintf("WARNING: Skipped IFS2 checksum verification\n");
			}
		}
	}
	else
	{	
		// No IFS2 or invalid restore data
		status = -1;
	}
	
	if((status == -1) && (debug_flag > RIFS_DEBUG_LEVEL))
	{
		kprintf("Restore IFS2 failed - Reload entire IFS2.\n");
	}
	
	return(status);
}
Exemple #9
0
// Restore an IFS already stored in RAM (i.e. CPU was turned off, RAM was left in self-refresh)
int rifs_restore_ifs(paddr32_t ifs_paddr)
{
	paddr32_t					paddr_dst, paddr_src;
	struct image_header			*ifs_hdr;
	int							status = 0;
	int							i;
	paddr32_t					paddr;
	
	// Allocate memory for the restore ifs info.
	// NOTE: We assume that the address will be the same everytime.
	// This should OK since the alloc_ram/find_ram algorithm is deterministic.
	paddr = alloc_ram(NULL_PADDR, sizeof(struct restore_ifs_info), sizeof(uint64_t));
	rifs_info = MAKE_1TO1_PTR(paddr);
	
	// Obtain a pointer to the IFS that *may* be in RAM.  At this point, we still 
	// don't know if it is valid or if it is safe to access this data structure.	
	ifs_hdr = MAKE_1TO1_PTR(ifs_paddr);	
	
	if(debug_flag > RIFS_DEBUG_LEVEL)	
	{
		kprintf("Restore IFS searching for valid IFS in RAM...\n");
		kprintf("rifs_info PADDR = 0x%X\n", paddr);
		kprintf("rifs_info ADDR = 0x%X\n", rifs_info);
	}
	
	// Determine if there is already an IFS in RAM and if the restore 
	// information stored from the last boot is valid.
	if(check_ifs_signature(ifs_hdr) == 0 && check_rifs_signature(rifs_info) == 0)
	{
		// At this point, we know that the IFS signature is valid and the 
		// restore info is valid.  We still can't be 100% sure that the IFS is
		// valid until we restore the IFS and peform a checksum.
		
		if(debug_flag > RIFS_DEBUG_LEVEL)	
		{
			kprintf("FOUND valid IFS signature and RIFS info in RAM.\n");
			kprintf("IFS pre checksum = 0x%X (should not be 0x0)\n", rifs_checksum(ifs_hdr, rifs_info->image_size));
		}
		
		// Loop through all bootable executables in the image and restore only 
		// the writeable data section to default/original values
		for(i = 0; i < rifs_info->numboot; i++)		
		{
			if(debug_flag > RIFS_DEBUG_LEVEL)	
			{
				kprintf("bootable exec %d offset: 0x%X\r\n", i, rifs_info->elfinfo[i].offset);
				kprintf("bootable exec %d size: 0x%X\r\n", i, rifs_info->elfinfo[i].size);
			}
			
			// Determine location of the executable's data	
			paddr_dst = shdr->image_paddr + shdr->startup_size + rifs_info->elfinfo[i].offset;
			
			// Determine if the image is compressed	
			if(shdr->flags1 & STARTUP_HDR_FLAGS1_COMPRESS_MASK)
			{
				// Compressed image
				if(debug_flag > RIFS_DEBUG_LEVEL)	
				{
					kprintf("Compressed image src = 0x%X\n", rifs_info->elfinfo[i].data);
				}
				// Copy over the previously saved data (dst & src both in the 1-to-1 mapping region)
				// NOTE: Use copy_memory to support mini-drivers
				copy_memory(paddr_dst, rifs_info->elfinfo[i].data, rifs_info->elfinfo[i].size);
			}
			else
			{
				// IFS in uncompressed, we can take the data directly from the source image
				paddr_src = shdr->imagefs_paddr + rifs_info->elfinfo[i].offset;
				if(debug_flag > RIFS_DEBUG_LEVEL)	
				{
					kprintf("Uncompressed image paddr_src = 0x%X\n", paddr_src);
				}
				
				// Copy over data from the original image (dst in the 1-to-1 mapping region, src may be anywhere)
				copy_memory(paddr_dst, paddr_src, rifs_info->elfinfo[i].size);
			}
		}
		
		if(debug_flag > RIFS_DEBUG_LEVEL)	
		{
			kprintf("IFS post checksum = 0x%X (should be 0x0)\n", rifs_checksum(ifs_hdr, rifs_info->image_size));
		}
		
		// Determine if we should checksum the IFS		
		if((rifs_flag & RIFS_FLAG_CKSUM))
		{
			// Checksum the entire IFS to determine if it has been restored correctly and hasn't been corrupted.
			if(rifs_checksum(ifs_hdr, rifs_info->image_size) != 0)
			{
				if(debug_flag > RIFS_DEBUG_LEVEL)	
				{
					kprintf("WARNING: Checksum failed on image!\n");
				}
				// Checksum failed - IFS is corrupt
				status = -1;
			}
		}
		else
		{
			if(debug_flag > RIFS_DEBUG_LEVEL)	
			{
				kprintf("WARNING: Skipped image checksum verification\n");
			}
		}
	}
	else
	{
		// No IFS or invalid restore data
		status = -1;
	}
	
	// Restore info is not initialized until after we have checked the old data
	rifs_init(rifs_info);
	
	if((status == -1) && (debug_flag > RIFS_DEBUG_LEVEL))
	{
		kprintf("Restore IFS failed - Reload entire IFS.\n");
	}
	
	return(status);
}
static void
load_elf32mmu(paddr32_t addr, Elf32_Ehdr *hdr, Elf32_Phdr *phdr) {
	int			i;

	for(i = 0; i < hdr->e_phnum; ++i, ++phdr) {
		switch(phdr->p_type) {
		case PT_LOAD:
			{
				size_t memsz  = phdr->p_memsz + (phdr->p_vaddr & PAGEBITS);
				size_t filesz = phdr->p_filesz + (phdr->p_vaddr & PAGEBITS);
				uintptr_t vaddr  = phdr->p_vaddr & ~PAGEBITS;
				paddr32_t paddr  = phdr->p_paddr & ~PAGEBITS;
				paddr32_t daddr;

				if((boot_vaddr_base == 0u) || (boot_vaddr_base > vaddr)){
					boot_vaddr_base = vaddr;
				}
				if(boot_vaddr_end < (vaddr + memsz)){
					boot_vaddr_end = vaddr + memsz;
				}
								
				if((phdr->p_flags & PF_W) == 0 && memsz == filesz) {
					filesz = memsz = ROUNDPG(filesz);
				}
				if(phdr->p_paddr != 0) {
					if (phdr->p_memsz == phdr->p_filesz) {
						// mkifs has padded out the data/bss section
						filesz = memsz = ROUNDPG(filesz);
					}
					elf_map(vaddr, paddr, filesz & ~PAGEBITS, phdr->p_flags);
					memsz = ROUNDPG(memsz - (filesz & ~PAGEBITS));
					if(memsz) {
						daddr = calloc_ram(memsz, __PAGESIZE);
						copy_memory(daddr, (paddr + (filesz & ~PAGEBITS)), filesz & PAGEBITS);
						elf_map(vaddr + (filesz & ~PAGEBITS), daddr, memsz, phdr->p_flags);
					}
				} else {
#ifndef BOOTSTRAPS_RUN_ONE_TO_ONE
	/*
	 * We need to do different things depending on whether the bootstrap
	 * executables a run in a physical <-> virtual one to one mapping
	 * area (MIPS, SH, PPC) or if they use the normal virtual address
	 * mapping gear (X86, ARM). Basically, is startup or procnto
	 * enabling the MMU on the CPU.
	 */
	#error BOOTSTRAPS_RUN_ONE_TO_ONE must be defined
#endif
#if BOOTSTRAPS_RUN_ONE_TO_ONE
					daddr = alloc_ram(vaddr - shdr->paddr_bias, ROUNDPG(memsz), __PAGESIZE);
					if(daddr != vaddr - shdr->paddr_bias) {
						crash("Error: can not allocate RAM for proc in XIP.\n");
					}
					memmove((void *)phdr->p_vaddr,
							MAKE_1TO1_PTR(addr + phdr->p_offset),
							phdr->p_filesz);
					memset((void *)(phdr->p_vaddr + phdr->p_filesz), 0,
								(phdr->p_memsz - phdr->p_filesz));
#else
					daddr = calloc_ram(ROUNDPG(memsz), __PAGESIZE);
					copy_memory(daddr, (addr + phdr->p_offset) - (phdr->p_vaddr & PAGEBITS), filesz);
					elf_map(vaddr, daddr, memsz, phdr->p_flags);
#endif
				}
			}
			break;
		}
	}
}