EFI_STATUS XenGetSharedInfoPage ( IN OUT XENBUS_DEVICE *Dev ) { xen_add_to_physmap_t Parameter; ASSERT (Dev->SharedInfo == NULL); Parameter.domid = DOMID_SELF; Parameter.space = XENMAPSPACE_shared_info; Parameter.idx = 0; // // using reserved page because the page is not released when Linux is // starting because of the add_to_physmap. QEMU might try to access the // page, and fail because it have no right to do so (segv). // Dev->SharedInfo = AllocateReservedPages (1); Parameter.gpfn = (UINTN) Dev->SharedInfo >> EFI_PAGE_SHIFT; if (XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &Parameter) != 0) { FreePages (Dev->SharedInfo, 1); Dev->SharedInfo = NULL; return EFI_LOAD_ERROR; } return EFI_SUCCESS; }
EFI_STATUS EFIAPI InitializeQemuRamfb ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_DEVICE_PATH_PROTOCOL *RamfbDevicePath; EFI_DEVICE_PATH_PROTOCOL *GopDevicePath; VOID *DevicePath; VENDOR_DEVICE_PATH VendorDeviceNode; ACPI_ADR_DEVICE_PATH AcpiDeviceNode; EFI_STATUS Status; EFI_PHYSICAL_ADDRESS FbBase; UINTN FbSize, MaxFbSize, Pages; UINTN FwCfgSize; UINTN Index; if (!QemuFwCfgIsAvailable ()) { DEBUG ((DEBUG_INFO, "Ramfb: no FwCfg\n")); return EFI_NOT_FOUND; } Status = QemuFwCfgFindFile ("etc/ramfb", &mRamfbFwCfgItem, &FwCfgSize); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } if (FwCfgSize != sizeof (RAMFB_CONFIG)) { DEBUG ((DEBUG_ERROR, "Ramfb: FwCfg size mismatch (expected %lu, got %lu)\n", (UINT64)sizeof (RAMFB_CONFIG), (UINT64)FwCfgSize)); return EFI_PROTOCOL_ERROR; } MaxFbSize = 0; for (Index = 0; Index < ARRAY_SIZE (mQemuRamfbModeInfo); Index++) { mQemuRamfbModeInfo[Index].PixelsPerScanLine = mQemuRamfbModeInfo[Index].HorizontalResolution; mQemuRamfbModeInfo[Index].PixelFormat = PixelBlueGreenRedReserved8BitPerColor; FbSize = RAMFB_BPP * mQemuRamfbModeInfo[Index].HorizontalResolution * mQemuRamfbModeInfo[Index].VerticalResolution; if (MaxFbSize < FbSize) { MaxFbSize = FbSize; } DEBUG ((DEBUG_INFO, "Ramfb: Mode %lu: %ux%u, %lu kB\n", (UINT64)Index, mQemuRamfbModeInfo[Index].HorizontalResolution, mQemuRamfbModeInfo[Index].VerticalResolution, (UINT64)(FbSize / 1024))); } Pages = EFI_SIZE_TO_PAGES (MaxFbSize); MaxFbSize = EFI_PAGES_TO_SIZE (Pages); FbBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateReservedPages (Pages); if (FbBase == 0) { DEBUG ((DEBUG_ERROR, "Ramfb: memory allocation failed\n")); return EFI_OUT_OF_RESOURCES; } DEBUG ((DEBUG_INFO, "Ramfb: Framebuffer at 0x%lx, %lu kB, %lu pages\n", (UINT64)FbBase, (UINT64)(MaxFbSize / 1024), (UINT64)Pages)); mQemuRamfbMode.FrameBufferSize = MaxFbSize; mQemuRamfbMode.FrameBufferBase = FbBase; // // 800 x 600 // QemuRamfbGraphicsOutputSetMode (&mQemuRamfbGraphicsOutput, 1); // // ramfb vendor devpath // VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH; VendorDeviceNode.Header.SubType = HW_VENDOR_DP; CopyGuid (&VendorDeviceNode.Guid, &gQemuRamfbGuid); SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH)); RamfbDevicePath = AppendDevicePathNode (NULL, (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode); if (RamfbDevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto FreeFramebuffer; } Status = gBS->InstallMultipleProtocolInterfaces ( &mRamfbHandle, &gEfiDevicePathProtocolGuid, RamfbDevicePath, NULL ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Ramfb: install Ramfb Vendor DevicePath failed: %r\n", Status)); goto FreeRamfbDevicePath; } // // gop devpath + protocol // AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH; AcpiDeviceNode.Header.SubType = ACPI_ADR_DP; AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR ( 1, // DeviceIdScheme 0, // HeadId 0, // NonVgaOutput 1, // BiosCanDetect 0, // VendorInfo ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, // Type 0, // Port 0 // Index ); SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH)); GopDevicePath = AppendDevicePathNode (RamfbDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode); if (GopDevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto FreeRamfbHandle; } Status = gBS->InstallMultipleProtocolInterfaces ( &mGopHandle, &gEfiDevicePathProtocolGuid, GopDevicePath, &gEfiGraphicsOutputProtocolGuid, &mQemuRamfbGraphicsOutput, NULL ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Ramfb: install GOP DevicePath failed: %r\n", Status)); goto FreeGopDevicePath; } Status = gBS->OpenProtocol ( mRamfbHandle, &gEfiDevicePathProtocolGuid, &DevicePath, gImageHandle, mGopHandle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Ramfb: OpenProtocol failed: %r\n", Status)); goto FreeGopHandle; } return EFI_SUCCESS; FreeGopHandle: gBS->UninstallMultipleProtocolInterfaces ( mGopHandle, &gEfiDevicePathProtocolGuid, GopDevicePath, &gEfiGraphicsOutputProtocolGuid, &mQemuRamfbGraphicsOutput, NULL ); FreeGopDevicePath: FreePool (GopDevicePath); FreeRamfbHandle: gBS->UninstallMultipleProtocolInterfaces ( mRamfbHandle, &gEfiDevicePathProtocolGuid, RamfbDevicePath, NULL ); FreeRamfbDevicePath: FreePool (RamfbDevicePath); FreeFramebuffer: FreePages ((VOID*)(UINTN)mQemuRamfbMode.FrameBufferBase, Pages); return Status; }