static void get_pcie_confspace(struct acpi_binding* b) { ACPI_DEBUG("get_pcie_confspace\n"); errval_t err; ACPI_STATUS as; ACPI_TABLE_HEADER *mcfg_header; as = AcpiGetTable("MCFG", 1, &mcfg_header); if (ACPI_SUCCESS(as) && mcfg_correct_length(mcfg_header->Length)) { ACPI_MCFG_ALLOCATION *mcfg = (void*) mcfg_header + sizeof(ACPI_TABLE_MCFG); ACPI_DEBUG( "PCIe enhanced configuration region at 0x%"PRIx64" " "(segment %u, buses %u-%u)\n", mcfg->Address, mcfg->PciSegment, mcfg->StartBusNumber, mcfg->EndBusNumber); err = b->tx_vtbl.get_pcie_confspace_response(b, NOP_CONT, SYS_ERR_OK, mcfg->Address, mcfg->PciSegment, mcfg->StartBusNumber, mcfg->EndBusNumber); } else { ACPI_DEBUG("No MCFG table found -> no PCIe enhanced configuration\n"); err = b->tx_vtbl.get_pcie_confspace_response(b, NOP_CONT, ACPI_ERR_NO_MCFG_TABLE, 0, 0, 0, 0); } assert(err_is_ok(err)); }
// XXX: proper cap handling static void mm_free_proxy_handler(struct acpi_binding* b, struct capref devframe, uint64_t base, uint8_t sizebits) { ACPI_DEBUG("mm_free_proxy_handler: base: 0x%"PRIx64", sizebits: %d\n", base, sizebits); errval_t err = mm_free(&pci_mm_physaddr, devframe, base, sizebits); if (err_is_fail(err)) { DEBUG_ERR(err, "mm free failed...\n"); } err = b->tx_vtbl.mm_free_proxy_response(b, NOP_CONT, err); assert(err_is_ok(err)); }
static void mm_realloc_range_proxy_handler(struct acpi_binding* b, uint8_t sizebits, genpaddr_t minbase) { ACPI_DEBUG("mm_realloc_range_proxy_handler: sizebits: %d, " "minbase: 0x%"PRIxGENPADDR"\n", sizebits, minbase); struct capref devframe = NULL_CAP; errval_t err = mm_realloc_range(&pci_mm_physaddr, sizebits, minbase, &devframe); if (err_is_fail(err)) { DEBUG_ERR(err, "mm alloc range failed...\n"); } err = b->tx_vtbl.mm_realloc_range_proxy_response(b, NOP_CONT, devframe, err); assert(err_is_ok(err)); }
static errval_t setup_skb_info(void) { skb_execute("[pci_queries]."); errval_t err = skb_read_error_code(); if (err_is_fail(err)) { ACPI_DEBUG("\npcimain.c: Could not load pci_queries.pl.\n" "SKB returned: %s\nSKB error: %s\n", skb_get_output(), skb_get_error_output()); return err; } skb_add_fact("mem_region_type(%d,ram).", RegionType_Empty); skb_add_fact("mem_region_type(%d,roottask).", RegionType_RootTask); skb_add_fact("mem_region_type(%d,phyaddr).", RegionType_PhyAddr); skb_add_fact("mem_region_type(%d,multiboot_module).", RegionType_Module); skb_add_fact("mem_region_type(%d,platform_data).", RegionType_PlatformData); skb_add_fact("mem_region_type(%d,apic).", RegionType_LocalAPIC); skb_add_fact("mem_region_type(%d,ioapic).", RegionType_IOAPIC); return err; }
static errval_t init_allocators(void) { errval_t err, msgerr; struct monitor_blocking_rpc_client *cl = get_monitor_blocking_rpc_client(); assert(cl != NULL); // Get the bootinfo and map it in. struct capref bootinfo_frame; size_t bootinfo_size; struct bootinfo *bootinfo; msgerr = cl->vtbl.get_bootinfo(cl, &err, &bootinfo_frame, &bootinfo_size); if (err_is_fail(msgerr) || err_is_fail(err)) { USER_PANIC_ERR(err_is_fail(msgerr) ? msgerr : err, "failed in get_bootinfo"); } err = vspace_map_one_frame((void**)&bootinfo, bootinfo_size, bootinfo_frame, NULL, NULL); assert(err_is_ok(err)); /* Initialize the memory allocator to handle PhysAddr caps */ static struct range_slot_allocator devframes_allocator; err = range_slot_alloc_init(&devframes_allocator, PCI_CNODE_SLOTS, NULL); if (err_is_fail(err)) { return err_push(err, LIB_ERR_SLOT_ALLOC_INIT); } err = mm_init(&pci_mm_physaddr, ObjType_DevFrame, 0, 48, /* This next parameter is important. It specifies the maximum * amount that a cap may be "chunked" (i.e. broken up) at each * level in the allocator. Setting it higher than 1 reduces the * memory overhead of keeping all the intermediate caps around, * but leads to problems if you chunk up a cap too small to be * able to allocate a large subregion. This caused problems * for me with a large framebuffer... -AB 20110810 */ 1, /*was DEFAULT_CNODE_BITS,*/ slab_default_refill, slot_alloc_dynamic, &devframes_allocator, false); if (err_is_fail(err)) { return err_push(err, MM_ERR_MM_INIT); } // Request I/O Cap struct capref requested_caps; errval_t error_code; err = cl->vtbl.get_io_cap(cl, &requested_caps, &error_code); assert(err_is_ok(err) && err_is_ok(error_code)); // Copy into correct slot struct capref caps_io = { .cnode = cnode_task, .slot = TASKCN_SLOT_IO }; err = cap_copy(caps_io, requested_caps); // XXX: The code below is confused about gen/l/paddrs. // Caps should be managed in genpaddr, while the bus mgmt must be in lpaddr. err = cl->vtbl.get_phyaddr_cap(cl, &requested_caps, &error_code); assert(err_is_ok(err) && err_is_ok(error_code)); physical_caps = requested_caps; // Build the capref for the first physical address capability struct capref phys_cap; phys_cap.cnode = build_cnoderef(requested_caps, PHYSADDRCN_BITS); phys_cap.slot = 0; struct cnoderef devcnode; err = slot_alloc(&my_devframes_cnode); assert(err_is_ok(err)); cslot_t slots; err = cnode_create(&my_devframes_cnode, &devcnode, 255, &slots); if (err_is_fail(err)) { USER_PANIC_ERR(err, "cnode create"); } struct capref devframe; devframe.cnode = devcnode; devframe.slot = 0; for (int i = 0; i < bootinfo->regions_length; i++) { struct mem_region *mrp = &bootinfo->regions[i]; if (mrp->mr_type == RegionType_Module) { skb_add_fact("memory_region(16'%" PRIxGENPADDR ",%u,%zu,%u,%tu).", mrp->mr_base, 0, mrp->mrmod_size, mrp->mr_type, mrp->mrmod_data); } else { skb_add_fact("memory_region(16'%" PRIxGENPADDR ",%u,%zu,%u,%tu).", mrp->mr_base, mrp->mr_bits, ((size_t)1) << mrp->mr_bits, mrp->mr_type, mrp->mrmod_data); } if (mrp->mr_type == RegionType_PhyAddr || mrp->mr_type == RegionType_PlatformData) { ACPI_DEBUG("Region %d: %"PRIxGENPADDR" - %"PRIxGENPADDR" %s\n", i, mrp->mr_base, mrp->mr_base + (((size_t)1)<<mrp->mr_bits), mrp->mr_type == RegionType_PhyAddr ? "physical address" : "platform data"); err = cap_retype(devframe, phys_cap, ObjType_DevFrame, mrp->mr_bits); if (err_no(err) == SYS_ERR_REVOKE_FIRST) { printf("cannot retype region %d: need to revoke first; ignoring it\n", i); } else { assert(err_is_ok(err)); err = mm_add(&pci_mm_physaddr, devframe, mrp->mr_bits, mrp->mr_base); if (err_is_fail(err)) { USER_PANIC_ERR(err, "adding region %d FAILED\n", i); } } phys_cap.slot++; devframe.slot++; } } return SYS_ERR_OK; }
int main(int argc, char *argv[]) { errval_t err; // Parse CMD Arguments bool got_apic_id = false; bool do_video_init = false; vtd_force_off = false; for (int i = 1; i < argc; i++) { if(sscanf(argv[i], "apicid=%" PRIuPTR, &my_apic_id) == 1) { got_apic_id = true; } if (strcmp(argv[i], "video_init") == 0) { do_video_init = true; } else if (strncmp(argv[i], "vtd_force_off", strlen("vtd_force_off")) == 0) { vtd_force_off = true; } } if(got_apic_id == false) { fprintf(stderr, "Usage: %s APIC_ID\n", argv[0]); fprintf(stderr, "Wrong monitor version?\n"); return EXIT_FAILURE; } err = oct_init(); if (err_is_fail(err)) { USER_PANIC_ERR(err, "Initialize dist"); } //connect to the SKB ACPI_DEBUG("acpi: connecting to the SKB...\n"); skb_client_connect(); skb_execute("[pci_queries]."); err = setup_skb_info(); if (err_is_fail(err)) { USER_PANIC_ERR(err, "Populating SKB failed."); } err = init_allocators(); if (err_is_fail(err)) { USER_PANIC_ERR(err, "Init memory allocator"); } err = copy_bios_mem(); if (err_is_fail(err)) { USER_PANIC_ERR(err, "Copy BIOS Memory"); } int r = init_acpi(); assert(r == 0); buttons_init(); if (do_video_init) { video_init(); } start_service(); messages_handler_loop(); }