vesa & framebuffer: Clone the framebuffer instead of having it be user-accessible.
This begins paving the way for removal of user access to kernel address space. After the previous commits, BDirectWindow and BWindowScreen still function properly. Part of #19990. Change-Id: I8477e43cd517ba67383755a4cb60b00bc117f5d7 Reviewed-on: https://review.haiku-os.org/c/haiku/+/10559 Reviewed-by: waddlesplash <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
95ace7f374
commit
9be0e148a2
@@ -37,11 +37,6 @@ struct vesa_shared_info {
|
||||
display_mode current_mode;
|
||||
uint32 bytes_per_row;
|
||||
|
||||
area_id frame_buffer_area; // area of frame buffer
|
||||
uint8* frame_buffer;
|
||||
// pointer to frame buffer (visible by all apps!)
|
||||
uint8* physical_frame_buffer;
|
||||
|
||||
uint32 vesa_mode_offset;
|
||||
uint32 vesa_mode_count;
|
||||
|
||||
@@ -62,6 +57,7 @@ struct vesa_shared_info {
|
||||
// list ioctls
|
||||
enum {
|
||||
VESA_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1,
|
||||
VESA_CLONE_FRAME_BUFFER,
|
||||
VESA_GET_DEVICE_NAME,
|
||||
VESA_SET_DISPLAY_MODE,
|
||||
VESA_GET_DPMS_MODE,
|
||||
|
||||
@@ -50,6 +50,7 @@ init_common(int device, bool isClone)
|
||||
gInfo->is_clone = isClone;
|
||||
gInfo->device = device;
|
||||
gInfo->current_mode = UINT16_MAX;
|
||||
gInfo->frame_buffer_area = -1;
|
||||
|
||||
// get basic info from driver
|
||||
|
||||
@@ -74,6 +75,7 @@ init_common(int device, bool isClone)
|
||||
static void
|
||||
uninit_common(void)
|
||||
{
|
||||
delete_area(gInfo->frame_buffer_area);
|
||||
delete_area(gInfo->shared_info_area);
|
||||
gInfo->shared_info_area = -1;
|
||||
gInfo->shared_info = NULL;
|
||||
@@ -106,6 +108,16 @@ framebuffer_init_accelerant(int device)
|
||||
return status;
|
||||
}
|
||||
|
||||
area_info info;
|
||||
status = ioctl(gInfo->device, VESA_CLONE_FRAME_BUFFER, &info, sizeof(info));
|
||||
if (status != B_OK) {
|
||||
uninit_common();
|
||||
return status;
|
||||
}
|
||||
|
||||
gInfo->frame_buffer_area = info.area;
|
||||
gInfo->frame_buffer = info.address;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@ typedef struct accelerant_info {
|
||||
// cloned list of standard display modes
|
||||
display_mode *mode_list;
|
||||
uint16 current_mode;
|
||||
|
||||
area_id frame_buffer_area;
|
||||
// cloned framebuffer
|
||||
void* frame_buffer;
|
||||
} accelerant_info;
|
||||
|
||||
extern accelerant_info *gInfo;
|
||||
|
||||
@@ -134,8 +134,8 @@ framebuffer_get_frame_buffer_config(frame_buffer_config* config)
|
||||
{
|
||||
TRACE(("framebuffer_get_frame_buffer_config()\n"));
|
||||
|
||||
config->frame_buffer = gInfo->shared_info->frame_buffer;
|
||||
config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer;
|
||||
config->frame_buffer = gInfo->frame_buffer;
|
||||
config->frame_buffer_dma = NULL;
|
||||
config->bytes_per_row = gInfo->shared_info->bytes_per_row;
|
||||
|
||||
return B_OK;
|
||||
|
||||
@@ -49,6 +49,7 @@ init_common(int device, bool isClone)
|
||||
gInfo->is_clone = isClone;
|
||||
gInfo->device = device;
|
||||
gInfo->current_mode = UINT16_MAX;
|
||||
gInfo->frame_buffer_area = -1;
|
||||
|
||||
// get basic info from driver
|
||||
|
||||
@@ -110,6 +111,7 @@ vesa_init_accelerant(int device)
|
||||
|
||||
// Initialize current mode completely from the mode list
|
||||
vesa_propose_display_mode(&gInfo->shared_info->current_mode, NULL, NULL);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@ typedef struct accelerant_info {
|
||||
int16 current_mode; // index in the mode_list, or -1 if using a custom mode
|
||||
|
||||
vesa_mode *vesa_modes;
|
||||
|
||||
area_id frame_buffer_area;
|
||||
// cloned framebuffer
|
||||
void* frame_buffer;
|
||||
} accelerant_info;
|
||||
|
||||
extern accelerant_info *gInfo;
|
||||
|
||||
@@ -231,8 +231,13 @@ vesa_set_display_mode(display_mode* _mode)
|
||||
if (gInfo->current_mode == i)
|
||||
return B_OK;
|
||||
status_t result = ioctl(gInfo->device, VESA_SET_DISPLAY_MODE, &i, sizeof(i));
|
||||
if (result == B_OK)
|
||||
if (result == B_OK) {
|
||||
delete_area(gInfo->frame_buffer_area);
|
||||
gInfo->frame_buffer_area = -1;
|
||||
gInfo->frame_buffer = NULL;
|
||||
|
||||
gInfo->current_mode = i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -241,6 +246,10 @@ vesa_set_display_mode(display_mode* _mode)
|
||||
status_t result = ioctl(gInfo->device, VESA_SET_CUSTOM_DISPLAY_MODE,
|
||||
&mode, sizeof(display_mode));
|
||||
if (result == B_OK) {
|
||||
delete_area(gInfo->frame_buffer_area);
|
||||
gInfo->frame_buffer_area = -1;
|
||||
gInfo->frame_buffer = NULL;
|
||||
|
||||
gInfo->current_mode = -1;
|
||||
}
|
||||
|
||||
@@ -278,8 +287,20 @@ vesa_get_frame_buffer_config(frame_buffer_config* config)
|
||||
{
|
||||
TRACE(("vesa_get_frame_buffer_config()\n"));
|
||||
|
||||
config->frame_buffer = gInfo->shared_info->frame_buffer;
|
||||
config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer;
|
||||
if (gInfo->frame_buffer == NULL) {
|
||||
// Clone the current framebuffer.
|
||||
area_info info;
|
||||
status_t status = ioctl(gInfo->device, VESA_CLONE_FRAME_BUFFER,
|
||||
&info, sizeof(info));
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
gInfo->frame_buffer_area = info.area;
|
||||
gInfo->frame_buffer = info.address;
|
||||
}
|
||||
|
||||
config->frame_buffer = gInfo->frame_buffer;
|
||||
config->frame_buffer_dma = NULL;
|
||||
config->bytes_per_row = gInfo->shared_info->bytes_per_row;
|
||||
|
||||
return B_OK;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <OS.h>
|
||||
#include <PCI.h>
|
||||
#include <SupportDefs.h>
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <vesa.h>
|
||||
|
||||
@@ -113,6 +114,18 @@ device_ioctl(void* cookie, uint32 msg, void* buffer, size_t bufferLength)
|
||||
|
||||
return B_OK;
|
||||
|
||||
case VESA_CLONE_FRAME_BUFFER:
|
||||
{
|
||||
void* dummy;
|
||||
area_id area = vm_clone_area(B_CURRENT_TEAM, "cloned framebuffer",
|
||||
&dummy, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, 0,
|
||||
info->frame_buffer_area, true);
|
||||
if (area < 0)
|
||||
return area;
|
||||
|
||||
return _user_get_area_info(area, (area_info*)buffer);
|
||||
}
|
||||
|
||||
// needed to share data between kernel and accelerant
|
||||
case VESA_GET_PRIVATE_DATA:
|
||||
return user_memcpy(buffer, &info->shared_area, sizeof(area_id));
|
||||
|
||||
@@ -49,7 +49,7 @@ get_color_space_for_depth(uint32 depth)
|
||||
|
||||
static status_t
|
||||
remap_frame_buffer(framebuffer_info& info, addr_t physicalBase, uint32 width,
|
||||
uint32 height, int8 depth, uint32 bytesPerRow, bool initializing)
|
||||
uint32 height, int8 depth, uint32 bytesPerRow)
|
||||
{
|
||||
vesa_shared_info& sharedInfo = *info.shared_info;
|
||||
addr_t frameBuffer = info.frame_buffer;
|
||||
@@ -63,25 +63,19 @@ remap_frame_buffer(framebuffer_info& info, addr_t physicalBase, uint32 width,
|
||||
if (area < 0)
|
||||
return area;
|
||||
|
||||
if (initializing) {
|
||||
// We need to manually update the kernel's frame buffer address,
|
||||
// since this frame buffer remapping has not been issued by the
|
||||
// app_server (which would otherwise take care of this)
|
||||
frame_buffer_update(frameBuffer, width, height, depth,
|
||||
bytesPerRow);
|
||||
}
|
||||
frame_buffer_update(frameBuffer, width, height, depth,
|
||||
bytesPerRow);
|
||||
|
||||
delete_area(info.shared_info->frame_buffer_area);
|
||||
vm_change_clones_to_null_areas(info.frame_buffer_area);
|
||||
delete_area(info.frame_buffer_area);
|
||||
|
||||
info.frame_buffer = frameBuffer;
|
||||
sharedInfo.frame_buffer_area = area;
|
||||
info.frame_buffer_area = area;
|
||||
|
||||
// Turn on write combining for the area
|
||||
vm_set_area_memory_type(area, base, B_WRITE_COMBINING_MEMORY);
|
||||
|
||||
// Update shared frame buffer information
|
||||
sharedInfo.frame_buffer = (uint8*)frameBuffer;
|
||||
sharedInfo.physical_frame_buffer = (uint8*)physicalBase;
|
||||
sharedInfo.bytes_per_row = bytesPerRow;
|
||||
|
||||
return B_OK;
|
||||
@@ -112,11 +106,11 @@ framebuffer_init(framebuffer_info& info)
|
||||
|
||||
memset(&sharedInfo, 0, sizeof(vesa_shared_info));
|
||||
|
||||
sharedInfo.frame_buffer_area = bufferInfo->area;
|
||||
info.frame_buffer_area = bufferInfo->area;
|
||||
|
||||
remap_frame_buffer(info, bufferInfo->physical_frame_buffer,
|
||||
bufferInfo->width, bufferInfo->height, bufferInfo->depth,
|
||||
bufferInfo->bytes_per_row, true);
|
||||
bufferInfo->bytes_per_row);
|
||||
// Does not matter if this fails - the frame buffer was already mapped
|
||||
// before.
|
||||
|
||||
@@ -142,6 +136,7 @@ framebuffer_uninit(framebuffer_info& info)
|
||||
{
|
||||
dprintf(DEVICE_NAME": framebuffer_uninit()\n");
|
||||
|
||||
delete_area(info.shared_info->frame_buffer_area);
|
||||
vm_change_clones_to_null_areas(info.frame_buffer_area);
|
||||
delete_area(info.frame_buffer_area);
|
||||
delete_area(info.shared_area);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ struct framebuffer_info {
|
||||
struct vesa_shared_info* shared_info;
|
||||
area_id shared_area;
|
||||
|
||||
area_id frame_buffer_area;
|
||||
addr_t frame_buffer;
|
||||
};
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <OS.h>
|
||||
#include <PCI.h>
|
||||
#include <SupportDefs.h>
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <vesa.h>
|
||||
|
||||
@@ -113,6 +114,18 @@ device_ioctl(void* cookie, uint32 msg, void* buffer, size_t bufferLength)
|
||||
|
||||
return B_OK;
|
||||
|
||||
case VESA_CLONE_FRAME_BUFFER:
|
||||
{
|
||||
void* dummy;
|
||||
area_id area = vm_clone_area(B_CURRENT_TEAM, "cloned framebuffer",
|
||||
&dummy, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, 0,
|
||||
info->frame_buffer_area, true);
|
||||
if (area < 0)
|
||||
return area;
|
||||
|
||||
return _user_get_area_info(area, (area_info*)buffer);
|
||||
}
|
||||
|
||||
// needed to share data between kernel and accelerant
|
||||
case VESA_GET_PRIVATE_DATA:
|
||||
return user_memcpy(buffer, &info->shared_area, sizeof(area_id));
|
||||
@@ -215,7 +228,7 @@ device_ioctl(void* cookie, uint32 msg, void* buffer, size_t bufferLength)
|
||||
if (user_memcpy(&args, buffer, sizeof(args)) != B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return vga_planar_blit(info->shared_info, args.source,
|
||||
return vga_planar_blit(info, args.source,
|
||||
args.source_bytes_per_row, args.left, args.top,
|
||||
args.right, args.bottom);
|
||||
}
|
||||
|
||||
@@ -316,23 +316,19 @@ remap_frame_buffer(vesa_info& info, addr_t physicalBase, uint32 width,
|
||||
|
||||
if (remap) {
|
||||
area_id area = map_physical_memory("vesa frame buffer", base,
|
||||
size, B_ANY_KERNEL_ADDRESS, B_READ_AREA | B_WRITE_AREA,
|
||||
size, B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
|
||||
(void**)&frameBuffer);
|
||||
if (area < 0)
|
||||
return area;
|
||||
|
||||
if (initializing) {
|
||||
// We need to manually update the kernel's frame buffer address,
|
||||
// since this frame buffer remapping has not been issued by the
|
||||
// app_server (which would otherwise take care of this)
|
||||
frame_buffer_update(frameBuffer, width, height, depth,
|
||||
bytesPerRow);
|
||||
}
|
||||
frame_buffer_update(frameBuffer, width, height, depth,
|
||||
bytesPerRow);
|
||||
|
||||
delete_area(info.shared_info->frame_buffer_area);
|
||||
vm_change_clones_to_null_areas(info.frame_buffer_area);
|
||||
delete_area(info.frame_buffer_area);
|
||||
|
||||
info.frame_buffer = frameBuffer;
|
||||
sharedInfo.frame_buffer_area = area;
|
||||
info.frame_buffer_area = area;
|
||||
|
||||
// Turn on write combining for the area
|
||||
vm_set_area_memory_type(area, base, B_WRITE_COMBINING_MEMORY);
|
||||
@@ -346,8 +342,6 @@ remap_frame_buffer(vesa_info& info, addr_t physicalBase, uint32 width,
|
||||
frameBuffer += physicalBase - info.physical_frame_buffer;
|
||||
|
||||
// Update shared frame buffer information
|
||||
sharedInfo.frame_buffer = (uint8*)frameBuffer;
|
||||
sharedInfo.physical_frame_buffer = (uint8*)physicalBase;
|
||||
sharedInfo.bytes_per_row = bytesPerRow;
|
||||
|
||||
return B_OK;
|
||||
@@ -400,7 +394,7 @@ vesa_init(vesa_info& info)
|
||||
memcpy((uint8*)&sharedInfo + sharedSize, modes, modesSize);
|
||||
}
|
||||
|
||||
sharedInfo.frame_buffer_area = bufferInfo->area;
|
||||
info.frame_buffer_area = bufferInfo->area;
|
||||
|
||||
remap_frame_buffer(info, bufferInfo->physical_frame_buffer,
|
||||
bufferInfo->width, bufferInfo->height, bufferInfo->depth,
|
||||
@@ -476,7 +470,8 @@ vesa_uninit(vesa_info& info)
|
||||
{
|
||||
dprintf(DEVICE_NAME": vesa_uninit()\n");
|
||||
|
||||
delete_area(info.shared_info->frame_buffer_area);
|
||||
vm_change_clones_to_null_areas(info.frame_buffer_area);
|
||||
delete_area(info.frame_buffer_area);
|
||||
delete_area(info.shared_area);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ struct vesa_info {
|
||||
uint8 vbe_capabilities;
|
||||
uint8 bits_per_gun;
|
||||
|
||||
area_id frame_buffer_area;
|
||||
addr_t frame_buffer;
|
||||
addr_t physical_frame_buffer;
|
||||
size_t physical_frame_buffer_size;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "vga.h"
|
||||
#include "driver.h"
|
||||
|
||||
#include <vesa_info.h>
|
||||
#include <vga.h>
|
||||
|
||||
#include <KernelExport.h>
|
||||
@@ -40,7 +41,7 @@ vga_set_indexed_colors(uint8 first, uint8 *colors, uint16 count)
|
||||
|
||||
|
||||
status_t
|
||||
vga_planar_blit(vesa_shared_info *info, uint8 *src, int32 srcBPR,
|
||||
vga_planar_blit(vesa_info *info, uint8 *src, int32 srcBPR,
|
||||
int32 left, int32 top, int32 right, int32 bottom)
|
||||
{
|
||||
// If we don't actually have an ISA bus, bail.
|
||||
@@ -48,11 +49,11 @@ vga_planar_blit(vesa_shared_info *info, uint8 *src, int32 srcBPR,
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
// If we don't actually have a frame_buffer, bail.
|
||||
if (info->frame_buffer == NULL)
|
||||
if (info->frame_buffer == 0)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
int32 dstBPR = info->bytes_per_row;
|
||||
uint8 *dst = info->frame_buffer + top * dstBPR + left / 8;
|
||||
int32 dstBPR = info->shared_info->bytes_per_row;
|
||||
uint8 *dst = (uint8*)(info->frame_buffer + top * dstBPR + left / 8);
|
||||
|
||||
// TODO: this is awfully slow...
|
||||
// TODO: assumes BGR order
|
||||
|
||||
@@ -6,11 +6,12 @@
|
||||
#define _VGA_H
|
||||
|
||||
|
||||
#include <vesa_info.h>
|
||||
#include "vesa_private.h"
|
||||
|
||||
|
||||
status_t vga_set_indexed_colors(uint8 first, uint8 *colors, uint16 count);
|
||||
status_t vga_planar_blit(vesa_shared_info *info, uint8 *src, int32 srcBPR,
|
||||
status_t vga_planar_blit(vesa_info *info, uint8 *src, int32 srcBPR,
|
||||
int32 left, int32 top, int32 right, int32 bottom);
|
||||
|
||||
|
||||
#endif /* _VGA_H */
|
||||
|
||||
Reference in New Issue
Block a user