int construct_guest_dom(struct domain *d, unsigned long guest_size, unsigned long image_start, unsigned long image_size, unsigned long initrd_start, unsigned long initrd_size, char *cmdline) { char *p = NULL; int i; int rc; unsigned long nr_pages; unsigned long nr_pt_pages; unsigned long map_track; unsigned long phys_offset; struct page_info *page = NULL; struct start_info *si = NULL; struct domain_setup_info dsi; struct vcpu *v = NULL; uint32_t domain_features_supported[XENFEAT_NR_SUBMAPS] = { 0 }; uint32_t domain_features_required[XENFEAT_NR_SUBMAPS] = { 0 }; BUG_ON(d == NULL); BUG_ON(d->domain_id <= 0); BUG_ON(d->vcpu[0] == NULL); v = d->vcpu[0]; printk("Image Start = 0x%x\n", image_start); /* Guest partition should be aligned to 1MB boundary */ ASSERT((guest_size & 0xFFFFF) == 0); BUG_ON(test_bit(_VCPUF_initialised, &v->vcpu_flags)); write_ptbase(idle_domain->vcpu[0]); memset(&dsi, 0, sizeof(struct domain_setup_info)); dsi.image_addr = image_start; dsi.image_len = image_size; printk("*** LOADING DOMAIN : %d ***\n", (int)d->domain_id); d->max_pages = ~0U; rc = parseelfimage(&dsi); if (rc != 0) { local_irq_enable(); return rc; } if (dsi.xen_section_string == NULL) { printk("Not a Xen-ELF image: '__xen_guest' section not found.\n"); local_irq_enable(); return -EINVAL; } if ((p = strstr(dsi.xen_section_string, "FEATURES=")) != NULL) { parse_features(p + strlen("FEATURES="), domain_features_supported, domain_features_required); printk("Guest kernel supports features = { %08x }.\n", domain_features_supported[0]); printk("Guest kernel requires features = { %08x }.\n", domain_features_required[0]); if (domain_features_required[0]) { printk("Guest kernel requires an unsupported hypervisor feature.\n"); local_irq_enable(); return -EINVAL; } } page = (struct page_info *) pages_u_alloc(d, get_order_from_bytes(guest_size), ~ALLOC_DOM_DMA); if (page == NULL) { printk("Not enough RAM for domain %d allocation.\n", d->domain_id); return -ENOMEM; } dsi.p_start = page_to_phys(page); dsi.p_end = dsi.p_start + guest_size; printk("Guest physical: 0x%x-0x%x\n", dsi.p_start, dsi.p_end); dsi.v_start &= (~(0xFFFFF)); nr_pt_pages = build_guest_tables(v, &dsi); write_ptbase(current); rc = inspect_guest_tables(v); if(!rc) { panic("Wrong guest table found\n"); } nr_pages = guest_size >> PAGE_SHIFT; if (d->tot_pages < nr_pages) printk(" (%lu pages to be allocated)", nr_pages - d->tot_pages); for (i = 0; i < MAX_VIRT_CPUS; i++) d->shared_info->vcpu_info[i].evtchn_upcall_mask = 1; for (i = 1; i < num_online_cpus(); i++) (void)alloc_vcpu(d, i, i); write_ptbase(v); phys_offset = v->arch.guest_pstart - v->arch.guest_vstart; dsi.image_addr -= phys_offset; /* Copy the OS image and free temporary buffer. */ (void)loadelfimage(&dsi); map_track = round_pgup((unsigned long)(v->arch.guest_vtable) + (PAGE_SIZE * nr_pt_pages)); si = (start_info_t *)map_track; memset(si, 0, PAGE_SIZE); si->nr_pages = nr_pages; #if 0 si->shared_info = virt_to_phys(d->shared_info); #endif si->shared_info = d->shared_info; si->flags = 0; si->pt_base = (unsigned long)v->arch.guest_vtable; si->nr_pt_frames = nr_pt_pages; si->mfn_list = NULL; si->min_mfn = dsi.p_start >> PAGE_SHIFT; map_track += PAGE_SIZE; if (initrd_size != 0) { si->mod_start = map_track; si->mod_len = initrd_size; printk("Initrd len 0x%lx, start at 0x%lx\n", si->mod_len, si->mod_start); memcpy((void *)map_track, (const void *)(initrd_start - phys_offset), initrd_size); map_track = round_pgup(map_track + initrd_size); } memset(map_track, 0, (PAGE_SIZE * 2)); si->store_mfn = (map_track + phys_offset) >> PAGE_SHIFT; si->store_evtchn = d->store_port; map_track += PAGE_SIZE; si->console_mfn = (map_track + phys_offset) >> PAGE_SHIFT; si->console_evtchn = d->console_port; map_track += PAGE_SIZE; d->console_mfn = si->console_mfn; d->store_mfn = si->store_mfn; memset(si->cmd_line, 0, sizeof(si->cmd_line)); if (cmdline != NULL) strncpy((char *)si->cmd_line, cmdline, sizeof(si->cmd_line)-1); #if 0 /* setup shared info table which is specified each domain */ rc = setup_shared_info_mapping(d, NULL); if (rc != 0) { return rc; } #endif write_ptbase(current); //init_domain_time(d); set_bit(_VCPUF_initialised, &v->vcpu_flags); new_thread(v, dsi.v_kernentry, map_track + PAGE_SIZE, (unsigned long)si); i = 0; BUG_ON(i != 0); return 0; }
int main(int argc, char **argv) { struct eeprom_dev *dev; int ch; int writing = 0; char *tmp; struct novena_eeprom_data_v2 newrom; int newdata = 0; int update_mac = 0; int update_features = 0; int update_serial = 0; int update_oops_start = 0; int update_oops_length = 0; int update_page_size = 0; int update_total_size = 0; int update_lvds1 = 0; int update_lvds2 = 0; int update_hdmi = 0; dev = eeprom_open(I2C_BUS, EEPROM_ADDRESS); if (!dev) return 1; while ((ch = getopt(argc, argv, "hm:s:f:wo:p:l:1:2:d:e:i:")) != -1) { switch(ch) { /* MAC address */ case 'm': if (parse_mac(optarg, newrom.mac)) return 1; update_mac = 1; break; /* Serial number */ case 's': newrom.serial = strtoul(optarg, NULL, 0); update_serial = 1; break; /* Featuresset */ case 'f': newrom.features = parse_features(optarg); if (newrom.features == -1) return 1; update_features = 1; break; case 'o': newrom.eepromoops_offset = strtoul(optarg, &tmp, 0); update_oops_start = 1; if (tmp && *tmp) { newrom.eepromoops_length = strtoul(tmp + 1, NULL, 0); update_oops_length = 1; } break; case 'p': newrom.page_size = strtoul(optarg, NULL, 0); update_page_size = 1; break; case 'l': newrom.eeprom_size = strtoul(optarg, NULL, 0); update_total_size = 1; break; case '1': if (parse_modesetting(&newrom.lvds1, optarg)) return 1; update_lvds1 = 1; break; case '2': if (parse_modesetting(&newrom.lvds2, optarg)) return 1; update_lvds2 = 1; break; case 'd': if (parse_modesetting(&newrom.hdmi, optarg)) return 1; update_hdmi = 1; break; case 'e': return eeprom_export(dev, optarg); case 'i': if (eeprom_import(dev, optarg)) return 1; newdata = 1; break; /* Write data */ case 'w': writing = 1; break; case 'h': print_usage(argv[0]); return 1; default: printf("Unrecognized option: %c\n", ch); print_usage(argv[0]); return 1; } } argc -= optind; argv += optind; if (update_mac || update_serial || update_features || update_oops_start || update_oops_length || update_page_size || update_total_size || update_lvds1 || update_lvds2 || update_hdmi) newdata = 1; if (argc) print_usage(argv[0]); else if (!writing) { if (newdata) printf("Not writing data, as -w was not specified\n"); printf("Current EEPROM settings:\n"); print_eeprom_data(dev); } else { int ret; ret = eeprom_read(dev); if (ret) return 1; if (dev->data.v1.version == 1) { printf("Updating v1 EEPROM to v2...\n"); eeprom_upgrade_v1_to_v2(dev); } else if (dev->data.v1.version == 2) { /* Ignore v2 */; } else { if (memcmp(dev->data.v2.signature, NOVENA_SIGNATURE, sizeof(dev->data.v2.signature))) printf("Blank EEPROM found, " "setting defaults...\n"); else fprintf(stderr, "Unrecognized EEPROM version found " "(v%d), overwriting with v2\n", dev->data.v1.version); eeprom_get_defaults(dev); } if (update_mac) memcpy(&dev->data.v2.mac, newrom.mac, sizeof(newrom.mac)); if (update_serial) dev->data.v2.serial = newrom.serial; if (update_features) dev->data.v2.features = newrom.features; if (update_oops_start) dev->data.v2.eepromoops_offset = newrom.eepromoops_offset; if (update_oops_length) dev->data.v2.eepromoops_length = newrom.eepromoops_length; if (update_page_size) dev->data.v2.page_size = newrom.page_size; if (update_total_size) dev->data.v2.eeprom_size = newrom.eeprom_size; if (update_lvds1) memcpy(&dev->data.v2.lvds1, &newrom.lvds1, sizeof(dev->data.v2.lvds1)); if (update_lvds2) memcpy(&dev->data.v2.lvds2, &newrom.lvds2, sizeof(dev->data.v2.lvds2)); if (update_hdmi) memcpy(&dev->data.v2.hdmi, &newrom.hdmi, sizeof(dev->data.v2.hdmi)); memcpy(&dev->data.v2.signature, NOVENA_SIGNATURE, sizeof(dev->data.v2.signature)); dev->data.v2.version = 2; ret = eeprom_write(dev); if (ret) { printf("EEPROM write failed\n"); return 1; } printf("Updated EEPROM. New values:\n"); print_eeprom_data(dev); } eeprom_close(&dev); return 0; }