mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
Map physical address of the vga text console framebuffer in DriverInit
Currently, the kernel can write to 0xb80000 because this is part of the initial identify mapping set up by the rt0 code. When we establish new mappings for the kernel using its real VMA address then writes to the framebuffer will cause a page fault unless we explicitly map it.
This commit is contained in:
parent
8ac2ba82cc
commit
13ef4cd08d
@ -1,9 +1,15 @@
|
||||
package console
|
||||
|
||||
import "gopheros/device"
|
||||
import "gopheros/kernel/hal/multiboot"
|
||||
import (
|
||||
"gopheros/device"
|
||||
"gopheros/kernel/cpu"
|
||||
"gopheros/kernel/hal/multiboot"
|
||||
"gopheros/kernel/mem/vmm"
|
||||
)
|
||||
|
||||
var (
|
||||
mapRegionFn = vmm.MapRegion
|
||||
portWriteByteFn = cpu.PortWriteByte
|
||||
getFramebufferInfoFn = multiboot.GetFramebufferInfo
|
||||
|
||||
// ProbeFuncs is a slice of device probe functions that is used by
|
||||
|
@ -3,16 +3,17 @@ package console
|
||||
import (
|
||||
"gopheros/device"
|
||||
"gopheros/kernel"
|
||||
"gopheros/kernel/cpu"
|
||||
"gopheros/kernel/hal/multiboot"
|
||||
"gopheros/kernel/kfmt"
|
||||
"gopheros/kernel/mem"
|
||||
"gopheros/kernel/mem/pmm"
|
||||
"gopheros/kernel/mem/vmm"
|
||||
"image/color"
|
||||
"io"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var portWriteByteFn = cpu.PortWriteByte
|
||||
|
||||
// VgaTextConsole implements an EGA-compatible 80x25 text console using VGA
|
||||
// mode 0x3. The console supports the default 16 EGA colors which can be
|
||||
// overridden using the SetPaletteColor method.
|
||||
@ -28,6 +29,7 @@ type VgaTextConsole struct {
|
||||
width uint32
|
||||
height uint32
|
||||
|
||||
fbPhysAddr uintptr
|
||||
fb []uint16
|
||||
|
||||
palette color.Palette
|
||||
@ -42,13 +44,8 @@ func NewVgaTextConsole(columns, rows uint32, fbPhysAddr uintptr) *VgaTextConsole
|
||||
return &VgaTextConsole{
|
||||
width: columns,
|
||||
height: rows,
|
||||
fbPhysAddr: fbPhysAddr,
|
||||
clearChar: uint16(' '),
|
||||
// overlay a 16bit slice over the fbPhysAddr
|
||||
fb: *(*[]uint16)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Len: int(columns * rows),
|
||||
Cap: int(columns * rows),
|
||||
Data: fbPhysAddr,
|
||||
})),
|
||||
palette: color.Palette{
|
||||
color.RGBA{R: 0, G: 0, B: 1}, /* black */
|
||||
color.RGBA{R: 0, G: 0, B: 128}, /* blue */
|
||||
@ -198,7 +195,29 @@ func (cons *VgaTextConsole) DriverVersion() (uint16, uint16, uint16) {
|
||||
}
|
||||
|
||||
// DriverInit initializes this driver.
|
||||
func (cons *VgaTextConsole) DriverInit(_ io.Writer) *kernel.Error { return nil }
|
||||
func (cons *VgaTextConsole) DriverInit(w io.Writer) *kernel.Error {
|
||||
// Map the framebuffer so we can write to it
|
||||
fbSize := mem.Size(cons.width * cons.height * 2)
|
||||
fbPage, err := mapRegionFn(
|
||||
pmm.Frame(cons.fbPhysAddr>>mem.PageShift),
|
||||
fbSize,
|
||||
vmm.FlagPresent|vmm.FlagRW,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cons.fb = *(*[]uint16)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Len: int(fbSize >> 1),
|
||||
Cap: int(fbSize >> 1),
|
||||
Data: fbPage.Address(),
|
||||
}))
|
||||
|
||||
kfmt.Fprintf(w, "mapped framebuffer to 0x%x\n", fbPage.Address())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// probeForVgaTextConsole checks for the presence of a vga text console.
|
||||
func probeForVgaTextConsole() device.Driver {
|
||||
|
@ -2,8 +2,12 @@ package console
|
||||
|
||||
import (
|
||||
"gopheros/device"
|
||||
"gopheros/kernel"
|
||||
"gopheros/kernel/cpu"
|
||||
"gopheros/kernel/hal/multiboot"
|
||||
"gopheros/kernel/mem"
|
||||
"gopheros/kernel/mem/pmm"
|
||||
"gopheros/kernel/mem/vmm"
|
||||
"image/color"
|
||||
"testing"
|
||||
"unsafe"
|
||||
@ -63,6 +67,7 @@ func TestVgaTextFill(t *testing.T) {
|
||||
|
||||
fb := make([]uint16, 80*25)
|
||||
cons := NewVgaTextConsole(80, 25, uintptr(unsafe.Pointer(&fb[0])))
|
||||
cons.fb = fb
|
||||
cw, ch := cons.Dimensions()
|
||||
|
||||
testPat := uint16(0xDEAD)
|
||||
@ -101,6 +106,7 @@ nextSpec:
|
||||
func TestVgaTextScroll(t *testing.T) {
|
||||
fb := make([]uint16, 80*25)
|
||||
cons := NewVgaTextConsole(80, 25, uintptr(unsafe.Pointer(&fb[0])))
|
||||
cons.fb = fb
|
||||
cw, ch := cons.Dimensions()
|
||||
|
||||
t.Run("up", func(t *testing.T) {
|
||||
@ -176,6 +182,7 @@ func TestVgaTextScroll(t *testing.T) {
|
||||
func TestVgaTextWrite(t *testing.T) {
|
||||
fb := make([]uint16, 80*25)
|
||||
cons := NewVgaTextConsole(80, 25, uintptr(unsafe.Pointer(&fb[0])))
|
||||
cons.fb = fb
|
||||
defaultFg, defaultBg := cons.DefaultColors()
|
||||
|
||||
t.Run("off-screen", func(t *testing.T) {
|
||||
@ -309,12 +316,11 @@ func TestVgaTextSetPaletteColor(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVgaTextDriverInterface(t *testing.T) {
|
||||
defer func() {
|
||||
mapRegionFn = vmm.MapRegion
|
||||
}()
|
||||
var dev device.Driver = NewVgaTextConsole(80, 25, 0)
|
||||
|
||||
if err := dev.DriverInit(nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if dev.DriverName() == "" {
|
||||
t.Fatal("DriverName() returned an empty string")
|
||||
}
|
||||
@ -322,6 +328,27 @@ func TestVgaTextDriverInterface(t *testing.T) {
|
||||
if major, minor, patch := dev.DriverVersion(); major+minor+patch == 0 {
|
||||
t.Fatal("DriverVersion() returned an invalid version number")
|
||||
}
|
||||
|
||||
t.Run("init success", func(t *testing.T) {
|
||||
mapRegionFn = func(_ pmm.Frame, _ mem.Size, _ vmm.PageTableEntryFlag) (vmm.Page, *kernel.Error) {
|
||||
return 0xb8000, nil
|
||||
}
|
||||
|
||||
if err := dev.DriverInit(nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("init fail", func(t *testing.T) {
|
||||
expErr := &kernel.Error{Module: "test", Message: "something went wrong"}
|
||||
mapRegionFn = func(_ pmm.Frame, _ mem.Size, _ vmm.PageTableEntryFlag) (vmm.Page, *kernel.Error) {
|
||||
return 0, expErr
|
||||
}
|
||||
|
||||
if err := dev.DriverInit(nil); err != expErr {
|
||||
t.Fatalf("expected error: %v; got %v", expErr, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestVgaTextProbe(t *testing.T) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user