예제 #1
0
void cmd_flash_mmc(const char *arg, void *data, unsigned sz)
{
	unsigned long long ptn = 0;
	unsigned long long size = 0;

	ptn = mmc_ptn_offset(arg);
	if(ptn == 0) {
		fastboot_fail("partition table doesn't exist");
		return;
	}

	if (!strcmp(arg, "boot") || !strcmp(arg, "recovery")) {
		if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
			fastboot_fail("image is not a boot image");
			return;
		}
	}

	size = mmc_ptn_size(arg);
	if (ROUND_TO_PAGE(sz,511) > size) {
		fastboot_fail("size too large");
		return;
	}

	if (mmc_write(ptn , sz, (unsigned int *)data)) {
		fastboot_fail("flash write failure");
		return;
	}
	fastboot_okay("");
	return;
}
예제 #2
0
int
pthread_attr_setstacksize(pthread_attr_t *attrp, size_t stacksize)
{
	if (stacksize < PTHREAD_STACK_MIN ||
	    stacksize > ROUND_TO_PAGE(stacksize))
		return (EINVAL);
	(*attrp)->stack_size = stacksize;

	return (0);
}
예제 #3
0
void cmd_boot(const char *arg, void *data, unsigned sz)
{
	unsigned kernel_actual;
	unsigned ramdisk_actual;
	static struct boot_img_hdr hdr;
	char *ptr = ((char*) data);

	if (sz < sizeof(hdr)) {
		fastboot_fail("invalid bootimage header");
		return;
	}

	memcpy(&hdr, data, sizeof(hdr));

	/* ensure commandline is terminated */
	hdr.cmdline[BOOT_ARGS_SIZE-1] = 0;

	if(target_is_emmc_boot() && hdr.page_size) {
		page_size = hdr.page_size;
		page_mask = page_size - 1;
	}

	kernel_actual = ROUND_TO_PAGE(hdr.kernel_size, page_mask);
	ramdisk_actual = ROUND_TO_PAGE(hdr.ramdisk_size, page_mask);

	if (page_size + kernel_actual + ramdisk_actual < sz) {
		fastboot_fail("incomplete bootimage");
		return;
	}

	memmove((void*) KERNEL_ADDR, ptr + page_size, hdr.kernel_size);
	memmove((void*) RAMDISK_ADDR, ptr + page_size + kernel_actual, hdr.ramdisk_size);

	fastboot_okay("");
	target_battery_charging_enable(0, 1);
	udc_stop();

	boot_linux((void*) KERNEL_ADDR, (void*) TAGS_ADDR,
		   (const char*) hdr.cmdline, board_machtype(),
		   (void*) RAMDISK_ADDR, hdr.ramdisk_size);
}
예제 #4
0
/*
 * Return stack info from the given thread.  Based upon the solaris
 * thr_stksegment function.  Note that the returned ss_sp member is the
 * *top* of the allocated stack area, unlike in sigaltstack() where
 * it's the bottom.  You'll have to ask Sun what they were thinking...
 *
 * This function taken from the uthread library, with the following
 * license: 
 * PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <*****@*****.**> */
int
pthread_stackseg_np(pthread_t thread, stack_t *sinfo)
{
	if (thread->stack) {
#ifdef MACHINE_STACK_GROWS_UP
		sinfo->ss_sp = thread->stack->base;
#else
		sinfo->ss_sp = (char *)thread->stack->base +
		    thread->stack->len;
#endif
		sinfo->ss_size = thread->stack->len;
		if (thread->stack->guardsize != 1)
			sinfo->ss_size -= thread->stack->guardsize;
		sinfo->ss_flags = 0;
		return (0);
	} else if (thread->tib->tib_thread_flags & TIB_THREAD_INITIAL_STACK) {
		static struct _ps_strings _ps;
		static struct rlimit rl;
		static int gotself;

		if (gotself == 0) {
			int mib[2];
			size_t len;

			if (getrlimit(RLIMIT_STACK, &rl) != 0)
				return (EAGAIN);

			mib[0] = CTL_VM;
			mib[1] = VM_PSSTRINGS;
			len = sizeof(_ps);
			if (sysctl(mib, 2, &_ps, &len, NULL, 0) != 0)
				return (EAGAIN);
			gotself = 1;
		}

		/*
		 * Provides a rough estimation of stack bounds.   Caller
		 * likely wants to know for the purpose of inspecting call
		 * frames, but VM_PSSTRINGS points to process arguments...
		 */
#ifdef MACHINE_STACK_GROWS_UP
		sinfo->ss_sp = _ps.val;
#else
		sinfo->ss_sp = (void *)ROUND_TO_PAGE((uintptr_t)_ps.val);
#endif
		sinfo->ss_size = (size_t)rl.rlim_cur;
		sinfo->ss_flags = 0;
		return (0);
	}
	return (EAGAIN);
}
예제 #5
0
static int emmc_set_recovery_msg(struct recovery_message *out)
{
	char *ptn_name = "misc";
	unsigned long long ptn = 0;
	unsigned int size = ROUND_TO_PAGE(sizeof(*out),511);
	unsigned char data[size];
	
	ptn = emmc_ptn_offset(ptn_name);

	if(ptn == 0) {
		dprintf(CRITICAL,"partition %s doesn't exist\n",ptn_name);
		return -1;
	}
	memcpy(data, out, sizeof(*out));
	if (emmc_write(ptn , size, (unsigned int*)data))
	{
		dprintf(CRITICAL,"write failure %s %d\n",ptn_name, sizeof(*out));
		return -1;
	}
	return 0;
}
static int emmc_get_recovery_msg(struct recovery_message *in)
{
	char *ptn_name = "misc";
	unsigned long long ptn = 0;
	unsigned int size = ROUND_TO_PAGE(sizeof(*in),511);
	unsigned char data[size];
	int index = INVALID_PTN;

	index = partition_get_index((unsigned char *) ptn_name);
	ptn = partition_get_offset(index);
	if(ptn == 0) {
		dprintf(CRITICAL,"partition %s doesn't exist\n",ptn_name);
		return -1;
	}
	if (mmc_read(ptn , (unsigned int*)data, size)) {
		dprintf(CRITICAL,"mmc read failure %s %d\n",ptn_name, size);
		return -1;
	}
	memcpy(in, data, sizeof(*in));
	return 0;
}
예제 #7
0
파일: lge_stage.c 프로젝트: jaehyek/lk
int LGE_set_bootloader_message(const struct gota_stage_message *out)
{
    char *ptn_name = "misc";
    unsigned long long ptn = 0;
    unsigned int size = ROUND_TO_PAGE(sizeof(*out),511);
    unsigned char data[size];
    int index = INVALID_PTN;

    index = partition_get_index((const char *) ptn_name);
    ptn = partition_get_offset(index);
    if(ptn == 0) {
            dprintf(CRITICAL,"partition %s doesn't exist\n",ptn_name);
            return -1;
    }
    memcpy(data, out, sizeof(*out));
    if (mmc_write(ptn , size, (unsigned int*)data)) {
            dprintf(CRITICAL,"mmc write failure %s %d\n",ptn_name, sizeof(*out));
            return -1;
    }
    return 0;
}
예제 #8
0
static int get_recovery_msg_v8(struct recovery_message *in)
{
	char *ptn_name = "misc";
	unsigned long long ptn = 0;
	unsigned int size = ROUND_TO_PAGE(sizeof(*in),511);
	unsigned char data[size];

	ptn = flash_ptn_offset(ptn_name);

	if(ptn == 0) {
		dprintf(CRITICAL,"partition %s doesn't exist\n",ptn_name);
		return -1;
	}

	if (flash_read_tnftl_v8(ptn , size ,(unsigned int*)data))
	{
		dprintf(CRITICAL,"read failure %s %d\n",ptn_name, size);
		return -1;
	}
	
	memcpy(in, data, sizeof(*in));
	return 0;
}
예제 #9
0
static void cmd_boot(struct protocol_handle *phandle, const char *arg)
{
    int sz, atags_sz, new_atags_sz;
    int rv;
    unsigned kernel_actual;
    unsigned ramdisk_actual;
    unsigned second_actual;
    void *kernel_ptr;
    void *ramdisk_ptr;
    void *second_ptr;
    struct boot_img_hdr *hdr;
    char *ptr = NULL;
    char *atags_ptr = NULL;
    char *new_atags = NULL;
    int data_fd = 0;

    D(DEBUG, "cmd_boot %s\n", arg);

    if (phandle->download_fd < 0) {
        fastboot_fail(phandle, "no kernel file");
        return;
    }

    atags_ptr = read_atags(ATAGS_LOCATION, &atags_sz);
    if (atags_ptr == NULL) {
        fastboot_fail(phandle, "atags read error");
        goto error;
    }

    // TODO: With cms we can also verify partition name included as
    // cms signed attribute
    if (flash_validate_certificate(phandle->download_fd, &data_fd) != 1) {
        fastboot_fail(phandle, "Access forbiden you need the certificate");
        return;
    }

    sz = get_file_size(data_fd);

    ptr = (char *) mmap(NULL, sz, PROT_READ,
                        MAP_POPULATE | MAP_PRIVATE, data_fd, 0);

    hdr = (struct boot_img_hdr *) ptr;

    if (ptr == MAP_FAILED) {
        fastboot_fail(phandle, "internal fastbootd error");
        goto error;
    }

    if ((size_t) sz < sizeof(*hdr)) {
        fastboot_fail(phandle, "invalid bootimage header");
        goto error;
    }

    kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, hdr->page_size);
    ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, hdr->page_size);
    second_actual = ROUND_TO_PAGE(hdr->second_size, hdr->page_size);

    new_atags = (char *) create_atags((unsigned *) atags_ptr, atags_sz, hdr, &new_atags_sz);

    if (new_atags == NULL) {
        fastboot_fail(phandle, "atags generate error");
        goto error;
    }
    if (new_atags_sz > 0x4000) {
        fastboot_fail(phandle, "atags file to large");
        goto error;
    }

    if ((int) (hdr->page_size + kernel_actual + ramdisk_actual) < sz) {
        fastboot_fail(phandle, "incomplete bootimage");
        goto error;
    }

    kernel_ptr = (void *)((unsigned) ptr + hdr->page_size);
    ramdisk_ptr = (void *)((unsigned) kernel_ptr + kernel_actual);
    second_ptr = (void *)((unsigned) ramdisk_ptr + ramdisk_actual);

    D(INFO, "preparing to boot");
    // Prepares boot physical address. Addresses from header are ignored
    rv = prepare_boot_linux(hdr->kernel_addr, kernel_ptr, kernel_actual,
                            hdr->ramdisk_addr, ramdisk_ptr, ramdisk_actual,
                            hdr->second_addr, second_ptr, second_actual,
                            hdr->tags_addr, new_atags, ROUND_TO_PAGE(new_atags_sz, hdr->page_size));
    if (rv < 0) {
        fastboot_fail(phandle, "kexec prepare failed");
        goto error;
    }

    fastboot_okay(phandle, "");

    free(atags_ptr);
    munmap(ptr, sz);
    free(new_atags);
    close(data_fd);

    D(INFO, "Kexec going to reboot");
    reboot(LINUX_REBOOT_CMD_KEXEC);

    fastboot_fail(phandle, "reboot error");

    return;

error:

    if (atags_ptr != NULL)
        free(atags_ptr);
    if (ptr != NULL)
        munmap(ptr, sz);

}
예제 #10
0
struct stack *
_rthread_alloc_stack(pthread_t thread)
{
	struct stack *stack;
	u_int32_t rnd;
	caddr_t base;
	caddr_t guard;
	size_t size;
	size_t guardsize;

	/* if the request uses the defaults, try to reuse one */
	if (thread->attr.stack_addr == NULL &&
	    thread->attr.stack_size == RTHREAD_STACK_SIZE_DEF &&
	    thread->attr.guard_size == _rthread_attr_default.guard_size) {
		_spinlock(&def_stacks_lock);
		stack = SLIST_FIRST(&def_stacks);
		if (stack != NULL) {
			SLIST_REMOVE_HEAD(&def_stacks, link);
			_spinunlock(&def_stacks_lock);
			return (stack);
		}
		_spinunlock(&def_stacks_lock);
	}

	/* allocate the stack struct that we'll return */
	stack = malloc(sizeof(*stack));
	if (stack == NULL)
		return (NULL);

	/* Smaller the stack, smaller the random bias */
	if (thread->attr.stack_size > _thread_pagesize)
		rnd = arc4random() & (_thread_pagesize - 1);
	else if (thread->attr.stack_size == _thread_pagesize)
		rnd = arc4random() & (_thread_pagesize / 16 - 1);
	else
		rnd = 0;
	rnd &= ~_STACKALIGNBYTES;

	/* If a stack address was provided, just fill in the details */
	if (thread->attr.stack_addr != NULL) {
		stack->base = base = thread->attr.stack_addr;
		stack->len  = thread->attr.stack_size;
#ifdef MACHINE_STACK_GROWS_UP
		stack->sp = base + rnd;
#else
		stack->sp = base + thread->attr.stack_size - rnd;
#endif
		/*
		 * This impossible guardsize marks this stack as
		 * application allocated so it won't be freed or
		 * cached by _rthread_free_stack()
		 */
		stack->guardsize = 1;
		return (stack);
	}

	/* round up the requested sizes up to full pages */
	size = ROUND_TO_PAGE(thread->attr.stack_size);
	guardsize = ROUND_TO_PAGE(thread->attr.guard_size);

	/* check for overflow */
	if (size < thread->attr.stack_size ||
	    guardsize < thread->attr.guard_size ||
	    SIZE_MAX - size < guardsize) {
		free(stack);
		errno = EINVAL;
		return (NULL);
	}
	size += guardsize;

	/* actually allocate the real stack */
	base = mmap(NULL, size, PROT_READ | PROT_WRITE,
	    MAP_PRIVATE | MAP_ANON, -1, 0);
	if (base == MAP_FAILED) {
		free(stack);
		return (NULL);
	}

#ifdef MACHINE_STACK_GROWS_UP
	guard = base + size - guardsize;
	stack->sp = base + rnd;
#else
	guard = base;
	stack->sp = base + size - rnd;
#endif

	/* memory protect the guard region */
	if (guardsize != 0 && mprotect(guard, guardsize, PROT_NONE) == -1) {
		munmap(base, size);
		free(stack);
		return (NULL);
	}

	stack->base = base;
	stack->guardsize = guardsize;
	stack->len = size;
	return (stack);
}
BOOL write_to_nand(u8* data, u32 length, u32 img_total_len)
{
	static u64 partition_size = 0;
	int next_flip = 0;
	u32 index;
	static int img_type = UNKOWN_IMG;
	s8* p_type;
	u32 w_length =0;
	//u32 pre_chksum = 0;
	//u32 post_chksum = 0;
	int r;

	if(sto_info.first_run)
	{
		r = get_partition_name(data, length, sto_info.partition_name);
		if(r < 0)
		{
			display_info("\nGet_partition_name() Fail");
			return FALSE;
		}

		index = partition_get_index(sto_info.partition_name);  //
		if(index == -1)
		{
			display_info("\nBrick phone??");
			return FALSE;
		}

		if(!is_support_flash(index))
		{
			display_info("\nDont support partition.");
			return FALSE;
		}

		partition_size = partition_get_size(index);
		dprintf(DBG_LV, "[index:%d]-[partitionSize:%lld]-[downSize:%d]\n", index, partition_size, sto_info.to_write_data_len);

		if (ROUND_TO_PAGE(sto_info.to_write_data_len,511) > partition_size)
		{
			display_info("size too large, space small.");
			dprintf(DBG_LV, "size too large, space small.");
			return FALSE;
		}

		{
			char i_type[20] = {0};
			get_image_type(data,length,(char *)i_type);
					
			partition_get_type(index,&p_type);
			
			if(strcmp(i_type,p_type)){
					display_info("[warning]image type is not match with partition type\n");
					dprintf(DBG_LV, "[warning]image type'%s' is not match with partition type'%s'",i_type,p_type);
			}
			printf("image type %s\n",i_type);

			if(!strcmp(i_type,"raw data")){
				img_type = RAW_DATA_IMG;	
			}else if(!strcmp(i_type,"yaffs2")){
				img_type = YFFS2_IMG;	
			}else if(!strcmp(i_type,"ubifs")){
				img_type = UBIFS_IMG;	
			}else{
					dprintf(DBG_LV, "image type '%s' unkown\n",i_type);
					display_info("\nimage type unkown");
					return FALSE;
			}
		}		
		sto_info.image_base_addr = partition_get_offset(index);

		//NAND has no sparse image.
		//sto_info.unsparse_status.image_base_addr = sto_info.image_base_addr;
		//sto_info.is_sparse_image = is_sparse_image(data, length);
		sto_info.first_run = 0;
	}
#if defined(MTK_MLC_NAND_SUPPORT)
	if (0 != nand_write_img_ex((u64)(sto_info.image_base_addr+sto_info.bulk_image_offset), (void*)data, length,img_total_len?(u64)(img_total_len):(u64)(sto_info.to_write_data_len), &w_length, (u64)(sto_info.image_base_addr),(u64)partition_size, img_type))
#else
	if (0 != nand_write_img_ex((u32)(sto_info.image_base_addr+sto_info.bulk_image_offset), (void*)data, length,img_total_len?(u32)(img_total_len):(u32)(sto_info.to_write_data_len), &w_length, (u32)(sto_info.image_base_addr),(u32)partition_size, img_type))
#endif
	{
		dprintf(DBG_LV, "nand_write_img() Failed.\n");
		display_info("Error in write bulk in NAND.");
		return FALSE;
	}
	if(sto_info.checksum_enabled)
	{
		//NAND do not support read() now.
	}

	sto_info.bulk_image_offset += w_length;

	return TRUE;
}
BOOL write_to_emmc(u8* data, u32 length)
{
	u64 paritition_size = 0;
	u64 size_wrote = 0;
	int next_flip = 0;
	u32 index;
	u32 pre_chksum = 0;
	u32 post_chksum = 0;
	int r;

	while(sto_info.first_run)
	{
		r = get_partition_name(data, length, sto_info.partition_name);
		if(r < 0)
		{
			display_info("\nget_partition_name() Fail");
			return FALSE;
		}

		if((!strncmp((char*)sto_info.partition_name, (char*)"signatureFile", 16))
			|| (!strncmp((char*)sto_info.partition_name, (char*)"boot", 8)))
		{
			//this do not need subsequent codes for normal partition.
			ctx.boot_like_info.is_boot_like_image = TRUE;
			ctx.boot_like_info.offset = 0;
			sto_info.first_run = 0;
			break;
		}

		index = partition_get_index((char*)sto_info.partition_name);
		if(index == (u32)(-1))
		{
			display_info("\nBrick phone??");
			return FALSE;
		}

		if(!is_support_flash(index))
		{
			display_info((char*)sto_info.partition_name);
			display_info("\nDont support partition");
			return FALSE;
		}

		paritition_size = partition_get_size(index);
		dprintf(DBG_LV, "[index:%d]-[downSize:%d]\n", index,  sto_info.to_write_data_len);

		if (ROUND_TO_PAGE(sto_info.to_write_data_len,511) > paritition_size)
		{
			display_info("\nsize too large, space small.");
			dprintf(DBG_LV, "size too large, space small.");
			return FALSE;
		}

#ifdef MTK_NEW_COMBO_EMMC_SUPPORT
		sto_info.part_id = partition_get_region(index);
		sto_info.unsparse_status.part_id = sto_info.part_id;
#endif
		sto_info.image_base_addr = partition_get_offset(index);
		sto_info.unsparse_status.image_base_addr = sto_info.image_base_addr;
		sto_info.is_sparse_image = is_sparse_image(data, length);
		sto_info.first_run = 0;
	}

	//boot like image do not need write to image at this function. it is in flash function.
	if(ctx.boot_like_info.is_boot_like_image)
	{
		dprintf(DBG_LV, "boot like img: len: %d\n", length);
		dprintf(DBG_LV, "data: %08X\n", (u32)data);
		//dprintf(DBG_LV, "ctx.boot_like_info.boot_like_image_address: %08X, ctx.boot_like_info.offset %u, \n", ctx.boot_like_info.boot_like_image_address , ctx.boot_like_info.offset);

		memcpy(ctx.boot_like_info.boot_like_image_address + ctx.boot_like_info.offset, data, length);
		ctx.boot_like_info.offset += length;
		return TRUE;
	}

	if(sto_info.is_sparse_image)
	{
		next_flip = cache_shift(ctx.flipIdxR);

		sto_info.unsparse_status.buf = data;
		sto_info.unsparse_status.size = length;
		mmc_write_sparse_data(&sto_info.unsparse_status);

		if(sto_info.unsparse_status.handle_status == S_DA_SDMMC_SPARSE_INCOMPLETE)
		{
			ctx.dual_cache[next_flip].padding_length = sto_info.unsparse_status.size;
			memcpy(ctx.dual_cache[next_flip].padding_buf +(CACHE_PADDING_SIZE-sto_info.unsparse_status.size)
				, sto_info.unsparse_status.buf
				, sto_info.unsparse_status.size);
		}
		else if (sto_info.unsparse_status.handle_status== S_DONE)
		{
			ctx.dual_cache[next_flip].padding_length = 0;
		}
		else
		{
			//some error
			dprintf(DBG_LV, "write_to_emmc() Failed. handle_status(%d)\n", sto_info.unsparse_status.handle_status);
			display_info("\nError in write sparse image in EMMC.");
			return FALSE;
		}
	}
	else
	{
#ifdef MTK_NEW_COMBO_EMMC_SUPPORT
		size_wrote = emmc_write(sto_info.part_id, sto_info.image_base_addr+sto_info.bulk_image_offset , (void*)data, length);
#else
		size_wrote = emmc_write(sto_info.image_base_addr+sto_info.bulk_image_offset , (void*)data, length);
#endif
		if (size_wrote  != length)
		{
			dprintf(DBG_LV, "write_to_emmc() Failed. act(%d) != want(%d)\n", (u32)size_wrote, length);
			display_info("\nError in write bulk in EMMC.");
			return FALSE;
		}
		if(sto_info.checksum_enabled)
		{
			pre_chksum = calc_checksum(data, (u32)length);
#ifdef MTK_NEW_COMBO_EMMC_SUPPORT
			if(length != emmc_read(sto_info.part_id, sto_info.image_base_addr+sto_info.bulk_image_offset, data,  length))
#else
			if(length != emmc_read(sto_info.image_base_addr+sto_info.bulk_image_offset, data,  length))
#endif
			{
				dprintf(DBG_LV, "emmc_read() Failed.\n");
				display_info("\nError in Read bulk EMMC.");
				return FALSE;
			}

			post_chksum = calc_checksum(data, (u32)length);

			if(post_chksum != pre_chksum)
			{
				dprintf(DBG_LV, "write_to_emmc() Failed. checksum error\n");
				display_info("\nWrite bulk in EMMC. Checksum Error");
				return FALSE;
			}
		}

		sto_info.bulk_image_offset += size_wrote;
	}
	return TRUE;
}
BOOL cmd_flash_emmc_sparse_img(const char *arg, void *data, unsigned sz)
{
	unsigned int chunk;
	unsigned int chunk_data_sz;
	sparse_header_t *sparse_header;
	chunk_header_t *chunk_header;
	u32 total_blocks = 0;
#ifdef MTK_NEW_COMBO_EMMC_SUPPORT
    unsigned int part_id;
#endif
	unsigned long long ptn = 0;
	unsigned long long size = 0;
	unsigned long long size_wrote = 0;
	int index = INVALID_PTN;
	char msg[256];
	dprintf(DBG_LV, "Enter cmd_flash_sparse_img()\n");
	//dprintf(DBG_LV, "EMMC Offset[0x%x], Length[%d], data In[0x%x]\n", arg, sz, data);

	index = partition_get_index(arg);
	if(index == -1)
	{
		fastboot_fail_wrapper("partition table doesn't exist");
		return FALSE;
	}

	if(!is_support_flash(index)){
		sprintf(msg,"partition '%s' not support flash\n",arg);
		fastboot_fail_wrapper(msg);
		return FALSE;
	}

#ifdef MTK_NEW_COMBO_EMMC_SUPPORT
    part_id = partition_get_region(index);
#endif
	ptn = partition_get_offset(index);

	size = partition_get_size(index);
	if (ROUND_TO_PAGE(sz,511) > size)
	{
		fastboot_fail_wrapper("size too large");
		return FALSE;
	}

	/* Read and skip over sparse image header */
	sparse_header = (sparse_header_t *) data;
	data += sparse_header->file_hdr_sz;
	if(sparse_header->file_hdr_sz > sizeof(sparse_header_t))
	{
		/* Skip the remaining bytes in a header that is longer than
		* we expected.
		*/
		data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
	}

	dprintf (DBG_LV, "=== Sparse Image Header ===\n");
	dprintf (DBG_LV, "magic: 0x%x\n", sparse_header->magic);
	dprintf (DBG_LV, "major_version: 0x%x\n", sparse_header->major_version);
	dprintf (DBG_LV, "minor_version: 0x%x\n", sparse_header->minor_version);
	dprintf (DBG_LV, "file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
	dprintf (DBG_LV, "chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
	dprintf (DBG_LV, "blk_sz: %d\n", sparse_header->blk_sz);
	dprintf (DBG_LV, "total_blks: %d\n", sparse_header->total_blks);
	dprintf (DBG_LV, "total_chunks: %d\n", sparse_header->total_chunks);

	TIME_START;
	display_info("Writing Flash ... ");
	/* Start processing chunks */
	for (chunk=0; chunk<sparse_header->total_chunks; chunk++)
	{
		/* Read and skip over chunk header */
		chunk_header = (chunk_header_t *) data;
		data += sizeof(chunk_header_t);

		dprintf (INFO, "=== Chunk Header ===\n");
		dprintf (INFO, "chunk_type: 0x%x\n", chunk_header->chunk_type);
		dprintf (INFO, "chunk_data_sz: 0x%x\n", chunk_header->chunk_sz);
		dprintf (INFO, "total_size: 0x%x\n", chunk_header->total_sz);

		if(sparse_header->chunk_hdr_sz > sizeof(chunk_header_t))
		{
			/* Skip the remaining bytes in a header that is longer than
			* we expected.
			*/
			data += (sparse_header->chunk_hdr_sz - sizeof(chunk_header_t));
		}

		chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
		switch (chunk_header->chunk_type)
		{
		case CHUNK_TYPE_RAW:
			if(chunk_header->total_sz != (sparse_header->chunk_hdr_sz +
				chunk_data_sz))
			{
				fastboot_fail_wrapper("Bogus chunk size for chunk type Raw");
				return FALSE;
			}


			//dprintf(INFO, "[Flash Base Address:0x%llx offset:0x%llx]-[size:%d]-[DRAM Address:0x%x]\n",
			//	ptn , ((uint64_t)total_blocks*sparse_header->blk_sz), chunk_data_sz, data);

#ifdef MTK_NEW_COMBO_EMMC_SUPPORT
			size_wrote = emmc_write(part_id, ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
				(unsigned int*)data, chunk_data_sz);
#else
			size_wrote = emmc_write(ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
				(unsigned int*)data, chunk_data_sz);
#endif

			dprintf(INFO, "[wrote:%lld]-[size:%d]\n", size_wrote ,chunk_data_sz);

			if(size_wrote != chunk_data_sz)
			{
				fastboot_fail_wrapper("flash write failure");
				return FALSE;
			}
			total_blocks += chunk_header->chunk_sz;
			data += chunk_data_sz;
			break;

		case CHUNK_TYPE_DONT_CARE:
			total_blocks += chunk_header->chunk_sz;
			break;

		case CHUNK_TYPE_CRC:
			if(chunk_header->total_sz != sparse_header->chunk_hdr_sz)
			{
				fastboot_fail_wrapper("Bogus chunk size for chunk type Dont Care");
				return FALSE;
			}
			total_blocks += chunk_header->chunk_sz;
			data += chunk_data_sz;
			break;

		default:
			fastboot_fail_wrapper("Unknown chunk type");
			return FALSE;
		}
	}

	dprintf(DBG_LV, "Wrote %d blocks, expected to write %d blocks\n",
		total_blocks, sparse_header->total_blks);

	if(total_blocks != sparse_header->total_blks)
	{
		fastboot_fail_wrapper("sparse image write failure");
        return FALSE;
	}

    fastboot_ok_wrapper("Write Flash OK", sz);
	
	return TRUE;;
}
BOOL cmd_flash_emmc_img(const char *arg, void *data, unsigned sz)
{
#ifdef MTK_NEW_COMBO_EMMC_SUPPORT
    unsigned int part_id;
#endif
	unsigned long long ptn = 0;
	unsigned long long size = 0;
	unsigned long long size_wrote = 0;
	int index = INVALID_PTN;
	u32 pre_chksum = 0;
	u32 post_chksum = 0;
	char msg[256];
	dprintf(DBG_LV, "Function cmd_flash_img()\n");
	//dprintf(DBG_LV, "EMMC Offset[0x%x], Length[0x%x], data In[0x%x]\n", arg, sz, data);
	TIME_START;

	if (!strcmp(arg, "partition"))
	{
		dprintf(DBG_LV, "Attempt to write partition image.(MBR, GPT?)\n");
		dprintf(DBG_LV, "Not supported, return.\n");
		fastboot_fail_wrapper("Not supported 'partition'.\n");
		return FALSE;
		/*if (write_partition(sz, (unsigned char *) data)) {
		fastboot_fail_wrapper("failed to write partition");
		return FALSE;
		}*/
	}
	else
	{
		index = partition_get_index(arg);
		if(index == -1)
		{
			fastboot_fail_wrapper("partition table doesn't exist");
			return FALSE;
		}
		if(!is_support_flash(index)){
			sprintf(msg,"\npartition '%s' not support flash",arg);
			fastboot_fail_wrapper(msg);
			return FALSE;
		}

#ifdef MTK_NEW_COMBO_EMMC_SUPPORT
        part_id = partition_get_region(index);
#endif
		ptn = partition_get_offset(index);

		//dprintf(DBG_LV, "[arg:%s]-[index:%d]-[ptn(offset):0x%x]\n", arg, index, ptn);

		if (!strcmp(arg, "boot") || !strcmp(arg, "recovery"))
		{
			if (memcmp((void *)data, BOOT_MAGIC, strlen(BOOT_MAGIC)))
			{
				fastboot_fail_wrapper("\nimage is not a boot image");
				return FALSE;
			}
		}

		size = partition_get_size(index);
		//dprintf(DBG_LV, "[index:%d]-[partitionSize:%lld]-[downSize:%lld]\n", index, size, sz);

		if (ROUND_TO_PAGE(sz,511) > size)
		{
			fastboot_fail_wrapper("size too large");
			dprintf(DBG_LV, "size too large");
			return FALSE;
		}

		display_info("\nWriting Flash ... ");

		pre_chksum = calc_checksum(data,  (u32)sz);

#ifdef MTK_NEW_COMBO_EMMC_SUPPORT
		size_wrote = emmc_write(part_id, ptn , data, sz);
#else
		size_wrote = emmc_write(ptn , data, sz);
#endif
		if (size_wrote  != sz)
		{
			//dprintf(DBG_LV, "emmc_write() Failed. act(%lld) != want(%lld)\n", size_wrote, sz);
			fastboot_fail_wrapper("\nFlash write failure");
			return FALSE;
		}

#ifdef MTK_NEW_COMBO_EMMC_SUPPORT
		if(sz != emmc_read(part_id, ptn,  data,  sz))
#else
		if(sz != emmc_read(ptn,  data,  sz))
#endif
		{
			dprintf(DBG_LV, "emmc_read() Failed.\n");
			fastboot_fail_wrapper("\nRead EMMC error.");
			return FALSE;
		}

		post_chksum = calc_checksum(data, (u32)sz);
		if(post_chksum != pre_chksum)
		{
			dprintf(DBG_LV, "write_to_emmc() Failed. checksum error\n");
			fastboot_fail_wrapper("\nChecksum Error.");
			return FALSE;
		}

		fastboot_ok_wrapper("OK", sz);
	}
    
	return TRUE;
}
예제 #15
0
Bool
I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags)
{
   I830Ptr pI830 = I830PTR(pScrn);
   unsigned long size, alloced, align = 0;
   int i;
   Bool tileable;
   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
   int verbosity = dryrun ? 4 : 1;
   const char *s = dryrun ? "[dryrun] " : "";
   int lines;

   DPRINTF(PFX, "I830Allocate3DMemory\n");

   /* Back Buffer */
   memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
   pI830->BackBuffer.Key = -1;
   tileable = !(flags & ALLOC_NO_TILING) &&
	      IsTileable(pScrn->displayWidth * pI830->cpp);
   if (tileable) {
      /* Make the height a multiple of the tile height (16) */
      lines = (pScrn->virtualY + 15) / 16 * 16;
   } else {
      lines = pScrn->virtualY;
   }

   size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
   /*
    * Try to allocate on the best tile-friendly boundaries.
    */
   alloced = 0;
   if (tileable) {
      align = GetBestTileAlignment(size);
      for (align = GetBestTileAlignment(size); align >= KB(512); align >>= 1) {
	 alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer),
				   &(pI830->StolenPool), size, align,
				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
				   ALIGN_BOTH_ENDS);
	 if (alloced >= size)
	    break;
      }
   }
   if (alloced < size) {
      /* Give up on trying to tile */
      tileable = FALSE;
      size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * pI830->cpp);
      align = GTT_PAGE_SIZE;
      alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer),
				&(pI830->StolenPool), size, align,
				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
   }
   if (alloced < size) {
      if (!dryrun) {
	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		    "Failed to allocate back buffer space.\n");
      }
      return FALSE;
   }
   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
		  "%sAllocated %d kB for the back buffer at 0x%x.\n", s,
		  alloced / 1024, pI830->BackBuffer.Start);

   /* Depth Buffer -- same size as the back buffer */
   memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
   pI830->DepthBuffer.Key = -1;
   /*
    * Try to allocate on the best tile-friendly boundaries.
    */
   alloced = 0;
   if (tileable) {
      /* Start with the previous align value. */
      for (; align >= KB(512); align >>= 1) {
	 alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer),
				   &(pI830->StolenPool), size, align,
				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
				   ALIGN_BOTH_ENDS);
	 if (alloced >= size)
	    break;
      }
   }
   if (alloced < size) {
      /* Give up on trying to tile */
      tileable = FALSE;
      size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * pI830->cpp);
      align = GTT_PAGE_SIZE;
      alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer),
				&(pI830->StolenPool), size, align,
				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
   }
   if (alloced < size) {
      if (!dryrun) {
	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		    "Failed to allocate depth buffer space.\n");
      }
      return FALSE;
   }
   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
		  "%sAllocated %d kB for the depth buffer at 0x%x.\n", s,
		  alloced / 1024, pI830->DepthBuffer.Start);

   /* Space for logical context.  32k is fine for right now. */
   memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
   pI830->ContextMem.Key = -1;
   size = KB(32);
   alloced = I830AllocVidMem(pScrn, &(pI830->ContextMem),
			     &(pI830->StolenPool), size, GTT_PAGE_SIZE,
			     flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
   if (alloced < size) {
      if (!dryrun) {
	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		    "Failed to allocate logical context space.\n");
      }
      return FALSE;
   }
   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
		  "%sAllocated %d kB for the logical context at 0x%x.\n", s,
		  alloced / 1024, pI830->ContextMem.Start);

   /*
    * Space for DMA buffers, only if there's enough free for at least 1MB
    * of texture space.
    */
   memset(&(pI830->BufferMem), 0, sizeof(pI830->BufferMem));
   pI830->BufferMem.Key = -1;
   /* This should already be a page multiple */
   size = I830_DMA_BUF_NR * I830_DMA_BUF_SZ;
   if (dryrun || (GetFreeSpace(pScrn) >= size + MB(1))) {
      alloced = I830AllocVidMem(pScrn, &(pI830->BufferMem),
				&(pI830->StolenPool), size,
				GTT_PAGE_SIZE,
				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
      if (alloced < size) {
	 if (!dryrun) {
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		       "Failed to allocate DMA buffer space.\n");
	 }
	 return FALSE;
      }
      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
		     "%sAllocated %d kB for the DMA buffers at 0x%x.\n", s,
		     alloced / 1024, pI830->BufferMem.Start);
   } else {
      if (!dryrun) {
	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		    "Not enough free space for DMA buffers.\n");
      }
      return FALSE;
   }

   /* Allocate the remaining space for textures. */
   memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
   pI830->TexMem.Key = -1;
   size = GetFreeSpace(pScrn);
   if (dryrun && (size < MB(1)))
      size = MB(1);
   i = myLog2(size / I830_NR_TEX_REGIONS);
   if (i < I830_LOG_MIN_TEX_REGION_SIZE)
      i = I830_LOG_MIN_TEX_REGION_SIZE;
   pI830->TexGranularity = i;
   /* Truncate size */
   size >>= i;
   size <<= i;
   if (size < KB(512)) {
      if (!dryrun) {
	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		    "Less than %d kBytes for texture space.\n", size / 1024);
      }
      return FALSE;
   }
   alloced = I830AllocVidMem(pScrn, &(pI830->TexMem),
			     &(pI830->StolenPool), size, GTT_PAGE_SIZE,
			     flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
   if (alloced < size) {
      if (!dryrun) {
	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		    "Failed to allocate texture space.\n");
      }
      return FALSE;
   }
   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
		  "%sAllocated %d kB for textures at 0x%x\n", s,
		  alloced / 1024, pI830->TexMem.Start);

   return TRUE;
}
예제 #16
0
/*
 * Allocate memory from the given pool.  Grow the pool if needed and if
 * possible.
 */
static unsigned long
AllocFromPool(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool,
	      unsigned long size, unsigned long alignment, int flags)
{
   I830Ptr pI830 = I830PTR(pScrn);
   unsigned long needed, start, end;
   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);

   if (!result || !pool || !size)
      return 0;

   /* Calculate how much space is needed. */
   if (alignment <= GTT_PAGE_SIZE)
      needed = size;
   else {
      if (flags & ALLOCATE_AT_BOTTOM) {
	 start = ROUND_TO(pool->Free.Start, alignment);
	 if (flags & ALIGN_BOTH_ENDS)
	    end = ROUND_TO(start + size, alignment);
	 else
	    end = start + size;
	 needed = end - pool->Free.Start;
      } else {				/* allocate at top */
	 if (flags & ALIGN_BOTH_ENDS)
	    end = ROUND_DOWN_TO(pool->Free.End, alignment);
	 else
	    end = pool->Free.End;

	 start = ROUND_DOWN_TO(end - size, alignment);
	 needed = pool->Free.End - start;
      }
   }
   if (needed > pool->Free.Size) {
      unsigned long extra;
      /* See if the pool can be grown. */
      if (pI830->StolenOnly && !dryrun)
	 return 0;
      extra = needed - pool->Free.Size;
      extra = ROUND_TO_PAGE(extra);
      if (extra > pI830->FreeMemory) {
	 if (dryrun)
	    pI830->FreeMemory = extra;
	 else
	    return 0;
      }

      if (!dryrun && (extra > pI830->MemoryAperture.Size))
	 return 0;

      pool->Free.Size += extra;
      pool->Free.End += extra;
      pool->Total.Size += extra;
      pool->Total.End += extra;
      pI830->FreeMemory -= extra;
      pI830->MemoryAperture.Start += extra;
      pI830->MemoryAperture.Size -= extra;
   }
   if (flags & ALLOCATE_AT_BOTTOM) {
      result->Start = ROUND_TO(pool->Free.Start, alignment);
      pool->Free.Start += needed;
      result->End = pool->Free.Start;
   } else {
      result->Start = ROUND_DOWN_TO(pool->Free.End - size, alignment) -
			pool->Total.End;
      result->End = pool->Free.End - pool->Total.End;
      pool->Free.End -= needed;
   }
   pool->Free.Size = pool->Free.End - pool->Free.Start;
   result->Size = result->End - result->Start;
   result->Pool = pool;
   result->Alignment = alignment;
   return needed;
}
예제 #17
0
Bool
I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags)
{
   I830Ptr pI830 = I830PTR(pScrn);
   unsigned long size, alloced;
   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
   int verbosity = dryrun ? 4 : 1;
   const char *s = dryrun ? "[dryrun] " : "";
   Bool tileable;
   int align, alignflags;

   DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n",
	   BOOLTOSTRING(flags & ALLOC_INITIAL));

   if (!pI830->StolenOnly &&
       (!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex))) {
      if (!dryrun) {
	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		    "AGP GART support is either not available or cannot "
		    "be used.\n"
		    "\tMake sure your kernel has agpgart support or has the\n"
		    "\tagpgart module loaded.\n");
      }
      return FALSE;
   }


   /*
    * The I830 is slightly different from the I830/I815, it has no
    * dcache and it has stolen memory by default in its gtt.  All
    * additional memory must go after it.
    */

   DPRINTF(PFX,
	   "size == %luk (%lu bytes == pScrn->videoRam)\n"
	   "pI830->StolenSize == %luk (%lu bytes)\n",
	   pScrn->videoRam, pScrn->videoRam * 1024,
	   pI830->StolenPool.Free.Size / 1024,
	   pI830->StolenPool.Free.Size);

   if (flags & ALLOC_INITIAL) {
      unsigned long minspace, avail, lineSize;
      int cacheLines, maxCacheLines;

      if (pI830->NeedRingBufferLow)
	 AllocateRingBuffer(pScrn, flags | FORCE_LOW);

      /* Clear everything first. */
      memset(&(pI830->FbMemBox), 0, sizeof(pI830->FbMemBox));
      memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer));
      pI830->FrontBuffer.Key = -1;

      pI830->FbMemBox.x1 = 0;
      pI830->FbMemBox.x2 = pScrn->displayWidth;
      pI830->FbMemBox.y1 = 0;
      pI830->FbMemBox.y2 = pScrn->virtualY;

      /*
       * Calculate how much framebuffer memory to allocate.  For the
       * initial allocation, calculate a reasonable minimum.  This is
       * enough for the virtual screen size, plus some pixmap cache
       * space.
       */

      lineSize = pScrn->displayWidth * pI830->cpp;
      minspace = lineSize * pScrn->virtualY;
      avail = pScrn->videoRam * 1024;
      maxCacheLines = (avail - minspace) / lineSize;
      /* This shouldn't happen. */
      if (maxCacheLines < 0) {
	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		    "Internal Error: "
		    "maxCacheLines < 0 in I830Allocate2DMemory()\n");
	 maxCacheLines = 0;
      }
      if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pScrn->virtualY))
	 maxCacheLines = MAX_DISPLAY_HEIGHT - pScrn->virtualY;

      if (pI830->CacheLines >= 0) {
	 cacheLines = pI830->CacheLines;
      } else {
#if 1
	 /* Make sure there is enough for two DVD sized YUV buffers */
	 cacheLines = (pScrn->depth == 24) ? 256 : 384;
	 if (pScrn->displayWidth <= 1024)
	    cacheLines *= 2;
#else
	 /*
	  * Make sure there is enough for two DVD sized YUV buffers.
	  * Make that 1.5MB, which is around what was allocated with
	  * the old algorithm
	  */
	 cacheLines = (MB(1) + KB(512)) / pI830->cpp / pScrn->displayWidth;
#endif
      }
      if (cacheLines > maxCacheLines)
	 cacheLines = maxCacheLines;

      pI830->FbMemBox.y2 += cacheLines;

      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
		     "%sAllocating at least %d scanlines for pixmap cache\n",
		     s, cacheLines);

      tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
		 IsTileable(pScrn->displayWidth * pI830->cpp);
      if (tileable) {
	 align = KB(512);
	 alignflags = ALIGN_BOTH_ENDS;
      } else {
	 align = KB(64);
	 alignflags = 0;
      }

      size = lineSize * (pScrn->virtualY + cacheLines);
      size = ROUND_TO_PAGE(size);
      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
		     "%sInitial framebuffer allocation size: %d kByte\n", s,
		     size / 1024);
      alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
				&(pI830->StolenPool), size, align,
				flags | alignflags |
				FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
      if (alloced < size) {
	 if (!dryrun) {
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		       "Failed to allocate framebuffer.\n");
	 }
	 return FALSE;
      }
   } else {
      unsigned long lineSize;
      unsigned long extra = 0;
      unsigned long maxFb = 0;

      /*
       * XXX Need to "free" up any 3D allocations if the DRI ended up
       * and make them available for 2D.  The best way to do this would
       * be position all of those regions contiguously at the end of the
       * StolenPool.
       */
      extra = GetFreeSpace(pScrn);

      if (extra == 0)
	 return TRUE;

      maxFb = pI830->FrontBuffer.Size + extra;
      lineSize = pScrn->displayWidth * pI830->cpp;
      maxFb = ROUND_DOWN_TO(maxFb, lineSize);
      if (maxFb > lineSize * MAX_DISPLAY_HEIGHT)
	 maxFb = lineSize * MAX_DISPLAY_HEIGHT;
      if (maxFb > pI830->FrontBuffer.Size) {
	 unsigned long oldsize;
	 /*
	  * Sanity check -- the fb should be the last thing allocated at
	  * the bottom of the stolen pool.
	  */
	 if (pI830->StolenPool.Free.Start != pI830->FrontBuffer.End) {
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		       "Internal error in I830Allocate2DMemory():\n\t"
		       "Framebuffer isn't the last allocation at the bottom"
		       " of StolenPool\n\t(%x != %x).\n",
		       pI830->FrontBuffer.End,
		       pI830->StolenPool.Free.Start);
	    return FALSE;
	 }
	 /*
	  * XXX Maybe should have a "Free" function.  This should be
	  * the only place where a region is resized, and we know that
	  * the fb is always at the bottom of the aperture/stolen pool,
	  * and is the only region that is allocated bottom-up.
	  * Allowing for more general realloction would require a smarter
	  * allocation system.
	  */
	 oldsize = pI830->FrontBuffer.Size;
	 pI830->StolenPool.Free.Size += pI830->FrontBuffer.Size;
	 pI830->StolenPool.Free.Start -= pI830->FrontBuffer.Size;
	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
			"%sUpdated framebuffer allocation size from %d "
			"to %d kByte\n", s, oldsize / 1024, maxFb / 1024);
	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
			"%sUpdated pixmap cache from %d scanlines to %d "
			"scanlines\n", s,
			oldsize / lineSize - pScrn->virtualY,
			maxFb / lineSize - pScrn->virtualY);
	 pI830->FbMemBox.y2 = maxFb / lineSize;
	 tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
		 IsTileable(pScrn->displayWidth * pI830->cpp);
	 if (tileable) {
	    align = KB(512);
	    alignflags = ALIGN_BOTH_ENDS;
	 } else {
	    align = KB(64);
	    alignflags = 0;
	 }
	 alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
				   &(pI830->StolenPool), maxFb, align,
				   flags | alignflags |
				   FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
	 if (alloced < maxFb) {
	    if (!dryrun) {
	       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
			  "Failed to re-allocate framebuffer\n");
	    }
	    return FALSE;
	 }
      }
      return TRUE;
   }

#if REMAP_RESERVED
   /*
    * Allocate a dummy page to pass when attempting to rebind the
    * pre-allocated region.
    */
   if (!dryrun) {
      memset(&(pI830->Dummy), 0, sizeof(pI830->Dummy));
      pI830->Dummy.Key =
	   xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL);
      pI830->Dummy.Offset = 0;
   }
#endif

   /* Clear cursor info */
   memset(&(pI830->CursorMem), 0, sizeof(pI830->CursorMem));
   pI830->CursorMem.Key = -1;

   if (!pI830->SWCursor) {
      int cursFlags = 0;
      /*
       * Mouse cursor -- The i810-i830 need a physical address in system
       * memory from which to upload the cursor.  We get this from
       * the agpgart module using a special memory type.
       */

      size = HWCURSOR_SIZE;
      cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
      if (pI830->CursorNeedsPhysical)
	 cursFlags |= NEED_PHYSICAL_ADDR;

      alloced = I830AllocVidMem(pScrn, &(pI830->CursorMem),
				&(pI830->StolenPool), size,
				GTT_PAGE_SIZE, flags | cursFlags);
      if (alloced < size) {
	 if (!dryrun) {
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		       "Failed to allocate HW cursor space.\n");
	 }
      } else {
	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
			"%sAllocated %d kB for HW cursor at 0x%x", s,
			alloced / 1024, pI830->CursorMem.Start);
	 if (pI830->CursorNeedsPhysical)
	    xf86ErrorFVerb(verbosity, " (0x%08x)", pI830->CursorMem.Physical);
	 xf86ErrorFVerb(verbosity, "\n");
      }
   }

#ifdef I830_XV
   AllocateOverlay(pScrn, flags);
#endif

   if (!pI830->NeedRingBufferLow)
      AllocateRingBuffer(pScrn, flags);

   /* Clear scratch info */
   memset(&(pI830->Scratch), 0, sizeof(pI830->Scratch));
   pI830->Scratch.Key = -1;

   if (!pI830->noAccel) {
      size = MAX_SCRATCH_BUFFER_SIZE;
      alloced = I830AllocVidMem(pScrn, &(pI830->Scratch), &(pI830->StolenPool),
				size, GTT_PAGE_SIZE,
				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
      if (alloced < size) {
	 size = MIN_SCRATCH_BUFFER_SIZE;
         alloced = I830AllocVidMem(pScrn, &(pI830->Scratch),
				   &(pI830->StolenPool), size,
				   GTT_PAGE_SIZE,
				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
      }
      if (alloced < size) {
	 if (!dryrun) {
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		       "Failed to allocate scratch buffer space\n");
	 }
	 return FALSE;
      }
      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
		    "%sAllocated %d kB for the scratch buffer at 0x%x\n", s,
		    alloced / 1024, pI830->Scratch.Start);
   }
   return TRUE;
}
예제 #18
0
BOOL write_to_nand(u8* data, u32 length)
{
	u64 paritition_size = 0;
	int next_flip = 0;
	u32 index;
	BOOL partition_type;
	s8* p_type;
	//u32 pre_chksum = 0;
	//u32 post_chksum = 0;
	int r;

	if(sto_info.first_run)
	{
		r = get_partition_name(data, length, sto_info.partition_name);
		if(r < 0)
		{
			display_info("ASSERT!! get_partition_name() Fail");
			return FALSE;
		}

		index = partition_get_index(sto_info.partition_name);  //
		if(index == -1)
		{
			display_info("ASSERT!! Brick phone??");
			return FALSE;
		}

		if(!is_support_flash(index))
		{
			display_info("ASSERT!! Dont support system??");
			return FALSE;
		}
		//verify boot partition.
		if (!strcmp(sto_info.partition_name, "boot") || !strcmp(sto_info.partition_name, "recovery"))
		{
			if (memcmp((void *)data, BOOT_MAGIC, strlen(BOOT_MAGIC)))
			{
				display_info("image is not a boot image");
				return FALSE;
			}
		}

		paritition_size = partition_get_size(index);
		dprintf(DBG_LV, "[index:%d]-[partitionSize:%lld]-[downSize:%d]\n", index, paritition_size, sto_info.to_write_data_len);

		if (ROUND_TO_PAGE(sto_info.to_write_data_len,511) > paritition_size)
		{
			display_info("size too large, space small.");
			dprintf(DBG_LV, "size too large, space small.");
			return FALSE;
		}

		partition_get_type(index,&p_type);
		partition_type = (!strcmp(p_type,"yaffs2")) ? TRUE : FALSE;

		sto_info.image_base_addr = partition_get_offset(index);
		//NAND has no sparse image.
		//sto_info.unsparse_status.image_base_addr = sto_info.image_base_addr;
		//sto_info.is_sparse_image = is_sparse_image(data, length);
		sto_info.first_run = 0;
	}

	if (0 != nand_write_img((u32)(sto_info.image_base_addr+sto_info.bulk_image_offset), (void*)data, length,(u32)paritition_size, partition_type))
	{
		dprintf(DBG_LV, "nand_write_img() Failed.\n");
		display_info("Error in write bulk in NAND.");
		return FALSE;
	}
	if(sto_info.checksum_enabled)
	{
		//NAND do not support read() now.
	}

	sto_info.bulk_image_offset += length;

	return TRUE;
}
예제 #19
0
/*
Returns -1 if somethings fails otherwise 0
*/
int sign_image(char* in, char* out){

	/*
	An int is enough because the partitions shouldn't be bigger than 4GB
	*/
	int finalimagesize = 0;
	/*
	Load an image at given path
	*/
	FILE *imageinput;
	imageinput = fopen(in, "rb");

	if (imageinput == NULL){
		std::cerr << "[ ERROR ] Image does not exist at given location" << std::endl;
		return -1;
	}

	/*
	Check if file has contents
	*/
	unsigned imagefilesize = get_file_size(imageinput);
	if (imagefilesize == 0){
		std::cerr << "[ ERROR ] Image has no size" << std::endl;
		return -1;
	}

	/*
	Extract image header first to determine if the final image is bigger than the orignal
	*/
	boot_img_hdr* hdr = NULL;
	hdr = (boot_img_hdr*)malloc(sizeof(boot_img_hdr));
	fread(hdr, sizeof(boot_img_hdr), 1, imageinput);

	/*
	Reposition pointer at start
	*/
	fseek(imageinput, 0, SEEK_SET);


	/*
	Check if image is an Android bootimage
	*/
	if (memcmp((char*)hdr->magic, "ANDROID!", 8) != 0){
		std::cerr << "[ ERROR ] File is not an Android boot image" << std::endl;
		return -1;
	}

	/*
	Load necessary variables from header and delete header
	*/
	unsigned kernel_actual;
	unsigned ramdisk_actual;
	unsigned imagesize_actual;
	unsigned dt_actual;
	unsigned page_size = hdr->page_size;
	unsigned page_mask = hdr->page_size - 1;

	kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
	ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
	dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
	free(hdr);

	/*
	Calculate size of the "real" image
	*/
	imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);

	/*
	If the "real" image is bigger than the file, the file is probably corrupted
	*/
	if (imagefilesize < imagesize_actual){
		std::cerr << "[ ERROR ] File is invalid (is it corrupted?)" << std::endl;
		return -1;
	}

	/*
	If the file is smaller than the "real" image + one page, a buffer with the size of the image would be too small we need allocate a new bigger one
	*/
	if (imagefilesize < imagesize_actual + page_size){
		finalimagesize = imagefilesize + page_size;
	} else {
		finalimagesize = imagefilesize;
	}

	/*
	Load image in buffer and close file
	*/
	unsigned char* image = NULL;
	image = (unsigned char*)malloc(finalimagesize);
	fread(image, 1, imagefilesize, imageinput);
	fclose(imageinput);


	/*
	Create output file
	*/
	FILE *imageoutput;
	imageoutput = fopen(out, "wb");

	if (imageoutput == NULL){
		std::cerr << "[ ERROR ] Can't write output image to disk" << std::endl;
		return -1;
	}

	/*
	Hash the real image
	*/
	unsigned char hash[65];
	unsigned char signature[SIGNATURE_SIZE];
	memset(signature, 0, SIGNATURE_SIZE);
	sha256_buffer(image, imagesize_actual, hash);

	/*
	Create signature with given hash
	*/
	int sig = create_signature(hash, signature);

	/*
	If the signature is created successfully AND the signature passes the check, the signature will be written into the image buffer, which will written to the output file
	*/
	if (sig != -1){
		std::cerr << std::endl << "[ STATUS ] Checking created signature... ";
		if (verify_image(image, signature, imagesize_actual) == 0){
			memcpy(image + imagesize_actual, signature, SIGNATURE_SIZE);
			fwrite(image, finalimagesize, 1, imageoutput);
		}
	} 

	/*
	Cleanup
	*/
	fclose(imageoutput);
	free(image);

	/*
	Final check of the output file
	*/
	std::cerr << std::endl << "[ STATUS ] Checking created image... ";
	check_image(out);

	return 0;
}
예제 #20
0
파일: recovery.c 프로젝트: jaehyek/lk
int write_misc(unsigned page_offset, void *buf, unsigned size)
{
	const char *ptn_name = "misc";
	void *scratch_addr = target_get_scratch_address();
	unsigned offset;
	unsigned aligned_size;

	if (size == 0 || buf == NULL || scratch_addr == NULL)
		return -1;

	if (target_is_emmc_boot())
	{
		int index;
		unsigned long long ptn;
		unsigned long long ptn_size;

		index = partition_get_index(ptn_name);
		if (index == INVALID_PTN)
		{
			dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
			return -1;
		}

		ptn = partition_get_offset(index);
		ptn_size = partition_get_size(index);

		offset = page_offset * BLOCK_SIZE;
		aligned_size = ROUND_TO_PAGE(size, (unsigned)BLOCK_SIZE - 1);
		if (ptn_size < offset + aligned_size)
		{
			dprintf(CRITICAL, "Write request out of '%s' boundaries\n",
					ptn_name);
			return -1;
		}

		if (scratch_addr != buf)
			memcpy(scratch_addr, buf, size);
		if (mmc_write(ptn + offset, aligned_size, (unsigned int *)scratch_addr))
		{
			dprintf(CRITICAL, "Writing MMC failed\n");
			return -1;
		}
	}
	else
	{
		struct ptentry *ptn;
		struct ptable *ptable;
		unsigned pagesize = flash_page_size();

		ptable = flash_get_ptable();
		if (ptable == NULL)
		{
			dprintf(CRITICAL, "Partition table not found\n");
			return -1;
		}

		ptn = ptable_find(ptable, ptn_name);
		if (ptn == NULL)
		{
			dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
			return -1;
		}

		offset = page_offset * pagesize;
		aligned_size = ROUND_TO_PAGE(size, pagesize - 1);
		if (ptn->length < offset + aligned_size)
		{
			dprintf(CRITICAL, "Write request out of '%s' boundaries\n",
					ptn_name);
			return -1;
		}

		if (scratch_addr != buf)
			memcpy(scratch_addr, buf, size);
		if (flash_write(ptn, offset, scratch_addr, aligned_size)) {
			dprintf(CRITICAL, "Writing flash failed\n");
			return -1;
		}
	}

	return 0;
}
예제 #21
0
int update_firmware_image (struct update_header *header, char *name)
{
	struct ptentry *ptn;
	struct ptable *ptable;
	unsigned offset = 0;
	unsigned pagesize = flash_page_size();
	unsigned pagemask = pagesize -1;
	unsigned n = 0;

	ptable = flash_get_ptable();
	if (ptable == NULL) {
		dprintf(CRITICAL, "ERROR: Partition table not found\n");
		return -1;
	}

	ptn = ptable_find(ptable, "cache");
	if (ptn == NULL) {
		dprintf(CRITICAL, "ERROR: No cache partition found\n");
		return -1;
	}

	offset += header->image_offset;
	n = (header->image_length + pagemask) & (~pagemask);

	if (flash_read(ptn, offset, SCRATCH_ADDR, n)) {
		dprintf(CRITICAL, "ERROR: Cannot read radio image\n");
		return -1;
	}

	if (!strcmp(name, "radio")) {
		ptn = ptable_find(ptable, name);
		if (ptn == NULL) {
			dprintf(CRITICAL, "ERROR: No %s partition found\n", name);
			return -1;
		}

		if (flash_write(ptn, 0, SCRATCH_ADDR, n)) {
			dprintf(CRITICAL, "ERROR: flash write fail!\n");
			return -1;
		}
	} else if (!strcmp(name, "bootloader")) {
#ifdef PLATFORM_TCC
		struct ptentry ptn = {
			.name = "bootloader",
		};

		flash_write(&ptn, 0, SCRATCH_ADDR, n);
#endif
	}


	dprintf(INFO, "Partition writen successfully!");
	return 0;
}

/* Bootloader / Recovery Flow
 *
 * On every boot, the bootloader will read the recovery_message
 * from flash and check the command field.  The bootloader should
 * deal with the command field not having a 0 terminator correctly
 * (so as to not crash if the block is invalid or corrupt).
 *
 * The bootloader will have to publish the partition that contains
 * the recovery_message to the linux kernel so it can update it.
 *
 * if command == "boot-recovery" -> boot recovery.img
 * else if command == "update-radio" -> update radio image (below)
 * else -> boot boot.img (normal boot)
 *
 * Radio Update Flow
 * 1. the bootloader will attempt to load and validate the header
 * 2. if the header is invalid, status="invalid-update", goto #8
 * 3. display the busy image on-screen
 * 4. if the update image is invalid, status="invalid-radio-image", goto #8
 * 5. attempt to update the firmware (depending on the command)
 * 6. if successful, status="okay", goto #8
 * 7. if failed, and the old image can still boot, status="failed-update"
 * 8. write the recovery_message, leaving the recovery field
 *    unchanged, updating status, and setting command to
 *    "boot-recovery"
 * 9. reboot
 *
 * The bootloader will not modify or erase the cache partition.
 * It is recovery's responsibility to clean up the mess afterwards.
 */

int recovery_init (void)
{
	struct recovery_message msg;
	struct update_header header;
	char partition_name[32];
	unsigned valid_command = 0;
	
	// get recovery message
	if(get_recovery_message(&msg))
		return -1;
	if (msg.command[0] != 0 && msg.command[0] != 255) {
		dprintf(INFO, "Recovery command: %s\n", msg.command);
	}
	msg.command[sizeof(msg.command)-1] = '\0'; //Ensure termination

	if (!strcmp("boot-recovery",msg.command)) {
		valid_command = 1;
		strcpy(msg.command, "");	// to safe against multiple reboot into recovery
		strcpy(msg.status, "OKAY");
		set_recovery_message(&msg);	// send recovery message
		boot_into_recovery = 1;		// Boot in recovery mode
		return 0;
	}

	if (!strcmp("update-radio",msg.command)) {
		valid_command = 1;
		strcpy(partition_name, "AMSS");
	} else if (!strcmp("update-bootloader", msg.command)) {
		valid_command = 1;
		strcpy(partition_name, "bootloader");
	}

	if(!valid_command) {
		//We need not to do anything
		return 0; // Boot in normal mode
	}

	if (read_update_header_for_bootloader(&header)) {
		strcpy(msg.status, "invalid-update");
		goto SEND_RECOVERY_MSG;
	}

	if (update_firmware_image (&header, partition_name)) {
		strcpy(msg.status, "failed-update");
		goto SEND_RECOVERY_MSG;
	}
	strcpy(msg.status, "OKAY");

SEND_RECOVERY_MSG:
	strcpy(msg.command, "boot-recovery");
	set_recovery_message(&msg);	// send recovery message
	boot_into_recovery = 1;		// Boot in recovery mode
	reboot_device(0);
	return 0;
}

#elif defined(TNFTL_V8_INCLUDE)
static int set_recovery_msg_v8(struct recovery_message *out)
{
	char *ptn_name = "misc";
	unsigned long long ptn = 0;
	unsigned int size = ROUND_TO_PAGE(sizeof(*out),511);
	unsigned char data[size];
	
	ptn = flash_ptn_offset(ptn_name);

	if(ptn == 0) {
		dprintf(CRITICAL,"partition %s doesn't exist\n",ptn_name);
		return -1;
	}
	
	memcpy(data, out, sizeof(*out));

	if (flash_write_tnftl_v8(ptn_name, ptn , size, (unsigned int*)data))
	{
		dprintf(CRITICAL,"write failure %s %d\n",ptn_name, sizeof(*out));
		return -1;
	}
	return 0;
}
예제 #22
0
int boot_linux_from_mmc(void)
{
	struct boot_img_hdr *hdr = (void*) buf;
	struct boot_img_hdr *uhdr;
	unsigned offset = 0;
	unsigned long long ptn = 0;
	unsigned n = 0;
	const char *cmdline;

	uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
	if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
		dprintf(INFO, "Unified boot method!\n");
		hdr = uhdr;
		goto unified_boot;
	}
	if(!boot_into_recovery)
	{
		ptn = mmc_ptn_offset("boot");
		if(ptn == 0) {
			dprintf(CRITICAL, "ERROR: No boot partition found\n");
                    return -1;
		}
	}
	else
	{
		ptn = mmc_ptn_offset("recovery");
		if(ptn == 0) {
			dprintf(CRITICAL, "ERROR: No recovery partition found\n");
                    return -1;
		}
	}

	if (mmc_read(ptn + offset, (unsigned int *)buf, page_size)) {
		dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
                return -1;
	}

	if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
		dprintf(CRITICAL, "ERROR: Invaled boot image header\n");
                return -1;
	}

	if (hdr->page_size && (hdr->page_size != page_size)) {
		page_size = hdr->page_size;
		page_mask = page_size - 1;
	}
	offset += page_size;

	n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
	if (mmc_read(ptn + offset, (void *)hdr->kernel_addr, n)) {
		dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
                return -1;
	}
	offset += n;

	n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
	if (mmc_read(ptn + offset, (void *)hdr->ramdisk_addr, n)) {
		dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
                return -1;
	}
	offset += n;

unified_boot:
	dprintf(INFO, "\nkernel  @ %x (%d bytes)\n", hdr->kernel_addr,
		hdr->kernel_size);
	dprintf(INFO, "ramdisk @ %x (%d bytes)\n", hdr->ramdisk_addr,
		hdr->ramdisk_size);

	if(hdr->cmdline[0]) {
		cmdline = (char*) hdr->cmdline;
	} else {
		cmdline = DEFAULT_CMDLINE;
	}
	dprintf(INFO, "cmdline = '%s'\n", cmdline);

	dprintf(INFO, "\nBooting Linux\n");
	boot_linux((void *)hdr->kernel_addr, (void *)TAGS_ADDR,
		   (const char *)cmdline, board_machtype(),
		   (void *)hdr->ramdisk_addr, hdr->ramdisk_size);

	return 0;
}
예제 #23
0
int boot_linux_from_flash(void)
{
	struct boot_img_hdr *hdr = (void*) buf;
	unsigned n;
	struct ptentry *ptn;
	struct ptable *ptable;
	unsigned offset = 0;
	const char *cmdline;

	if (target_is_emmc_boot()) {
		hdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
		if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
			dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
			return -1;
		}
		goto continue_boot;
	}

	ptable = flash_get_ptable();
	if (ptable == NULL) {
		dprintf(CRITICAL, "ERROR: Partition table not found\n");
		return -1;
	}

	if(!boot_into_recovery)
	{
	        ptn = ptable_find(ptable, "boot");
	        if (ptn == NULL) {
		        dprintf(CRITICAL, "ERROR: No boot partition found\n");
		        return -1;
	        }
	}
	else
	{
	        ptn = ptable_find(ptable, "recovery");
	        if (ptn == NULL) {
		        dprintf(CRITICAL, "ERROR: No recovery partition found\n");
		        return -1;
	        }
	}

	if (flash_read(ptn, offset, buf, page_size)) {
		dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
		return -1;
	}
	offset += page_size;

	if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
		dprintf(CRITICAL, "ERROR: Invaled boot image heador\n");
		return -1;
	}

	if (hdr->page_size != page_size) {
		dprintf(CRITICAL, "ERROR: Invaled boot image pagesize. Device pagesize: %d, Image pagesize: %d\n",page_size,hdr->page_size);
		return -1;
	}

	n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
	if (flash_read(ptn, offset, (void *)hdr->kernel_addr, n)) {
		dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
		return -1;
	}
	offset += n;

	n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
	if (flash_read(ptn, offset, (void *)hdr->ramdisk_addr, n)) {
		dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
		return -1;
	}
	offset += n;

continue_boot:
	dprintf(INFO, "\nkernel  @ %x (%d bytes)\n", hdr->kernel_addr,
		hdr->kernel_size);
	dprintf(INFO, "ramdisk @ %x (%d bytes)\n", hdr->ramdisk_addr,
		hdr->ramdisk_size);

	if(hdr->cmdline[0]) {
		cmdline = (char*) hdr->cmdline;
	} else {
		cmdline = DEFAULT_CMDLINE;
	}
	dprintf(INFO, "cmdline = '%s'\n", cmdline);

	/* TODO: create/pass atags to kernel */

	dprintf(INFO, "\nBooting Linux\n");
	boot_linux((void *)hdr->kernel_addr, (void *)TAGS_ADDR,
		   (const char *)cmdline, board_machtype(),
		   (void *)hdr->ramdisk_addr, hdr->ramdisk_size);

	return 0;
}
예제 #24
0
void cmd_boot(const char *arg, void *data, unsigned sz)
{
	unsigned kernel_actual;
	unsigned ramdisk_actual;
	static struct boot_img_hdr hdr;
	char *ptr = ((char*) data);
   unsigned page_size = 0;
   unsigned page_mask = 0;
   int strlen = 0;

	if (sz < sizeof(hdr)) {
		fastboot_fail("invalid bootimage header");
		return;
	}

	memcpy(&hdr, data, sizeof(hdr));

  printf("\n============================================================\n");
	hdr.magic[7] = '\0';
  printf("[%s] Android Boot IMG Hdr - Magic 	        : %s\n",MODULE_NAME,hdr.magic);
  printf("[%s] Android Boot IMG Hdr - Kernel Size 	: 0x%x\n",MODULE_NAME,hdr.kernel_size);
  printf("[%s] Android Boot IMG Hdr - Rootfs Size 	: 0x%x\n",MODULE_NAME,hdr.ramdisk_size);
  printf("[%s] Android Boot IMG Hdr - Page Size    	: 0x%x\n",MODULE_NAME,hdr.page_size);
  printf("============================================================\n");

	/* ensure commandline is terminated */
	hdr.cmdline[BOOT_ARGS_SIZE-1] = 0;

	if(hdr.page_size) {
		page_size = hdr.page_size;
		page_mask = page_size - 1;
		//page_mask = 2*1024 ; /*FIXME*/
	}
   else
   {
     printf("[FASTBOOT] Please specify the storage page-size in the boot header!\n");
     fastboot_fail("Please specify the storage page-size in the boot header!\n");
     return;
   }

	kernel_actual = ROUND_TO_PAGE(hdr.kernel_size, page_mask);
	ramdisk_actual = ROUND_TO_PAGE(hdr.ramdisk_size, page_mask);

	/* sz should have atleast raw boot image */
	if (page_size + kernel_actual + ramdisk_actual > sz) {
		fastboot_fail("incomplete bootimage");
		return;
	}

	memmove((void*) hdr.kernel_addr, (ptr + MKIMG_HEADER_SZ + BIMG_HEADER_SZ), hdr.kernel_size);
	memmove((void*) hdr.ramdisk_addr, (ptr + MKIMG_HEADER_SZ + BIMG_HEADER_SZ + kernel_actual), hdr.ramdisk_size);

  strlen += sprintf((const char*) hdr.cmdline, "%s lcm=%1d-%s", hdr.cmdline, DISP_IsLcmFound(), mt_disp_get_lcm_id());
  strlen += sprintf((const char*) hdr.cmdline, "%s fps=%1d", hdr.cmdline, mt_disp_get_lcd_time());

	fastboot_okay("");
	udc_stop();
   mtk_wdt_init(); //re-open wdt

  g_boot_mode = NORMAL_BOOT;

	boot_linux((void*) hdr.kernel_addr, (void*) hdr.tags_addr,
		   (const char*) hdr.cmdline, board_machtype(),
		   (void*) hdr.ramdisk_addr, hdr.ramdisk_size);
#if 0
  unsigned kernel_actual;
  unsigned ramdisk_actual;
  struct boot_img_hdr boot_hdr;
  unsigned int k_pg_cnt = 0;
  unsigned int r_pg_cnt = 0;
  unsigned int b_pg_cnt = 0;
  unsigned int size_b = 0;
  unsigned int pg_sz = 2*1024 ;
  int strlen = 0;

  /*copy hdr data from download_base*/
  memcpy(&boot_hdr, data, sizeof(boot_hdr));

  /* ensure commandline is terminated */
  boot_hdr.cmdline[BOOT_ARGS_SIZE-1] = 0;

  printf("\n============================================================\n");
	boot_hdr.magic[7] = '\0';
  printf("[%s] Android Boot IMG Hdr - Magic 	        : %s\n",MODULE_NAME,boot_hdr.magic);
  printf("[%s] Android Boot IMG Hdr - Kernel Size 	: 0x%x\n",MODULE_NAME,boot_hdr.kernel_size);
  printf("[%s] Android Boot IMG Hdr - Rootfs Size 	: 0x%x\n",MODULE_NAME,boot_hdr.ramdisk_size);
  printf("[%s] Android Boot IMG Hdr - Page Size    	: 0x%x\n",MODULE_NAME,boot_hdr.page_size);
  printf("============================================================\n");

  //***************
  //* check partition magic
  //*
  if (strncmp(boot_hdr.magic,BOOT_MAGIC, sizeof(BOOT_MAGIC))!=0) {
    printf("[%s] boot image header magic error\n", MODULE_NAME);
    return -1;
  }

  g_kmem_off =  (unsigned int)target_get_scratch_address();
  g_kmem_off = g_kmem_off + MKIMG_HEADER_SZ + BIMG_HEADER_SZ;


  if(boot_hdr.kernel_size % pg_sz == 0)
  {
    k_pg_cnt = boot_hdr.kernel_size / pg_sz;
  }
  else
  {
    k_pg_cnt = (boot_hdr.kernel_size / pg_sz) + 1;
  }

  if(boot_hdr.ramdisk_size % pg_sz == 0)
  {
    r_pg_cnt = boot_hdr.ramdisk_size / pg_sz;
  }
  else
  {
    r_pg_cnt = (boot_hdr.ramdisk_size / pg_sz) + 1;
  }

  printf(" > page count of kernel image = %d\n",k_pg_cnt);
  g_rmem_off = g_kmem_off + k_pg_cnt * pg_sz;

  printf(" > kernel mem offset = 0x%x\n",g_kmem_off);
  printf(" > rootfs mem offset = 0x%x\n",g_rmem_off);

  //***************
  //* specify boot image size
  //*
  g_bimg_sz = (k_pg_cnt + r_pg_cnt + 2)* pg_sz;
  printf(" > boot image size = 0x%x\n",g_bimg_sz);

  memmove((void*)CFG_BOOTIMG_LOAD_ADDR , g_kmem_off, boot_hdr.kernel_size);
  memmove((void*)CFG_RAMDISK_LOAD_ADDR , g_rmem_off, boot_hdr.ramdisk_size);

  //custom_port_in_kernel(g_boot_mode, commanline);
  //strlen += sprintf(commanline, "%s lcm=%1d-%s", commanline, DISP_IsLcmFound(), mt_disp_get_lcm_id());
  //strlen += sprintf(commanline, "%s fps=%1d", commanline, mt_disp_get_lcd_time());

  fastboot_okay("");

  udc_stop();

  mtk_wdt_init();
  boot_linux((void *)CFG_BOOTIMG_LOAD_ADDR, (unsigned *)CFG_BOOTARGS_ADDR,
		   (const char*) boot_hdr.cmdline, board_machtype(),
		   (void *)CFG_RAMDISK_LOAD_ADDR, boot_hdr.ramdisk_size);
#endif
}
예제 #25
0
		jtag_fail("unknown partition name");
		return;
	}

	if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
		if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
			jtag_fail("image is not a boot image");
			return;
		}
	}

	if (!strcmp(ptn->name, "system") || !strcmp(ptn->name, "userdata")
	    || !strcmp(ptn->name, "persist"))
		extra = ((page_size >> 9) * 16);
	else
		sz = ROUND_TO_PAGE(sz, page_mask);

	data = (void *)target_get_scratch_address();

	dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
	if (flash_write(ptn, extra, data, sz)) {
		jtag_fail("flash write failure");
		return;
	}
	dprintf(INFO, "partition '%s' updated\n", ptn->name);
	jtag_okay("Done");
	enter_critical_section();
	platform_uninit_timer();
	arch_disable_cache(UCACHE);
	arch_disable_mmu();
}
예제 #26
0
/*
Returns -1 if somethings fails otherwise 0
*/
int check_image(char* in){

	/*
	Load an image at given path
	*/
	FILE *imageinput;
	imageinput = fopen(in, "rb");

	if (imageinput == NULL){
		std::cerr << "[ ERROR ] Image does not exist at given location" << std::endl;
		return -1;
	}

	/*
	Check if file has contents
	*/
	unsigned imagefilesize = get_file_size(imageinput);
	if (imagefilesize == 0){
		std::cerr << "[ ERROR ] Image has no size" << std::endl;
		return -1;
	}

	/*
	Load image in buffer and close file
	*/
	unsigned char* image = NULL;
	image = (unsigned char*)malloc(imagefilesize);
	
	fread(image, imagefilesize, 1, imageinput);
	fclose(imageinput);

	/*
	Extract image header
	*/
	boot_img_hdr* hdr = NULL;
	hdr = (boot_img_hdr*)malloc(sizeof(boot_img_hdr));
	memcpy(hdr, image, sizeof(boot_img_hdr));

	
	/*
	Check if image is an Android bootimage
	*/
	if (memcmp((char*)hdr->magic, "ANDROID!", 8) != 0){
		std::cerr << "[ ERROR ] File is not an Android boot image" << std::endl;
		return -1;
	}

	/*
	Load necessary variables from header and delete header
	*/
	unsigned kernel_actual;
	unsigned ramdisk_actual;
	unsigned imagesize_actual;
	unsigned dt_actual;
	unsigned page_size = hdr->page_size;
	unsigned page_mask = hdr->page_size - 1;

	kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
	ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
	dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);

	free(hdr);
	/*
	Calculate size of the "real" image
	*/
	imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual) ;

	/*
	If the "real" image is bigger than the file, the file is probably corrupted
	*/
	if (imagefilesize < imagesize_actual){
		std::cerr << "[ ERROR ] File is invalid (is it corrupted?)" << std::endl;
		return -1;
	}

	/*
	Verify the image.
	*/
	verify_image(image, image + imagesize_actual, imagesize_actual);
	
	return 0;
}
예제 #27
0
BOOL write_to_emmc(u8* data, u32 length)
{
	u64 paritition_size = 0;
	u64 size_wrote = 0;
	int next_flip = 0;
	u32 index;
	u32 pre_chksum = 0;
	u32 post_chksum = 0;
	int r;

	if(sto_info.first_run)
	{
		r = get_partition_name(data, length, sto_info.partition_name);
		if(r < 0)
		{
			display_info("\nASSERT!! get_partition_name() Fail");
			return FALSE;
		}
		if(!strncmp(sto_info.partition_name, "boot", 8))
		{
			ctx.boot_info.is_boot_image = TRUE;
			ctx.boot_info.offset = 0;
		}
		index = partition_get_index(sto_info.partition_name);
		if(index == -1)
		{
			display_info("\nASSERT!! Brick phone??");
			return FALSE;
		}

		if(!is_support_flash(index))
		{
			display_info(sto_info.partition_name);
			display_info("\nASSERT!! Dont support system??");
			return FALSE;
		}

		paritition_size = partition_get_size(index);
		dprintf(DBG_LV, "[index:%d]-[partitionSize:%lld]-[downSize:%lld]\n", index, paritition_size, sto_info.to_write_data_len);

		if (ROUND_TO_PAGE(sto_info.to_write_data_len,511) > paritition_size)
		{
			display_info("\nsize too large, space small.");
			dprintf(DBG_LV, "size too large, space small.");
			return FALSE;
		}

		sto_info.image_base_addr = partition_get_offset(index);
		sto_info.unsparse_status.image_base_addr = sto_info.image_base_addr;
		sto_info.is_sparse_image = is_sparse_image(data, length);
		sto_info.first_run = 0;
	}

	//boot image do not need write to image at this function. it is in flash function.
	if(ctx.boot_info.is_boot_image)
	{
		dprintf(DBG_LV, "boot img: len: %d\n", length);
		dprintf(DBG_LV, "data: %08X\n", data);
		dprintf(DBG_LV, "ctx.boot_info.boot_image_address: %08X, ctx.boot_info.offset %u, \n", ctx.boot_info.boot_image_address , ctx.boot_info.offset);

		memcpy(ctx.boot_info.boot_image_address + ctx.boot_info.offset, data, length);
		ctx.boot_info.offset += length;
		return TRUE;
	}

	if(sto_info.is_sparse_image)
	{
		next_flip = cache_shift(ctx.flipIdxR);

		sto_info.unsparse_status.buf = data;
		sto_info.unsparse_status.size = length;
		mmc_write_sparse_data(&sto_info.unsparse_status);

		if(sto_info.unsparse_status.handle_status == S_DA_SDMMC_SPARSE_INCOMPLETE)
		{
			ctx.dual_cache[next_flip].padding_length = sto_info.unsparse_status.size;
			memcpy(ctx.dual_cache[next_flip].padding_buf +(CACHE_PADDING_SIZE-sto_info.unsparse_status.size)
				, sto_info.unsparse_status.buf
				, sto_info.unsparse_status.size);
		}
		else if (sto_info.unsparse_status.handle_status== S_DONE)
		{
			ctx.dual_cache[next_flip].padding_length = 0;
		}
		else
		{
			//some error
			dprintf(DBG_LV, "write_to_emmc() Failed. handle_status(%d)\n", sto_info.unsparse_status.handle_status);
			display_info("\nError in write sparse image in EMMC.");
			return FALSE;
		}
	}
	else
	{
		size_wrote = emmc_write(sto_info.image_base_addr+sto_info.bulk_image_offset , (void*)data, length);
		if (size_wrote  != length)
		{
			dprintf(DBG_LV, "write_to_emmc() Failed. act(%lld) != want(%lld)\n", size_wrote, length);
			display_info("\nError in write bulk in EMMC.");
			return FALSE;
		}
		if(sto_info.checksum_enabled)
		{
			pre_chksum = calc_checksum(data, (u32)length);
			if(length != emmc_read(sto_info.image_base_addr+sto_info.bulk_image_offset, data,  length))
			{
				dprintf(DBG_LV, "emmc_read() Failed.\n");
				display_info("\nError in Read bulk EMMC.");
				return FALSE;
			}

			post_chksum = calc_checksum(data, (u32)length);

			if(post_chksum != pre_chksum)
			{
				dprintf(DBG_LV, "write_to_emmc() Failed. checksum error\n");
				display_info("\nWrite bulk in EMMC. Checksum Error");
				return FALSE;
			}
		}

		sto_info.bulk_image_offset += size_wrote;
	}
	return TRUE;
}