예제 #1
0
	void Texture::load(std::string filename)
	{
		uint8 *data;
		file_t fd = fs_open(filename.c_str(), O_RDONLY);
		data = new uint8[fs_total(fd)];
		fs_read(fd, data, fs_total(fd));
		fs_close(fd);
		
		memcpy(&header, data, sizeof(HeaderStruct));
		
		assert_msg(Texture::formatTag.compare(header.formatTag) == 0, "Wrong texture format OR version");
		
		/* Read texture */
		uint16 *tdata = new uint16[header.byteCount];
		memcpy(tdata, &data[0x18], header.byteCount);
		
		int pvrfmt = -1;
		if(header.format == KOS_IMG_FMT_ARGB1555) pvrfmt = PVR_TXRFMT_ARGB1555;
		else if(header.format == KOS_IMG_FMT_ARGB4444) pvrfmt = PVR_TXRFMT_ARGB4444;
		assert_msg(pvrfmt != -1, "Cannot determine PVR texture format");
		
		sys->debugLog(" -> size %lu*%lu, KOS format %lu, pvr format %i, byteCount %08lx\n", header.width, header.height, header.format, pvrfmt, header.byteCount);
		
		texture = plx_txr_canvas(header.width, header.height, pvrfmt);
		pvr_txr_load_ex(tdata, texture->ptr, texture->w, texture->h, PVR_TXRLOAD_16BPP);
		
		delete[] tdata;
		
		delete[] data;
	}
예제 #2
0
파일: utils.c 프로젝트: WinCoder/DreamShell
int snd_init_firmware(const char *filename) {
	file_t f;
	size_t sz;
	uint8 *buff;
	
	f = fs_open(filename, O_RDONLY);
	
	if(f < 0) {
		ds_printf("DS_ERROR: Can't open firmware %s\n", filename);
		return -1;
	}
	
	sz = fs_total(f);
	ds_printf("DS_PROCESS: Loading firmware %s (%d bytes) into SPU RAM\n", filename, sz);
	
	buff = (uint8*)malloc(sz);
	fs_read(f, buff, sz);
	fs_close(f);
	
	spu_disable();
	spu_memset(0, 0, AICA_RAM_START);
	spu_memload(0, buff, sz);

	/* Enable the AICA and give it a few ms to start up */
	spu_enable();
	timer_spin_sleep(10);

	/* Initialize the RAM allocator */
	snd_mem_init(AICA_RAM_START);
	return 0;
}
예제 #3
0
파일: conio.c 프로젝트: zig/kos-dcplaya
/* Check to see if a key has been pressed */
int conio_check_getch() {
	int key = -1;
	uint8 b;

	switch (conio_ttymode) {
		case CONIO_TTY_PVR:
#ifdef GFX
			key = kbd_get_key();
#endif
			break;
		case CONIO_TTY_SERIAL: {
			key = scif_read();

			if (key == 3)
				arch_exit();
	
			break;
		}
		case CONIO_TTY_STDIO:
			if (fs_total(conio_serial_fd) > 0) {
				if (fs_read(conio_serial_fd, &b, 1) == 1)
					key = b;
			}
			if (key == '\n')
				key = -1;
			break;
	}

	return key;
}
예제 #4
0
파일: spu.c 프로젝트: Corbachu/KallistiOS
int main(int argc, char **argv) {
    file_t f;
    int len;

    /* Open the S3M file from the romdisk */
    f = fs_open("/rd/cyboman.s3m", O_RDONLY);

    /* Get its length */
    len = fs_total(f);

    /* mmap() the file space; note that this ONLY works on rom file
       systems for now; this may change later */
    song = fs_mmap(f);

    /* Start a song playing */
    copy_s3m(song, len);

    /* Close the file */
    fs_close(f);

    /* Wait for start */
    wait_start();

    return 0;
}
예제 #5
0
파일: utils.c 프로젝트: WinCoder/DreamShell
int CopyFile(const char *src_fn, const char *dest_fn, int verbose) {
	
	size_t cnt, size, cur = 0, buf_size;
	file_t src_fd, dest_fd;
	uint8 *buff;
	
	if(verbose) {
		ds_printf("DS_PROCESS: Copying file: %s to %s\n", src_fn, dest_fn);
	}

	src_fd = fs_open(src_fn, O_RDONLY);

	if (src_fd == FILEHND_INVALID) {
		ds_printf("DS_ERROR: Can't open %s for read\n", src_fn);
		return 0;
	}

	dest_fd = fs_open(dest_fn, O_WRONLY | O_CREAT);

	if (dest_fd == FILEHND_INVALID) {
		ds_printf("DS_ERROR: Can't open %s for write\n", dest_fn);
		fs_close(src_fd);
		return 0;
	}

	size = fs_total(src_fd) / 1024;

	if(size >= 256) {
		buf_size = 32 * 1024;
	} else if(size < 32 && size > 8) {
		buf_size = 1024;
	} else if(size <= 8) {
		buf_size = 512;
	} else {
		buf_size = 16 * 1024;
	}

	buff = (uint8 *) memalign(32, buf_size);

	if(buff == NULL) {
		ds_printf("DS_ERROR: No memory: %d bytes\n", buf_size); 
		return 0;
	}

	while ((cnt = fs_read(src_fd, buff, buf_size)) > 0) {
		
		cur += cnt;
		
		if(fs_write(dest_fd, buff, cnt) < 0) {
			break;
		}
	}

	fs_close(dest_fd);
	fs_close(src_fd);
	free(buff);
	return 1;
}
예제 #6
0
파일: utils.c 프로젝트: WinCoder/DreamShell
int FileSize(const char *fn) {

	int size;
	file_t f = fs_open(fn, O_RDONLY); 

	if(f == FILEHND_INVALID) {
		return -1; 
	}

	size = fs_total(f);
	fs_close(f);
	return size;
}
예제 #7
0
	void Font::load(std::string filename)
	{
		uint8 *data;
		file_t fd = fs_open(filename.c_str(), O_RDONLY);
		data = new uint8[fs_total(fd)];
		fs_read(fd, data, fs_total(fd));
		fs_close(fd);
		
		uint32 rofs;
		memcpy(&header, data, sizeof(HeaderStruct));
		
		assert_msg(Font::formatTag.compare(header.formatTag) == 0, "Wrong font format OR version");
		
		/* Read characters */
		rofs = header.characterDataOffset;
		memcpy(&characterList.characterCount, &data[rofs], 4);
		rofs += 4;
		
		characterList.characters = new CharacterDataStruct[characterList.characterCount];
		memcpy(characterList.characters, &data[rofs], (sizeof(CharacterDataStruct) * characterList.characterCount));
		
		/* Read font texture */
		rofs = header.fontTextureOffset;
		int w = 0, h = 0, fmt = 0, byte_count = 0;
		memcpy(&w, &data[rofs], 4);
		memcpy(&h, &data[rofs + 0x4], 4);
		memcpy(&fmt, &data[rofs + 0x8], 4);
		memcpy(&byte_count, &data[rofs + 0xC], 4);
		
		uint32 *tdata = new uint32[byte_count];
		memcpy(tdata, &data[rofs + 0x10], byte_count);
		
		texture = plx_txr_canvas(w, h, PVR_TXRFMT_ARGB4444);
		pvr_txr_load_ex(tdata, texture->ptr, texture->w, texture->h, PVR_TXRLOAD_16BPP);
		
		delete[] tdata;
		
		delete[] data;
	}
예제 #8
0
void netcfg_vmuify(const char *filename_in, const char *filename_out) {
    int fd, pkg_size;
    uint8   *buf;
    uint8   *pkg_out;
    vmu_pkg_t pkg;

    dbgp("Opening source file\n");
    fd = fs_open(filename_in, O_RDONLY);
    buf = (uint8 *) malloc(fs_total(fd));
    fs_read(fd, buf, fs_total(fd));
    dbgp("Read %i bytes\n", fs_total(fd));

    strcpy(pkg.desc_short, "KallistiOS 1.3");
    strcpy(pkg.desc_long, "KOS Network Settings");
    strcpy(pkg.app_id, "KOS");
    pkg.icon_cnt = 1;
    pkg.icon_anim_speed = 1;
    memcpy(&pkg.icon_pal[0], netcfg_icon, 32);
    pkg.icon_data = netcfg_icon + 32;
    pkg.eyecatch_type = VMUPKG_EC_NONE;
    pkg.data_len = fs_total(fd);
    pkg.data = buf;
    dbgp("Building package\n");
    vmu_pkg_build(&pkg, &pkg_out, &pkg_size);
    fs_close(fd);
    dbgp("Closing source file\n");

    dbgp("Opening output file\n");
    fd = fs_open(filename_out, O_WRONLY);
    dbgp("Writing..\n");
    fs_write(fd, pkg_out, pkg_size);
    dbgp("Closing output file\n");
    fs_close(fd);
    free(buf);
    dbgp("VMUification complete\n");
}
예제 #9
0
/* Copies a file from 'src' to 'dst'. The amount of the file
   actually copied without error is returned. */
ssize_t fs_copy(const char * src, const char * dst) {
	char	*buff;
	ssize_t	left, total, r;
	file_t	fs, fd;

	/* Try to open both files */
	fs = fs_open(src, O_RDONLY);
	if (fs == FILEHND_INVALID) {
		return -1;
	}

	fd = fs_open(dst, O_WRONLY | O_TRUNC);
	if (fd == FILEHND_INVALID) {
		fs_close(fs);
		return -2;
	}

	/* Get the source size */
	left = fs_total(fs);
	total = 0;

	/* Allocate a buffer */
	buff = malloc(65536);

	/* Do the copy */
	while (left > 0) {
		r = fs_read(fs, buff, 65536);
		if (r <= 0)
			break;
		fs_write(fd, buff, r);
		left -= r;
		total += r;
	}

	/* Free the buffer */
	free(buff);

	/* Close both files */
	fs_close(fs);
	fs_close(fd);

	return total;
}
예제 #10
0
/* Opens a file, allocates enough RAM to hold the whole thing,
   reads it into RAM, and closes it. The caller owns the allocated
   memory (and must free it). The file size is returned, or -1  
   on failure; on success, out_ptr is filled with the address    
   of the loaded buffer. */
ssize_t fs_load(const char * src, void ** out_ptr) {
	file_t	f;
	void	* data;
	uint8	* out;
	ssize_t	total, left, r;

	assert( out_ptr != NULL );
	*out_ptr = NULL;

	/* Try to open the file */
	f = fs_open(src, O_RDONLY);
	if (f == FILEHND_INVALID)
		return -1;

	/* Get the size and alloc a buffer */
	left = fs_total(f);
	total = 0;
	data = malloc(left);
	out = (uint8 *)data;

	/* Load the data */
	while (left > 0) {
		r = fs_read(f, out, left);
		if (r <= 0)
			break;
		left -= r;
		total += r;
		out += r;
	}

	/* Did we get it all? If not, realloc the buffer */
	if (left > 0) {
		*out_ptr = realloc(data, total);
		if (*out_ptr == NULL)
			*out_ptr = data;
	} else
		*out_ptr = data;

	fs_close(f);

	return total;
}
예제 #11
0
파일: exec.c 프로젝트: losinggeneration/kos
int main(int argc, char **argv) {
	file_t f;
	void *subelf;

	/* Print a hello */
	printf("\n\nHello world from the exec.elf process\n");

	/* Map the sub-elf */
	f = fs_open("/rd/sub.bin", O_RDONLY);
	assert( f );
	subelf = fs_mmap(f);
	assert( subelf );

	/* Tell exec to replace us */
	printf("sub.bin mapped at %08x, jumping to it!\n\n\n", subelf);
	arch_exec(subelf, fs_total(f));

	/* Shouldn't get here */
	assert_msg( false, "exec call failed" );

	return 0;
}
예제 #12
0
int bflash_auto_reflash(const char *file, uint32 start_sector, int erase_mode) {

	file_t f;
	uint8 *ptr;
	uint32 len;
	int	i, b_idx;
	bflash_dev_t *dev = NULL;
	bflash_manufacturer_t *mrf = NULL;
	
	if(bflash_detect(&mrf, &dev) < 0) {
		return -1;
	}
	
	if(!(dev->flags & F_FLASH_PROGRAM)) {
		ds_printf("DS_ERROR: %s %s flash chip is not programmable.\n", mrf->name, dev->name);
		return -1;
	}

	f = fs_open(file, O_RDONLY);
	
	if (f < 0) {
		ds_printf("DS_ERROR: Couldn't open %s\n", file);
		return -1;
	}
	
	len = fs_total(f);
	
	if((len / 1024) > dev->size) {
		ds_printf("DS_ERROR: The firmware larger than a flash chip (%d KB vs %d KB).\n", (len / 1024), dev->size);
		fs_close(f);
		return -1;
	}
	
	ds_printf("DS_PROCESS: Loading firmware in to memory...\n");
	ptr = (uint8 *) malloc(len);

	if(ptr == NULL) {
		ds_printf("DS_ERROR: Not enough memory\n");
		fs_close(f);
		return -1;
	}

	memset(ptr, 0, len);
	fs_read(f, ptr, len);
	fs_close(f);

	ds_printf("DS_WARTING: Don't power off your DC and don't switch the bios!\n");
	
	EXPT_GUARD_BEGIN;
	
		b_idx = bflash_get_sector_index(dev, start_sector);
		
		if(b_idx < 0) {
			ds_printf("DS_ERROR: Uknown sector addr 0x%08x\n", start_sector);
			free(ptr);
			EXPT_GUARD_RETURN -1;
		}
		
		if(erase_mode) {
			
			ds_printf("DS_PROCESS: Erasing flash chip...\n");
			
			if(erase_mode == F_FLASH_ERASE_ALL) {
				
				if (bflash_erase_all(dev) < 0) {
					free(ptr);
					EXPT_GUARD_RETURN -1;
				}
				
			} else if(erase_mode == F_FLASH_ERASE_SECTOR) {
			
				for (i = b_idx; i < dev->sec_count; i++) {
					
					if (dev->sectors[i] >= (len + dev->sectors[b_idx]))
						break;
					
					ds_printf("DS_PROCESS: Erasing sector: 0x%08x\n", dev->sectors[i]);
					
					if (bflash_erase_sector(dev, dev->sectors[i]) < 0) {
						free(ptr);
						EXPT_GUARD_RETURN -1;
					}
				}
				
			} else {
				ds_printf("DS_ERROR: Unsupported erase mode: %04x\n", erase_mode);
				free(ptr);
				EXPT_GUARD_RETURN -1;
			}
			
		} else {
			ds_printf("DS_WARNING: Writing to flash without erasing.\n");
		}

		ds_printf("DS_PROCESS: Writing firmware (%d KB) into the flash chip...\n", len / 1024);
		
		if (bflash_write_data(dev, start_sector, ptr, len) < 0) {
			free(ptr);
			EXPT_GUARD_RETURN -1;
		}
	
	EXPT_GUARD_CATCH;
	
		ds_printf("DS_ERROR: Fatal error in reflash process.\n");
		ds_printf("DS_WARNING: Maybe when you reboot your DC can't boot from the current bios.\n");
		ds_printf("DS_INFO: Try to reflash again without rebooting.\n");
		free(ptr);
		EXPT_GUARD_RETURN -1;
		
	EXPT_GUARD_END;

	free(ptr);
	ds_printf("DS_OK: Firmware written successfully\n");
	return 0;
}
예제 #13
0
파일: module.c 프로젝트: i-rom/DreamShell
void Speedtest_Run(GUI_Widget *widget) {

	uint8 *buff = (uint8*)0x8c400000;
	size_t buff_size = 0x10000;
	int size = 0x800000, cnt = 0, rs; 
	int64 time_before, time_after;
	uint32 t;
	double speed;
	file_t fd;
	int read_only = 0;
	
	char name[64];
	char result[128];
	const char *wname = GUI_ObjectGetName((GUI_Object *)widget);
	
	if(!strncasecmp(wname, "/cd", 3)) {
		
		read_only = 1;
		snprintf(name, sizeof(name), "%s/1DS_CORE.BIN", wname);

		if(FileExists(name)) {
			goto readtest;
		} else {
			snprintf(name, sizeof(name), "%s/1ST_READ.BIN", wname);
			goto readtest;
		}
	}
	
	show_status_ok("Testing WRITE speed...");
	GUI_LabelSetText(self.speedwr, "...");
	GUI_LabelSetText(self.speedrd, "   ");
	
	snprintf(name, sizeof(name), "%s/%s.tst", wname, lib_get_name());
	
	if(FileExists(name)) {
		fs_unlink(name);
	}
	
	/* WRITE TEST */
	fd = fs_open(name, O_CREAT | O_WRONLY);
	
	if (fd == FILEHND_INVALID) {
		ds_printf("DS_ERROR: Can't open %s for write: %d\n", name, errno);
		show_status_error("Can't open file for write");
		return;
	}

	ShutdownVideoThread(); 
	time_before = timer_ms_gettime64();
	
	while(cnt < size) {
		
		rs = fs_write(fd, buff, buff_size);
		
		if(rs <= 0) {
			fs_close(fd);
			InitVideoThread(); 
			ds_printf("DS_ERROR: Can't write to file: %d\n", errno);
			show_status_error("Can't write to file");
			return;
		}
		
		buff += rs;
		cnt += rs;
	}
	
	time_after = timer_ms_gettime64();
	InitVideoThread();
	
	t = (uint32)(time_after - time_before);
	speed = size / ((float)t / 1000);
	fs_close(fd);
	
	snprintf(result, sizeof(result), 
				"Write speed %.2f Kbytes/s (%.2f Mbit/s) Time: %ld ms",
				speed / 1024, ((speed / 1024) / 1024) * 8, t);
	
	GUI_LabelSetText(self.speedwr, result);
	show_status_ok("Complete!"); 
	
	ds_printf("DS_OK: Complete!\n"
				" Test: write\n Time: %ld ms\n"
				" Speed: %.2f Kbytes/s (%.2f Mbit/s)\n"
				" Size: %d Kb\n Buff: %d Kb\n", 
				t, speed / 1024, 
				((speed / 1024) / 1024) * 8, 
				size / 1024, buff_size / 1024); 
				
readtest:

	show_status_ok("Testing READ speed...");
	GUI_LabelSetText(self.speedrd, "...");

	/* READ TEST */
	fd = fs_open(name, O_RDONLY);
	
	if (fd == FILEHND_INVALID) {
		ds_printf("DS_ERROR: Can't open %s for read: %d\n", name, errno);
		show_status_error("Can't open file for read");
		return;
	}

	if(read_only) {
		GUI_LabelSetText(self.speedwr, "Write test passed");
		/* Reset ISO9660 filesystem cache */
		fs_ioctl(fd, NULL, 0);
		fs_close(fd);
		fd = fs_open(name, O_RDONLY);
	}
	
	time_before = time_after = t = cnt = 0;
	speed = 0.0f;
	size = fs_total(fd);
	buff = rd_buff;

	ShutdownVideoThread();
	time_before = timer_ms_gettime64();

	while(cnt < size) {
		
		rs = fs_read(fd, buff, buff_size);
		
		if(rs <= 0) {
			fs_close(fd);
			InitVideoThread(); 
			ds_printf("DS_ERROR: Can't read file: %d\n", errno);
			show_status_error("Can't read file");
			return;
		}
		
		cnt += rs;
	}
	
	time_after = timer_ms_gettime64();
	t = (uint32)(time_after - time_before);
	speed = size / ((float)t / 1000);
	fs_close(fd);
	
	if(!read_only) { 
		fs_unlink(name);
	} else {
		cdrom_spin_down();
	}
	
	snprintf(result, sizeof(result), 
			"Read speed %.2f Kbytes/s (%.2f Mbit/s) Time: %ld ms",
			speed / 1024, ((speed / 1024) / 1024) * 8, t);
	
	InitVideoThread();
	
	ds_printf("DS_OK: Complete!\n"
				" Test: read\n Time: %ld ms\n"
				" Speed: %.2f Kbytes/s (%.2f Mbit/s)\n"
				" Size: %d Kb\n Buff: %d Kb\n", 
				t, speed / 1024, 
				((speed / 1024) / 1024) * 8, 
				size / 1024, buff_size / 1024);
    
	GUI_LabelSetText(self.speedrd, result);
	show_status_ok("Complete!"); 
}
예제 #14
0
파일: module.c 프로젝트: DC-SWAT/DreamShell
int BiosFlasher_CompareBiosWithFile(const char* filename, BiosFlasher_OperationCallback guiClbk)
{
	uint8* data 	= 0;
	file_t pFile 	= 0;

	UPDATE_GUI(eReading, 0.0f, guiClbk);
	// Detect writible flash
	bflash_dev_t *dev = NULL;
	bflash_manufacturer_t *mrf = NULL;
	if (bflash_detect(&mrf, &dev) < 0) 
	{
		ds_printf("DS_ERROR: flash chip detection error.\n");
		return eDetectionFail;
	}
	
	// Read bios file from file to memory
	pFile = fs_open(filename, O_RDONLY);
	if (pFile == FILEHND_INVALID)
	{
		ds_printf("DS_ERROR: Can't open bios file: %s.\n", filename);
		return eFileFail;
	}
	
	size_t fileSize = fs_total(pFile);
	if (fileSize > dev->size * 1024) 
	{
		ds_printf("DS_ERROR: The firmware larger than a flash chip (%d KB vs %d KB).\n", (fileSize / 1024), dev->size);
		fs_close(pFile);
		return eDataMissmatch;
	}

	data = (uint8 *) memalign(32, CHUNK_SIZE);
	if(data == NULL) 
	{
		ds_printf("DS_ERROR: Not enough memory\n");
		fs_close(pFile);
		return eUnknownFail;
	}

	int ret = eSuccess;
	int i = 0;
	size_t chunkCount = fileSize / CHUNK_SIZE;
	size_t dataPos, dataLen, readLen;
	
	for (i = 0; i <= chunkCount; ++i)
	{

		dataPos = i * CHUNK_SIZE;
		dataLen = (dataPos + CHUNK_SIZE > fileSize) ? fileSize - dataPos : CHUNK_SIZE;

		UPDATE_GUI(eReading, (float)i / chunkCount, guiClbk);
		
		readLen = fs_read(pFile, data, dataLen);
		if (readLen != dataLen)
		{
			ds_printf("DS_ERROR: Part of file wasn't loaded to memory\n");
			free(data);
			fs_close(pFile);
			return eFileFail;
		}

		if (memcmp(data, (uint8*)BIOS_FLASH_ADDR + dataPos, dataLen) != 0)
		{
			ret = eDataMissmatch;
			break;
		}
	}

	free(data);
	fs_close(pFile);

	return ret;
}
예제 #15
0
파일: module.c 프로젝트: DC-SWAT/DreamShell
int BiosFlasher_WriteBiosFileToFlash(const char* filename, BiosFlasher_OperationCallback guiClbk)
{
	size_t i = 0;
	uint8* data 	= 0;
	file_t pFile 	= 0;

	UPDATE_GUI(eReading, 0.0f, guiClbk);
	// Detect writible flash
	bflash_dev_t *dev = NULL;
	bflash_manufacturer_t *mrf = NULL;
	if( bflash_detect(&mrf, &dev) < 0   ||
		!(dev->flags & F_FLASH_PROGRAM) ) 
	{
		ds_printf("DS_ERROR: flash chip detection error.\n");
		return eDetectionFail;
	}

	// Read bios file from file to memory
	pFile = fs_open(filename, O_RDONLY);
	if (pFile == FILEHND_INVALID)
	{
		ds_printf("DS_ERROR: Can't open bios file: %s.\n", filename);
		return eFileFail;
	}
	
	size_t fileSize = fs_total(pFile);
	if(fileSize > dev->size * 1024) 
	{
		ds_printf("DS_ERROR: The firmware larger than a flash chip (%d KB vs %d KB).\n", (fileSize / 1024), dev->size);
		fs_close(pFile);
		return eFileFail;
	}

	data = (uint8 *) memalign(32, fileSize);
	if(data == NULL) 
	{
		ds_printf("DS_ERROR: Not enough memory\n");
		fs_close(pFile);
		return eUnknownFail;
	}
	
	size_t readLen = fs_read(pFile, data, fileSize);
	if (fileSize != readLen)
	{
		ds_printf("DS_ERROR: File wasn't loaded fully to memory\n");
		fs_close(pFile);
		return eFileFail;
	}
	fs_close(pFile);

	EXPT_GUARD_BEGIN;

		// Erasing
		if (dev->flags & F_FLASH_ERASE_SECTOR || 
			dev->flags & F_FLASH_ERASE_ALL) 
		{
			for (i = 0; i < dev->sec_count; ++i) 
			{		
				UPDATE_GUI(eErasing, (float)i / dev->sec_count, guiClbk);

				if (bflash_erase_sector(dev, dev->sectors[i]) < 0) 
				{
					ds_printf("DS_ERROR: Can't erase flash\n");
					free(data);
					EXPT_GUARD_RETURN eErasingFail;
				}
			}
		}

		// Writing
		size_t offset = 0;
		if (fileSize >= settings.m_DataStart + settings.m_DataLength)
		{
			offset = settings.m_DataStart;
			fileSize = (settings.m_DataLength > 0) ? offset + settings.m_DataLength : fileSize - offset;
		}

		size_t chunkCount = fileSize / CHUNK_SIZE;
		for (i = 0; i <= chunkCount; ++i)
		{
			UPDATE_GUI(eWriting, (float)i / chunkCount, guiClbk);

			size_t dataPos = i * CHUNK_SIZE + offset;
			size_t dataLen = (dataPos + CHUNK_SIZE > fileSize) ? fileSize - dataPos : CHUNK_SIZE;
//			ScreenWaitUpdate();
			LockVideo();
			int result = bflash_write_data(dev, dataPos, data + dataPos, dataLen);
			UnlockVideo();
			
			if (result < 0)
			{
				ds_printf("DS_ERROR: Can't write flash\n");
				free(data);
				EXPT_GUARD_RETURN eWritingFail;
			}
		}

	EXPT_GUARD_CATCH;
	
		ds_printf("DS_ERROR: Fatal error\n");
		free(data);
		fs_close(pFile);
		EXPT_GUARD_RETURN eFileFail;
		
	EXPT_GUARD_END;

	free(data);
	fs_close(pFile);

	return 0;
}
예제 #16
0
/* There's a lot of shit in here that's not documented or very poorly
   documented by Intel.. I hope that this works for future compilers. */
cmd_elf_prog_t *cmd_elf_load(const char * fn) {
	uint8			*img, *imgout;
	int			sz, i, j, sect; 
	struct elf_hdr_t	*hdr;
	struct elf_shdr_t	*shdrs, *symtabhdr;
	struct elf_sym_t	*symtab;
	int			symtabsize;
	struct elf_rel_t	*reltab;
	struct elf_rela_t	*relatab;
	int			reltabsize;
	char			*stringtab;
	uint32			vma;
	file_t			fd;
	cmd_elf_prog_t *out;
	
	out = malloc(sizeof(cmd_elf_prog_t));
	memset(out, 0, sizeof(cmd_elf_prog_t));

	/* Load the file: needs to change to just load headers */
	fd = fs_open(fn, O_RDONLY);
	if (fd == FILEHND_INVALID) {
		ds_printf("DS_ERROR: Can't open input file '%s'\n", fn);
		return NULL;
	}
	sz = fs_total(fd);
	DBG(("Loading ELF file of size %d\n", sz));

	img = memalign(32, sz);
	if (img == NULL) {
		ds_printf("DS_ERROR: Can't allocate %d bytes for ELF load\n", sz);
		fs_close(fd);
		return NULL;
	}
	fs_read(fd, img, sz);
	fs_close(fd);

	/* Header is at the front */
	hdr = (struct elf_hdr_t *)(img+0);
	if (hdr->ident[0] != 0x7f || strncmp((const char*)hdr->ident+1, "ELF", 3)) {
		ds_printf("DS_ERROR: File is not a valid ELF file\n");
		hdr->ident[4] = 0;
		ds_printf("DS_ERROR: hdr->ident is %d/%s\n", hdr->ident[0], hdr->ident+1);
		goto error1;
	}
	if (hdr->ident[4] != 1 || hdr->ident[5] != 1) {
		ds_printf("DS_ERROR: Invalid architecture flags in ELF file\n");
		goto error1;
	}
	if (hdr->machine != ARCH_CODE) {
		ds_printf("DS_ERROR: Invalid architecture %02x in ELF file\n", hdr->machine);
		goto error1;
	}

	/* Print some debug info */
	DBG(("File size is %d bytes\n", sz));
	DBG(("	entry point	%08lx\n", hdr->entry));
	DBG(("	ph offset	%08lx\n", hdr->phoff));
	DBG(("	sh offset	%08lx\n", hdr->shoff));
	DBG(("	flags		%08lx\n", hdr->flags));
	DBG(("	ehsize		%08x\n", hdr->ehsize));
	DBG(("	phentsize	%08x\n", hdr->phentsize));
	DBG(("	phnum		%08x\n", hdr->phnum));
	DBG(("	shentsize	%08x\n", hdr->shentsize));
	DBG(("	shnum		%08x\n", hdr->shnum));
	DBG(("	shstrndx	%08x\n", hdr->shstrndx));

	/* Locate the string table; SH elf files ought to have
	   two string tables, one for section names and one for object
	   string names. We'll look for the latter. */
	shdrs = (struct elf_shdr_t *)(img + hdr->shoff);
	stringtab = NULL;
	for (i=0; i<hdr->shnum; i++) {
		if (shdrs[i].type == SHT_STRTAB && i != hdr->shstrndx) {
			stringtab = (char*)(img + shdrs[i].offset);
		}
	}
	if (!stringtab) {
		ds_printf("DS_ERROR: ELF contains no object string table\n");
		goto error1;
	}

	/* Locate the symbol table */
	symtabhdr = NULL;
	for (i=0; i<hdr->shnum; i++) {
		if (shdrs[i].type == SHT_SYMTAB || shdrs[i].type == SHT_DYNSYM) {
			symtabhdr = shdrs+i;
			break;
		}
	}
	if (!symtabhdr) {
		ds_printf("DS_ERROR: ELF contains no symbol table\n");
		goto error1;
	}
	symtab = (struct elf_sym_t *)(img + symtabhdr->offset);
	symtabsize = symtabhdr->size / sizeof(struct elf_sym_t);

	/* Relocate symtab entries for quick access */
	for (i=0; i<symtabsize; i++)
		symtab[i].name = (uint32)(stringtab + symtab[i].name);

	/* Build the final memory image */
	sz = 0;
	for (i=0; i<hdr->shnum; i++) {
		if (shdrs[i].flags & SHF_ALLOC) {
			shdrs[i].addr = sz;
			sz += shdrs[i].size;
			if (shdrs[i].addralign && (shdrs[i].addr % shdrs[i].addralign)) {
				uint32 orig = shdrs[i].addr;
				shdrs[i].addr = (shdrs[i].addr + shdrs[i].addralign)
					& ~(shdrs[i].addralign-1);
				sz += shdrs[i].addr - orig;
			}
		}
	}
	DBG(("Final image is %d bytes\n", sz));
	out->data = imgout = malloc(sz);
	if (out->data == NULL) {
		ds_printf("DS_ERROR: Can't allocate %d bytes for ELF program data\n", sz);
		goto error1;
	}
	out->size = sz;
	vma = (uint32)imgout;
	for (i=0; i<hdr->shnum; i++) {
		if (shdrs[i].flags & SHF_ALLOC) {
			if (shdrs[i].type == SHT_NOBITS) {
				DBG(("  setting %d bytes of zeros at %08x\n",
					shdrs[i].size, shdrs[i].addr));
				memset(imgout+shdrs[i].addr, 0, shdrs[i].size);
			}
			else {
				DBG(("  copying %d bytes from %08x to %08x\n",
					shdrs[i].size, shdrs[i].offset, shdrs[i].addr));
				memcpy(imgout+shdrs[i].addr,
					img+shdrs[i].offset,
					shdrs[i].size);
			}
		}
	}

	/* Go through and patch in any symbols that are undefined */
	for (i=1; i<symtabsize; i++) {
		export_sym_t * sym;

		/* DBG((" symbol '%s': value %04lx, size %04lx, info %02x, other %02x, shndx %04lx\n",
			(const char *)(symtab[i].name),
			symtab[i].value, symtab[i].size,
			symtab[i].info,
			symtab[i].other,
			symtab[i].shndx)); */
		if (symtab[i].shndx != SHN_UNDEF || ELF32_ST_TYPE(symtab[i].info) == STT_SECTION) {
			// DBG((" symbol '%s': skipping\n", (const char *)(symtab[i].name)));
			continue;
		}

		/* Find the symbol in our exports */
		sym = export_lookup((const char *)(symtab[i].name + ELF_SYM_PREFIX_LEN));
		if (!sym/* && strcmp((symtab[i].name + ELF_SYM_PREFIX_LEN), "start")*/) {
			ds_printf("DS_ERROR: Function '%s' is undefined. Maybe need load module?\n", (const char *)(symtab[i].name + ELF_SYM_PREFIX_LEN));
			goto error3;
		}

		/* Patch it in */
		DBG((" symbol '%s' patched to 0x%lx\n",
			(const char *)(symtab[i].name),
			sym->ptr));
		symtab[i].value = sym->ptr;
	}

	/* Process the relocations */
	reltab = NULL; relatab = NULL;
	for (i=0; i<hdr->shnum; i++) {
		if (shdrs[i].type != SHT_REL && shdrs[i].type != SHT_RELA) continue;

		sect = shdrs[i].info;
		DBG(("Relocating (%s) on section %d\n", shdrs[i].type == SHT_REL ? "SHT_REL" : "SHT_RELA", sect));

		switch (shdrs[i].type) {
		case SHT_RELA:
			relatab = (struct elf_rela_t *)(img + shdrs[i].offset);
			reltabsize = shdrs[i].size / sizeof(struct elf_rela_t);
		
			for (j=0; j<reltabsize; j++) {
				int sym;

				// XXX Does non-sh ever use RELA?
				if (ELF32_R_TYPE(relatab[j].info) != R_SH_DIR32) {
					dbglog(DBG_ERROR, "cmd_elf_load: ELF contains unknown RELA type %02x\n",
						ELF32_R_TYPE(relatab[j].info));
					goto error3;
				}

				sym = ELF32_R_SYM(relatab[j].info);
				if (symtab[sym].shndx == SHN_UNDEF) {
					DBG(("  Writing undefined RELA %08x(%08lx+%08lx) -> %08x\n",
						symtab[sym].value + relatab[j].addend,
						symtab[sym].value,
						relatab[j].addend,
						vma + shdrs[sect].addr + relatab[j].offset));
					*((uint32 *)(imgout
						+ shdrs[sect].addr
						+ relatab[j].offset))
						=	  symtab[sym].value
							+ relatab[j].addend;
				} else {
					DBG(("  Writing RELA %08x(%08x+%08x+%08x+%08x) -> %08x\n",
						vma + shdrs[symtab[sym].shndx].addr + symtab[sym].value + relatab[j].addend,
						vma, shdrs[symtab[sym].shndx].addr, symtab[sym].value, relatab[j].addend,
						vma + shdrs[sect].addr + relatab[j].offset));
					*((uint32*)(imgout
						+ shdrs[sect].addr		/* assuming 1 == .text */
						+ relatab[j].offset))
						+=	  vma
							+ shdrs[symtab[sym].shndx].addr
							+ symtab[sym].value
							+ relatab[j].addend;
				}
			}
			break;

		case SHT_REL:
			reltab = (struct elf_rel_t *)(img + shdrs[i].offset);
			reltabsize = shdrs[i].size / sizeof(struct elf_rel_t);
		
			for (j=0; j<reltabsize; j++) {
				int sym, info, pcrel;

				// XXX Does non-ia32 ever use REL?
				info = ELF32_R_TYPE(reltab[j].info);
				if (info != R_386_32 && info != R_386_PC32) {
					ds_printf("DS_ERROR: ELF contains unknown REL type %02x\n", info);
					goto error3;
				}
				pcrel = (info == R_386_PC32);

				sym = ELF32_R_SYM(reltab[j].info);
				if (symtab[sym].shndx == SHN_UNDEF) {
					uint32 value = symtab[sym].value;
					if (sect == 1 && j < 5) {
						DBG(("  Writing undefined %s %08x -> %08x",
							pcrel ? "PCREL" : "ABSREL",
							value,
							vma + shdrs[sect].addr + reltab[j].offset));
					}
					if (pcrel)
						value -= vma + shdrs[sect].addr + reltab[j].offset;

					*((uint32 *)(imgout
						+ shdrs[sect].addr
						+ reltab[j].offset))
						+= value;

					if (sect == 1 && j < 5) {
						DBG(("(%08x)\n", *((uint32 *)(imgout + shdrs[sect].addr + reltab[j].offset))));
					}
				} else {
					uint32 value = vma + shdrs[symtab[sym].shndx].addr
						+ symtab[sym].value;
					if (sect == 1 && j < 5) {
						DBG(("  Writing %s %08x(%08x+%08x+%08x) -> %08x",
							pcrel ? "PCREL" : "ABSREL",
							value,
							vma, shdrs[symtab[sym].shndx].addr, symtab[sym].value,
							vma + shdrs[sect].addr + reltab[j].offset));
					}
					if (pcrel)
						value -= vma + shdrs[sect].addr + reltab[j].offset;
					
					*((uint32*)(imgout
						+ shdrs[sect].addr
						+ reltab[j].offset))
						+= value;

					if (sect == 1 && j < 5) {
						DBG(("(%08x)\n", *((uint32 *)(imgout + shdrs[sect].addr + reltab[j].offset))));
					}
				}
			}
			break;
		
		}
	}
	if (reltab == NULL && relatab == NULL) {
		ds_printf("DS_WARNING: found no REL(A) sections; did you forget -r?\n");
	}

	/* Look for the program entry points and deal with that */
	{
		int sym;

	#define DO_ONE(symname, outp) \
		sym = find_sym(ELF_SYM_PREFIX symname, symtab, symtabsize); \
		if (sym < 0) { \
			ds_printf("DS_ERROR: ELF contains no %s()\n", symname); \
			goto error3; \
		} \
		\
		out->outp = (vma + shdrs[symtab[sym].shndx].addr \
			+ symtab[sym].value);

		DO_ONE("main", main);
		
	#undef DO_ONE
	}

	free(img);
	DBG(("elf_load final ELF stats: memory image at %p, size %08lx\n\tentry pt %p\n", out->data, out->size, out->start));
	
	/* Flush the icache for that zone */
	icache_flush_range((uint32)out->data, out->size);

	return out;

error3:
	free(out->data);

error1:
	free(img);
	return NULL;
}