blob: 0763dbe07e67c6d11cb1b8732fcc1a5edbeb48ed [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <assert.h>
#include <lib/crashlog.h>
#include <lib/debuglog.h>
#include <lib/gfxconsole.h>
#include <lib/io.h>
#include <platform.h>
#include <stdlib.h>
#include <string.h>
#include <trace.h>
#include <zircon/boot/crash-reason.h>
#include <dev/udisplay.h>
#include <ktl/move.h>
#include <platform/crashlog.h>
#include <vm/vm_address_region.h>
#include <vm/vm_aspace.h>
#include <vm/vm_object.h>
#include <ktl/enforce.h>
#define LOCAL_TRACE 0
constexpr uint kFramebufferArchMmuFlags = ARCH_MMU_FLAG_PERM_READ | ARCH_MMU_FLAG_PERM_WRITE;
struct udisplay_info {
void* framebuffer_virt;
size_t framebuffer_size;
display_info info;
fbl::RefPtr<VmMapping> framebuffer_vmo_mapping;
};
static struct udisplay_info g_udisplay = {};
zx_status_t udisplay_init(void) { return ZX_OK; }
void udisplay_clear_framebuffer_vmo() {
if (g_udisplay.framebuffer_vmo_mapping) {
g_udisplay.framebuffer_size = 0;
g_udisplay.framebuffer_virt = 0;
g_udisplay.framebuffer_vmo_mapping->Destroy();
g_udisplay.framebuffer_vmo_mapping = nullptr;
}
}
zx_status_t udisplay_set_framebuffer(fbl::RefPtr<VmObject> vmo) {
udisplay_clear_framebuffer_vmo();
const size_t size = vmo->size();
zx::result<VmAddressRegion::MapResult> mapping_result =
VmAspace::kernel_aspace()->RootVmar()->CreateVmMapping(
0 /* ignored */, size, 0 /* align pow2 */, 0 /* vmar flags */, ktl::move(vmo), 0,
kFramebufferArchMmuFlags, "framebuffer_vmo");
if (mapping_result.is_error()) {
return mapping_result.status_value();
}
zx_status_t status = mapping_result->mapping->MapRange(0, size, true);
if (status != ZX_OK) {
mapping_result->mapping->Destroy();
return status;
}
g_udisplay.framebuffer_virt = reinterpret_cast<void*>(mapping_result->base);
g_udisplay.framebuffer_size = size;
g_udisplay.framebuffer_vmo_mapping = mapping_result->mapping;
return ZX_OK;
}
zx_status_t udisplay_set_display_info(display_info* display) {
memcpy(&g_udisplay.info, display, sizeof(display_info));
return ZX_OK;
}
zx_status_t udisplay_bind_gfxconsole(void) {
if (g_udisplay.framebuffer_virt == 0)
return ZX_ERR_NOT_FOUND;
// bind the display to the gfxconsole
g_udisplay.info.framebuffer = g_udisplay.framebuffer_virt;
g_udisplay.info.flags = DISPLAY_FLAG_NEEDS_CACHE_FLUSH | DISPLAY_FLAG_CRASH_FRAMEBUFFER;
gfxconsole_bind_display(&g_udisplay.info, nullptr);
return ZX_OK;
}