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; }
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); }
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); }
/* * 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); }
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; }
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; }
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; }
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); }
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; }
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; }
/* * 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; }
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; }
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; }
/* 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; }
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; }
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; }
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; }
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; }
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 }
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(); }
/* 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; }
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; }