static void boot_find_cobjs(struct cobj_header *h, int n) { int i; vaddr_t start, end; start = (vaddr_t)h; hs[0] = h; for (i = 1 ; i < n ; i++) { int j = 0, size = 0, tot = 0; size = h->size; for (j = 0 ; j < (int)h->nsect ; j++) { tot += cobj_sect_size(h, j); } printc("cobj %d found at %p:%d, size %d -> %x\n", i, hs[i-1], size, tot, cobj_sect_get(hs[i-1], 0)->vaddr); end = start + round_up_to_cacheline(size); hs[i] = h = (struct cobj_header*)end; start = end; } hs[n] = NULL; printc("cobj found at %p ... -> %x\n", hs[n-1], cobj_sect_get(hs[n-1], 0)->vaddr); }
static void boot_create_system(void) { int i; for (i = 0 ; hs[i] != NULL ; i++) { struct cobj_header *h; spdid_t spdid; struct cobj_sect *sect; vaddr_t comp_info = 0; h = hs[i]; if ((spdid = cos_spd_cntl(COS_SPD_CREATE, 0, 0, 0)) == 0) BUG(); //printc("spdid %d, h->id %d\n", spdid, h->id); assert(spdid == h->id); sect = cobj_sect_get(h, 0); if (cos_spd_cntl(COS_SPD_LOCATION, spdid, sect->vaddr, SERVICE_SIZE)) BUG(); if (boot_spd_symbs(h, spdid, &comp_info)) BUG(); if (boot_spd_map(h, spdid, comp_info)) BUG(); if (boot_spd_reserve_caps(h, spdid)) BUG(); if (cos_spd_cntl(COS_SPD_ACTIVATE, spdid, 0, 0)) BUG(); } for (i = 0 ; hs[i] != NULL ; i++) { struct cobj_header *h; h = hs[i]; if (boot_spd_caps(h, h->id)) BUG(); } for (i = 0 ; hs[i] != NULL ; i++) { struct cobj_header *h; h = hs[i]; boot_spd_thd(h->id); } }
static int boot_spd_map_memory(struct cobj_header *h, spdid_t spdid, vaddr_t comp_info) { unsigned int i; vaddr_t dest_daddr; local_md[spdid].spdid = spdid; local_md[spdid].h = h; local_md[spdid].page_start = cos_get_heap_ptr(); local_md[spdid].comp_info = comp_info; for (i = 0 ; i < h->nsect ; i++) { struct cobj_sect *sect; char *dsrc; int left; sect = cobj_sect_get(h, i); dest_daddr = sect->vaddr; left = cobj_sect_size(h, i); while (left > 0) { dsrc = cos_get_vas_page(); if ((vaddr_t)dsrc != mman_get_page(cos_spd_id(), (vaddr_t)dsrc, 0)) BUG(); if (dest_daddr != (mman_alias_page(cos_spd_id(), (vaddr_t)dsrc, spdid, dest_daddr))) BUG(); dest_daddr += PAGE_SIZE; left -= PAGE_SIZE; } } local_md[spdid].page_end = (void*)dest_daddr; return 0; }
static vaddr_t boot_spd_end(struct cobj_header *h) { struct cobj_sect *sect; int max_sect; max_sect = h->nsect-1; sect = cobj_sect_get(h, max_sect); return sect->vaddr + round_up_to_page(sect->bytes); }
static int boot_spd_map_populate(struct cobj_header *h, spdid_t spdid, vaddr_t comp_info) { unsigned int i; char *start_page; start_page = local_md[spdid].page_start; for (i = 0 ; i < h->nsect ; i++) { struct cobj_sect *sect; vaddr_t dest_daddr; char *lsrc, *dsrc; int left, page_left; sect = cobj_sect_get(h, i); dest_daddr = sect->vaddr; lsrc = cobj_sect_contents(h, i); left = cobj_sect_size(h, i); while (left) { /* data left on a page to copy over */ page_left = (left > PAGE_SIZE) ? PAGE_SIZE : left; dsrc = start_page; start_page += PAGE_SIZE; if (sect->flags & COBJ_SECT_ZEROS) { memset(dsrc, 0, PAGE_SIZE); } else { memcpy(dsrc, lsrc, page_left); if (page_left < PAGE_SIZE) memset(dsrc+page_left, 0, PAGE_SIZE - page_left); } /* Check if special symbols that need * modification are in this page */ boot_symb_process(h, spdid, boot_spd_end(h), dsrc, dest_daddr, comp_info); lsrc += PAGE_SIZE; dest_daddr += PAGE_SIZE; left -= page_left; } } return 0; }
void make_spd_boot(struct service_symbs *boot, struct service_symbs *all) { int n = 0, cnt = 0, tot_sz = 0; unsigned int off = 0, i; struct cobj_header *h, *new_h; char *new_end, *new_sect_start; u32_t new_vaddr_start; u32_t all_obj_sz; struct cos_component_information *ci; struct service_symbs *first = all; /* array to hold the order of initialization/schedule */ struct service_symbs **schedule; if (service_get_spdid(boot) != LLBOOT_BOOT) { printf("Booter component must be component number %d, is %d.\n" "\tSuggested fix: Your first four components should be e.g. " "c0.o, ;llboot.o, ;*fprr.o, ;mm.o, ;print.o, ;boot.o, ;\n", LLBOOT_BOOT, service_get_spdid(boot)); exit(-1); } /* should be loaded by llboot */ assert(is_booter_loaded(boot) && !is_hl_booter_loaded(boot)); assert(boot->cobj->nsect == MAXSEC_S); /* extra section for other components */ /* Assign ids to the booter-loaded components. */ for (all = first ; NULL != all ; all = all->next) { if (!is_hl_booter_loaded(all)) continue; h = all->cobj; assert(h); cnt++; tot_sz += h->size; } schedule = malloc(sizeof(struct service_symbs *) * cnt); assert(schedule); printl(PRINT_HIGH, "Loaded component's initialization scheduled in the following order:\n"); for (all = first ; NULL != all ; all = all->next) { make_spd_boot_schedule(all, schedule, &off); } /* Setup the capabilities for each of the booter-loaded * components */ all = first; for (all = first ; NULL != all ; all = all->next) { if (!is_hl_booter_loaded(all)) continue; if (make_cobj_caps(all, all->cobj)) { printl(PRINT_HIGH, "Could not create capabilities in cobj for %s\n", all->obj); exit(-1); } } all_obj_sz = 0; /* Find the cobj's size */ for (all = first ; NULL != all ; all = all->next) { struct cobj_header *h; if (!is_hl_booter_loaded(all)) continue; printl(PRINT_HIGH, "booter found %s:%d with len %d\n", all->obj, service_get_spdid(all), all->cobj->size) n++; assert(is_hl_booter_loaded(all)); h = all->cobj; assert(h); all_obj_sz += round_up_to_cacheline(h->size); } all_obj_sz = all_obj_sz; all_obj_sz += 3 * PAGE_SIZE; // schedule, config info, and edge info h = boot->cobj; assert(h->nsect == MAXSEC_S); new_h = malloc(h->size + all_obj_sz); assert(new_h); memcpy(new_h, h, h->size); /* Initialize the new section */ { struct cobj_sect *s_prev; new_h->size += all_obj_sz; s_prev = cobj_sect_get(new_h, INITFILE_S); cobj_sect_init(new_h, INITFILE_S, cos_sect_get(INITFILE_S)->cobj_flags, round_up_to_page(s_prev->vaddr + s_prev->bytes), all_obj_sz); } new_sect_start = new_end = cobj_sect_contents(new_h, INITFILE_S); new_vaddr_start = cobj_sect_get(new_h, INITFILE_S)->vaddr; ci = (void *)cobj_vaddr_get(new_h, (u32_t)get_symb_address(&boot->exported, COMP_INFO)); assert(ci); ci->cos_poly[0] = ADDR2VADDR(new_sect_start); /* copy the cobjs */ for (all = first ; NULL != all ; all = all->next) { struct cobj_header *h; if (!is_hl_booter_loaded(all)) continue; h = all->cobj; assert(h); memcpy(new_end, h, h->size); new_end += round_up_to_cacheline(h->size); } assert((u32_t)(new_end - new_sect_start) + 3*PAGE_SIZE == cobj_sect_get(new_h, INITFILE_S)->bytes); all = first; ci->cos_poly[1] = (vaddr_t)n; ci->cos_poly[2] = ADDR2VADDR(new_end); serialize_spd_graph((struct comp_graph*)new_end, PAGE_SIZE/sizeof(struct comp_graph), all); new_end += PAGE_SIZE; ci->cos_poly[3] = ADDR2VADDR(new_end); format_config_info(all, (struct component_init_str*)new_end); assert(off < PAGE_SIZE/sizeof(unsigned int)); /* schedule must fit into page. */ new_end += PAGE_SIZE; ci->cos_poly[4] = ADDR2VADDR(new_end); for (i = 0 ; i < off ; i++) { ((int *)new_end)[i] = service_get_spdid(schedule[i]); } ((int *)new_end)[off] = 0; new_end += PAGE_SIZE; ci->cos_heap_ptr = round_up_to_page(ADDR2VADDR(new_end)); boot->cobj = new_h; printl(PRINT_HIGH, "boot component %s:%d has new section @ %x:%x at address %x, \n\t" "with n %d, graph @ %x, config info @ %x, schedule %x, and heap %x\n", boot->obj, service_get_spdid(boot), (unsigned int)cobj_sect_get(new_h, 3)->vaddr, (int)cobj_sect_get(new_h, 3)->bytes, (unsigned int)ci->cos_poly[0], (unsigned int)ci->cos_poly[1], (unsigned int)ci->cos_poly[2], (unsigned int)ci->cos_poly[3], (unsigned int)ci->cos_poly[4], (unsigned int)ci->cos_heap_ptr); }