static ssize_t dcc_write(void *unused, const void *_data, size_t len) { const unsigned char *data = _data; size_t pos = 0; LTRACEF("buf %p, len %zu\n", _data, len); while (pos < len) { LTRACEF("pos %zu, len %zu, dtoh_filled %d\n", pos, len, dtoh_filled); if (!dtoh_filled) { // put as much data as we can in the outgoing buffer size_t tocopy = MIN(len, DCC_BUFLEN); LTRACEF("tocopy %zu\n", tocopy); memcpy(dtoh_buffer, data, tocopy); arch_clean_cache_range((vaddr_t)dtoh_buffer, DCC_BUFLEN); send_out_index_update(tocopy); dtoh_filled = true; pos += tocopy; } // process a dcc command uint32_t dcc; ssize_t err = arm_dcc_read(&dcc, 1, 1000); if (err > 0) { err = dcc_process_opcode(dcc); if (err == DCC_PROCESS_RESET) { return ERR_IO; } } } return pos; }
void arch_init(void) { arch_mp_init_percpu(); #if WITH_SMP LTRACEF("midr_el1 0x%llx\n", ARM64_READ_SYSREG(midr_el1)); secondaries_to_init = SMP_MAX_CPUS - 1; /* TODO: get count from somewhere else, or add cpus as they boot */ lk_init_secondary_cpus(secondaries_to_init); LTRACEF("releasing %d secondary cpus\n", secondaries_to_init); /* release the secondary cpus */ spin_unlock(&arm_boot_cpu_lock); /* flush the release of the lock, since the secondary cpus are running without cache on */ arch_clean_cache_range((addr_t)&arm_boot_cpu_lock, sizeof(arm_boot_cpu_lock)); #endif }
void mt_disp_update(UINT32 x, UINT32 y, UINT32 width, UINT32 height) { { unsigned int va = fb_addr; dprintf(0,"fb dump: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", *(unsigned int*)va, *(unsigned int*)(va+4), *(unsigned int*)(va+8), *(unsigned int*)(va+0xC)); } arch_clean_cache_range((unsigned int)fb_addr, DISP_GetFBRamSize()); primary_display_trigger(TRUE); if(!primary_display_is_video_mode()) { /*video mode no need to wait*/ mdelay(30); } /* // TODO: Fixit!!!!! if(fb_isdirty) { fb_isdirty = 0; MASKREG32(0x1400E000, 0x1, 0x1); //Enable DISP MUTEX0 MASKREG32(0x1400E004, 0x1, 0x0); LCD_CHECK_RET(LCD_LayerSetAddress(FB_LAYER - 1, (UINT32)fb_addr + fb_offset_logo * fb_size)); printk("[wwy] hardware address = %x, fb_offset_logo = %d\n",(UINT32)fb_addr + fb_offset_logo * fb_size,fb_offset_logo); arch_clean_cache_range((unsigned int)fb_addr, DISP_GetFBRamSize()); DISP_CHECK_RET(DISP_UpdateScreen(x, y, width, height)); //wait reg update to set fb_offset_logo DISP_WaitRegUpdate(); fb_offset_logo = fb_offset_logo ? 0 : 3; } else { arch_clean_cache_range((unsigned int)fb_addr, DISP_GetFBRamSize()); DISP_CHECK_RET(DISP_UpdateScreen(x, y, width, height)); } */ }
void lkboot_dcc_init(void) { paddr_t pa; __UNUSED status_t err; buffer_desc.version = PDCC_VERSION; err = arch_mmu_query((vaddr_t)htod_buffer, &pa, NULL); DEBUG_ASSERT(err == NO_ERROR); buffer_desc.htod_buffer_phys = pa; buffer_desc.htod_buffer_len = DCC_BUFLEN; err = arch_mmu_query((vaddr_t)dtoh_buffer, &pa, NULL); DEBUG_ASSERT(err == NO_ERROR); buffer_desc.dtoh_buffer_phys = pa; buffer_desc.dtoh_buffer_len = DCC_BUFLEN; err = arch_mmu_query((vaddr_t)&buffer_desc, &buffer_desc_phys, NULL); DEBUG_ASSERT(err == NO_ERROR); arch_clean_cache_range((vaddr_t)&buffer_desc, sizeof(buffer_desc)); }
// return NULL for success, error string for failure int lkb_handle_command(lkb_t *lkb, const char *cmd, const char *arg, size_t len, const char **result) { *result = NULL; struct lkb_command *lcmd; for (lcmd = lkb_cmd_list; lcmd; lcmd = lcmd->next) { if (!strcmp(lcmd->name, cmd)) { *result = lcmd->handler(lkb, arg, len, lcmd->cookie); return 0; } } if (!strcmp(cmd, "flash") || !strcmp(cmd, "erase")) { struct ptable_entry entry; bdev_t *bdev; if (ptable_find(arg, &entry) < 0) { size_t plen = len; /* doesn't exist, make one */ if (ptable_add(arg, plen, 0) < 0) { *result = "error creating partition"; return -1; } if (ptable_find(arg, &entry) < 0) { *result = "couldn't find partition after creating it"; return -1; } } if (len > entry.length) { *result = "partition too small"; return -1; } if (!(bdev = ptable_get_device())) { *result = "ptable_get_device failed"; return -1; } printf("lkboot: erasing partition of size %llu\n", entry.length); if (bio_erase(bdev, entry.offset, entry.length) != (ssize_t)entry.length) { *result = "bio_erase failed"; return -1; } if (!strcmp(cmd, "flash")) { printf("lkboot: writing to partition\n"); void *buf = malloc(bdev->block_size); if (!buf) { *result = "memory allocation failed"; return -1; } size_t pos = 0; while (pos < len) { size_t toread = MIN(len - pos, bdev->block_size); LTRACEF("offset %zu, toread %zu\n", pos, toread); if (lkb_read(lkb, buf, toread)) { *result = "io error"; free(buf); return -1; } if (bio_write(bdev, buf, entry.offset + pos, toread) != (ssize_t)toread) { *result = "bio_write failed"; free(buf); return -1; } pos += toread; } free(buf); } } else if (!strcmp(cmd, "remove")) { if (ptable_remove(arg) < 0) { *result = "remove failed"; return -1; } } else if (!strcmp(cmd, "fpga")) { #if PLATFORM_ZYNQ void *buf = malloc(len); if (!buf) { *result = "error allocating buffer"; return -1; } /* translate to physical address */ paddr_t pa = vaddr_to_paddr(buf); if (pa == 0) { *result = "error allocating buffer"; free(buf); return -1; } if (lkb_read(lkb, buf, len)) { *result = "io error"; free(buf); return -1; } /* make sure the cache is flushed for this buffer for DMA coherency purposes */ arch_clean_cache_range((vaddr_t)buf, len); /* program the fpga */ zynq_reset_fpga(); zynq_program_fpga(pa, len); free(buf); #else *result = "no fpga"; return -1; #endif } else if (!strcmp(cmd, "boot")) { return do_boot(lkb, len, result); } else if (!strcmp(cmd, "getsysparam")) { const void *ptr; size_t len; if (sysparam_get_ptr(arg, &ptr, &len) == 0) { lkb_write(lkb, ptr, len); } } else if (!strcmp(cmd, "reboot")) { thread_resume(thread_create("reboot", &do_reboot, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE)); } else { *result = "unknown command"; return -1; } return 0; }
/* try to boot the system from a flash partition */ status_t do_flash_boot(void) { status_t err; LTRACE_ENTRY; /* construct a boot argument list */ const size_t bootargs_size = PAGE_SIZE; #if 0 /* old code */ void *args = (void *)((uintptr_t)lkb_iobuffer + lkb_iobuffer_size - bootargs_size); paddr_t args_phys = lkb_iobuffer_phys + lkb_iobuffer_size - bootargs_size; #elif PLATFORM_ZYNQ /* grab the top page of sram */ paddr_t args_phys = SRAM_BASE + SRAM_SIZE - bootargs_size; void *args = paddr_to_kvaddr(args_phys); #else #error need better way #endif LTRACEF("boot args %p, phys 0x%lx, len %zu\n", args, args_phys, bootargs_size); bootargs_start(args, bootargs_size); bootargs_add_command_line(args, bootargs_size, "what what"); arch_clean_cache_range((vaddr_t)args, bootargs_size); ulong lk_args[4]; bootargs_generate_lk_arg_values(args_phys, lk_args); const void *ptr; if (!ptable_found_valid()) { TRACEF("ptable not found\n"); return ERR_NOT_FOUND; } /* find the system partition */ struct ptable_entry entry; err = ptable_find("system", &entry); if (err < 0) { TRACEF("cannot find system partition\n"); return ERR_NOT_FOUND; } /* get a direct pointer to the device */ bdev_t *bdev = ptable_get_device(); if (!bdev) { TRACEF("error opening boot device\n"); return ERR_NOT_FOUND; } /* convert the bdev to a memory pointer */ err = bio_ioctl(bdev, BIO_IOCTL_GET_MEM_MAP, (void *)&ptr); TRACEF("err %d, ptr %p\n", err, ptr); if (err < 0) { TRACEF("error getting direct pointer to block device\n"); return ERR_NOT_FOUND; } /* sniff it to see if it's a bootimage or a raw image */ bootimage_t *bi; if (bootimage_open((char *)ptr + entry.offset, entry.length, &bi) >= 0) { size_t len; /* it's a bootimage */ TRACEF("detected bootimage\n"); /* find the lk image */ if (bootimage_get_file_section(bi, TYPE_LK, &ptr, &len) >= 0) { TRACEF("found lk section at %p\n", ptr); /* add the boot image to the argument list */ size_t bootimage_size; bootimage_get_range(bi, NULL, &bootimage_size); bootargs_add_bootimage_pointer(args, bootargs_size, bdev->name, entry.offset, bootimage_size); } } else { /* did not find a bootimage, abort */ bio_ioctl(bdev, BIO_IOCTL_PUT_MEM_MAP, NULL); return ERR_NOT_FOUND; } TRACEF("chain loading binary at %p\n", ptr); arch_chain_load((void *)ptr, lk_args[0], lk_args[1], lk_args[2], lk_args[3]); /* put the block device back into block mode (though we never get here) */ bio_ioctl(bdev, BIO_IOCTL_PUT_MEM_MAP, NULL); return NO_ERROR; }
static int do_boot(lkb_t *lkb, size_t len, const char **result) { LTRACEF("lkb %p, len %zu, result %p\n", lkb, len, result); void *buf; paddr_t buf_phys; if (vmm_alloc_contiguous(vmm_get_kernel_aspace(), "lkboot_iobuf", len, &buf, log2_uint(1024*1024), 0, ARCH_MMU_FLAG_UNCACHED) < 0) { *result = "not enough memory"; return -1; } buf_phys = vaddr_to_paddr(buf); LTRACEF("iobuffer %p (phys 0x%lx)\n", buf, buf_phys); if (lkb_read(lkb, buf, len)) { *result = "io error"; // XXX free buffer here return -1; } /* construct a boot argument list */ const size_t bootargs_size = PAGE_SIZE; #if 0 void *args = (void *)((uintptr_t)lkb_iobuffer + lkb_iobuffer_size - bootargs_size); paddr_t args_phys = lkb_iobuffer_phys + lkb_iobuffer_size - bootargs_size; #elif PLATFORM_ZYNQ /* grab the top page of sram */ /* XXX do this better */ paddr_t args_phys = SRAM_BASE + SRAM_SIZE - bootargs_size; void *args = paddr_to_kvaddr(args_phys); #else #error need better way #endif LTRACEF("boot args %p, phys 0x%lx, len %zu\n", args, args_phys, bootargs_size); bootargs_start(args, bootargs_size); bootargs_add_command_line(args, bootargs_size, "what what"); arch_clean_cache_range((vaddr_t)args, bootargs_size); ulong lk_args[4]; bootargs_generate_lk_arg_values(args_phys, lk_args); const void *ptr; /* sniff it to see if it's a bootimage or a raw image */ bootimage_t *bi; if (bootimage_open(buf, len, &bi) >= 0) { size_t len; /* it's a bootimage */ TRACEF("detected bootimage\n"); /* find the lk image */ if (bootimage_get_file_section(bi, TYPE_LK, &ptr, &len) >= 0) { TRACEF("found lk section at %p\n", ptr); /* add the boot image to the argument list */ size_t bootimage_size; bootimage_get_range(bi, NULL, &bootimage_size); bootargs_add_bootimage_pointer(args, bootargs_size, "pmem", buf_phys, bootimage_size); } } else { /* raw image, just chain load it directly */ TRACEF("raw image, chainloading\n"); ptr = buf; } /* start a boot thread to complete the startup */ static struct chainload_args cl_args; cl_args.func = (void *)ptr; cl_args.args[0] = lk_args[0]; cl_args.args[1] = lk_args[1]; cl_args.args[2] = lk_args[2]; cl_args.args[3] = lk_args[3]; thread_resume(thread_create("boot", &chainload_thread, &cl_args, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE)); return 0; }
void aee_mrdump_flush_cblock(void) { if (mrdump_cb != NULL) { arch_clean_cache_range(mrdump_cb, sizeof(struct mrdump_control_block)); } }