Example #1
0
// Load an elf file and export a section of it to a new file, without
// header, padding or checksum. For exporting the .irom0.text library.
// Produces error message on failure (so caller doesn't need to).
bool ExportElfSection(char *infile, char *outfile, char *name) {
	
	bool ret = false;
	FILE *fd = 0;
	MyElf_File *elf = 0;

	// load elf file
	elf = LoadElf(infile);
	if (!elf) {
		goto end_function;
	}

	// open output file
	fd = fopen(outfile, "wb");
    if(!fd) {
		error("Error: Can't open output file '%s' for writing.\r\n", outfile);
        goto end_function;
    }

	// actually do the export
	ret = WriteElfSection(elf, fd, name, false, false, false, 0);
        
end_function:
	// clean up
	if (fd) fclose(fd);
	UnloadElf(elf);
	
	return ret;
}
Example #2
0
//===============================================================================
// This loads the program "name" into memory, if it exists.
//===============================================================================
long DoExec(char *name, char *environment)
{
	struct FCB *fHandle;
	long argv, argc;
	int retval = -ENOEXEC;
	struct Message *FSMsg = ALLOCMSG;

	char *kname = AllocKMem((size_t) strlen(name) + 6); // Enough space for "/bin" + name

	strcpy(kname, "/bin/");
	strcat(kname, name);

	// Open file
	FSMsg->nextMessage = 0;
	FSMsg->byte = OPENFILE;
	FSMsg->quad1 = (long) kname;
	FSMsg->quad2 = (long) fHandle;
	SendReceiveMessage(FSPort, FSMsg);

	fHandle = (struct FCB *) FSMsg->quad1;

	if ((long) fHandle > 0)
	{
		char magic[5];
		char executable = 0;
		(void) SeekFile(FSMsg, fHandle, 10, SEEK_SET);
		(void) ReadFromFile(fHandle, magic, 4);
		magic[4] = 0;
		if (!strcmp(magic, "IJ64"))
		{
			(void) SeekFile(FSMsg, fHandle, 0, SEEK_SET);
			LoadFlat(fHandle);
			executable = 1;
		}
		else
		{
			(void) SeekFile(FSMsg, fHandle, 0, SEEK_SET);
			(void) ReadFromFile(fHandle, magic, 4);
			if (magic[0] == 0x7F)
			{
				(void) SeekFile(FSMsg, fHandle, 0, SEEK_SET);
				LoadElf(FSMsg, fHandle);
				executable = 1;
			}
		}

		//Close file and deallocate memory for structures
		FSMsg->nextMessage = 0;
		FSMsg->byte = CLOSEFILE;
		FSMsg->quad1 = (long) fHandle;
		SendReceiveMessage(FSPort, FSMsg);
		DeallocMem(kname);
		DeallocMem(FSMsg);

		if (executable)
		{
			long *l;

			// Process the arguments for argc and argv
			// Copy environment string to user data space
			// It occupies the 81 bytes after the current first free memory
			currentTask->environment = (void *) currentTask->firstfreemem;
			memcpy(currentTask->environment, environment, 80);
			currentTask->firstfreemem += 80;
			argv = (long) currentTask->environment;
			argc = ParseEnvironmentString(&argv);
			argv += 80;

			// Adjust firstfreemem to point to the first free memory location.
			currentTask->firstfreemem += argc * sizeof(char *);

			// Build the first MemStruct struct. Is all this necessary? User tasks don't use the kernel memory allocation, do they?
			l = (long *) (currentTask->firstfreemem);
			*l = 0;
			*(l + 1) = -(long) (((sizeof(struct MemStruct)
					+ currentTask->firstfreemem)) % PageSize);
			asm("mov %0,%%rdi;" "mov %1,%%rsi":
					: "r"(argc), "r"(argv):"%rax", "%rdi");
			return 0;
		}
		else
			return retval;
Example #3
0
// Create the main binary firmware image, from specified elf sections.
// Can produce for standard standalone app (separate .irom0.text)
// or sdk bootloaded apps (integrated .irom0.text).
// Choice of type requires appropriately linked elf file.
// Produces error message on failure (so caller doesn't need to).
bool CreateBinFile(char *elffile, char *imagefile, int bootver, unsigned char mode,
	unsigned char clock, unsigned char size, bool iromchksum, char *sections[], int numsec) {

	bool ret = false;
	int i, pad, len;
	unsigned char chksum = CHECKSUM_INIT;
	unsigned char *data = 0;
	FILE *outfile = 0;
	MyElf_File *elf = 0;
	Image_Header imghead;
	
	// load elf file
	elf = LoadElf(elffile);
	if (!elf) {
		goto end_function;
	}
    
	// open output file
	outfile = fopen(imagefile, "wb");
	if(outfile == NULL) {
		error("Error: Failed to open output file '%s' for writing.\r\n", imagefile);
		goto end_function;
	}

	// set options common to standard and boot v1.2+ headers
	imghead.byte2 = mode;
	//imghead.byte3 = (int)((int)size << 4 | clock) && 0xff;
	imghead.byte3 = ((size << 4) | clock) & 0xff;
	imghead.entry = elf->header.e_entry;
	debug("Size = %02x\r\n", size);
	debug("Byte2 = %02x\r\n", imghead.byte2);
	debug("Byte3 = %02x\r\n", imghead.byte3);
	debug("Entry = %08x\r\n", imghead.entry);

	// boot v1.2+ header
	if (bootver == 2) {
		// extra header
		imghead.magic = BIN_MAGIC_IROM;
		imghead.count = 4; // probably a version number here, not a count
		if(fwrite(&imghead, 1, sizeof(imghead), outfile) != sizeof(imghead)) {
			error("Error: Failed to write header to image file.\r\n");
			goto end_function;
		}
		if(!WriteElfSection(elf, outfile, ".irom0.text", true, true, IMAGE_PADDING, (iromchksum ? &chksum : 0))) {
			goto end_function;
		}
	}

	// standard header
    imghead.magic = BIN_MAGIC_FLASH;
    imghead.count = numsec;
	// write header
	if(fwrite(&imghead, 1, sizeof(imghead), outfile) != sizeof(imghead)) {
		error("Error: Failed to write header to image file.\r\n");
		goto end_function;
	}

	// add sections
	for (i = 0; i < numsec; i++) {
		if(!WriteElfSection(elf, outfile, sections[i], true, false, SECTION_PADDING, &chksum)) {
			goto end_function;
		}
	}
	
	// get image length (plus a byte for the checksum)
	len = ftell(outfile) + 1;

	// do we need to pad the image?
	pad = len % IMAGE_PADDING;
	if (pad > 0) {
		pad = IMAGE_PADDING - pad;
		debug("Padding image with %d byte(s).\r\n", pad);
		if(fwrite(PADDING, 1, pad, outfile) != pad) {
			error("Error: Failed to write padding to image file.\r\n");
			goto end_function;
		}
	}

	// write checksum
	if(fwrite(&chksum, 1, 1, outfile) != 1) {
        error("Error: Failed to write checksum to image file.\r\n");
		goto end_function;
    }

	// boot v1.1
	if(bootver == 1) {
		// write 'ff' padding up to the position of the library
		len = 0x10000 - ftell(outfile);
		debug("Adding boot v1.1 padding, %d bytes of '0xff'.\r\n", len);
		data = (unsigned char*)malloc(len);
		memset(data, 0xff, len);
		if(fwrite(data, 1, len, outfile) != len) {
			error("Error: Failed to write boot v1.1 spacer.\r\n");
			goto end_function;
		}

		// write the library
		if(!WriteElfSection(elf, outfile, ".irom0.text", false, false, 0, 0)) {
			goto end_function;
		}
	}

	// if we got this far everything worked!
	ret = true;

end_function:
	// clean up
	if (outfile) fclose(outfile);
	if (data) free(data);
	if (elf) UnloadElf(elf);
	
	return ret;
}
Example #4
0
// Create the main binary firmware image, from specified elf sections.
// Can produce for standard standalone app (separate .irom0.text)
// or sdk bootloaded apps (integrated .irom0.text).
// Choice of type requires appropriately linked elf file.
// Produces error message on failure (so caller doesn't need to).
bool CreateHeaderFile(char *elffile, char *imagefile, char *sections[], int numsec) {

	bool ret = false;
	int i;
	unsigned int j, len;
	FILE *outfile = 0;
	MyElf_File *elf = 0;
	MyElf_Section *sect;
	unsigned char *bindata = 0;
	char name[31];
	
	// load elf file
	elf = LoadElf(elffile);
	if (!elf) {
		goto end_function;
	}
    
	// open output file
	outfile = fopen(imagefile, "wb");
	if(outfile == NULL) {
		error("Error: Failed to open output file '%s' for writing.\r\n", imagefile);
		goto end_function;
	}

	// add entry point
	fprintf(outfile, "const uint32 entry_addr = 0x%08x;\r\n", elf->header.e_entry);

	// add sections
	for (i = 0; i < numsec; i++) {
		// get elf section header
		sect = GetElfSection(elf, sections[i]);
		if(!sect) {
			error("Error: Section '%s' not found in elf file.\r\n", sections[i]);
			goto end_function;
		}

		// simple name fix name
		strncpy(name, sect->name, 31);
		len = strlen(name);
		for (j = 0; j < len; j++) {
			if (name[j] == '.') name[j] = '_';
		}

		// add address, length and start the data block
		debug("Adding section '%s', addr: 0x%08x, size: %d.\r\n", sections[i], sect->address, sect->size);
		fprintf(outfile, "\r\nconst uint32 %s_addr = 0x%08x;\r\nconst uint32 %s_len = %d;\r\nconst uint8  %s_data[] = {",
			name, sect->address, name, sect->size, name);

		// get elf section binary data
		bindata = GetElfSectionData(elf, sect);
		if (!bindata) {
			goto end_function;
		}

		// add the data and finish off the block
		for (j = 0; j < sect->size; j++) {
			if (j % 16 == 0) fprintf(outfile, "\r\n  0x%02x,", bindata[j]);
			else fprintf(outfile, " 0x%02x,", bindata[j]);
		}
		fprintf(outfile, "\r\n};\r\n");
		free(bindata);
		bindata = 0;
	}
	
	// if we got this far everything worked!
	ret = true;

end_function:
	// clean up
	if (outfile) fclose(outfile);
	if (elf) UnloadElf(elf);
	if (bindata) free(bindata);
	
	return ret;
}
Example #5
0
int
LoadAndStartApplication(UID pid,
                        void *elf_loc,
                        uint64_t elf_size,
                        const char *argv,
                        uint32_t argc,
                        uint64_t arg_len) {
    ElfInformation elf_info;
    ElfLoaderError err = LoadElf(elf_loc, elf_size, ElfLimitations_64Bit | ElfLimitations_LSB, pid, &elf_info);
    if(err != ElfLoaderError_Success)
        return -1;

    //Put argv, argc and elf info into at most 4 pages, take the physical address, unmap the page
    //Map the page to the same virtual address in the target process as read/write
    //Pass the pointer as a parameter to the thread

    uint64_t net_size = argc * sizeof(char*) + arg_len + sizeof(struct ElfSetupParameters);

    if(net_size % PAGE_SIZE)
        net_size += (PAGE_SIZE - (net_size % PAGE_SIZE));

    uint64_t phys_addr = 0;
    struct ElfSetupParameters *params = NULL;//MAP

    if(R0_AllocatePages(net_size / PAGE_SIZE, PhysicalMemoryAllocationFlags_None, &phys_addr) != 0)
        return -3;

    //Map the memory into the current process to allow editing
    if(R0_Map(GetCurrentProcessUID(),
              phys_addr,
              (uint64_t*)&params,
              net_size,
              CachingModeWriteBack,
              MemoryAllocationType_Application |
              MemoryAllocationType_Phys,
              MemoryAllocationFlags_NoExec |
              MemoryAllocationFlags_Read |
              MemoryAllocationFlags_Write |
              MemoryAllocationFlags_User |
              MemoryAllocationFlags_Present))
        return -4;

    //Map the memory into the target process
    uint64_t target_virt_addr = 0;
    if(R0_Map(pid,
              phys_addr,
              &target_virt_addr,
              net_size,
              CachingModeWriteBack,
              MemoryAllocationType_MMap,
              MemoryAllocationFlags_NoExec |
              MemoryAllocationFlags_Read |
              MemoryAllocationFlags_Write |
              MemoryAllocationFlags_User |
              MemoryAllocationFlags_Present))
        return -5;

    params->ver = 1;
    params->size = net_size;
    params->page_size = PAGE_SIZE;
    params->argc = argc;
    params->rnd_seed = 0;         //Set the seed to 0 for now, secondary loader will set it properly
    params->elf_entry_point = (uint64_t)elf_info.entry_point;

    uint8_t **argv_base = (uint8_t**)params->argv;
    uint8_t *arg_loc = (uint8_t*)argv_base + sizeof(char*) * argc;

    for(uint32_t i = 0; i < argc; i++) {
        argv_base[i] = (char*)(target_virt_addr + ((uint64_t)arg_loc - (uint64_t)params));

        uint32_t len = strlen(argv) + 1;
        strcpy(arg_loc, argv);
        argv += len;
        arg_loc += len;
    }

    R0_Unmap(GetCurrentProcessUID(), (uint64_t)params, net_size);

    // We're no longer following the SysV Linux ABI, so just map in the data and
    // pass the virtual address.


    UID tid = 0;
    int (*entry_point)(void*) = (int(*)(void*))elf_info.entry_point;
    if(R0_CreateThread(pid, entry_point, (void*)target_virt_addr, &tid) != 0)
        return -6;

    return 0;
}