The Pedigree Project 0.1
mach_pc/Vga.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "Vga.h"
21#include "pedigree/kernel/BootstrapInfo.h"
22#include "pedigree/kernel/LockGuard.h"
23#include "pedigree/kernel/machine/Framebuffer.h"
24#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
25#include "pedigree/kernel/processor/VirtualAddressSpace.h"
26#include "pedigree/kernel/utilities/utility.h"
27
28X86Vga::X86Vga() : m_Framebuffer("Console framebuffer") {}
29
30X86Vga::~X86Vga() {}
31
33 LockGuard<Spinlock> guard(m_ConsoleLock);
34 m_Console.invalidate();
35 return true;
36}
37
38void X86Vga::pokeBuffer(uint8_t* pBuffer, size_t nBufLen) {
39 if (!pBuffer) {
40 return;
41 }
42 size_t length =
43 nBufLen < FramebufferConsole::CellCount * 2 ? nBufLen : FramebufferConsole::CellCount * 2;
44 MemoryCopy(m_Console.cells(), pBuffer, length);
45 flush();
46}
47
48void X86Vga::peekBuffer(uint8_t* pBuffer, size_t nBufLen) {
49 if (!pBuffer) {
50 return;
51 }
52 size_t length =
53 nBufLen < FramebufferConsole::CellCount * 2 ? nBufLen : FramebufferConsole::CellCount * 2;
54 MemoryCopy(pBuffer, m_Console.cells(), length);
55}
56
57void X86Vga::moveCursor(size_t nX, size_t nY) {
58 LockGuard<Spinlock> guard(m_ConsoleLock);
59 m_Console.moveCursor(nX, nY);
60 m_Console.flush();
61 if (m_pConsoleFramebuffer) {
62 m_pConsoleFramebuffer->redraw();
63 }
64}
65
66void X86Vga::flush() {
67 LockGuard<Spinlock> guard(m_ConsoleLock);
68 m_Console.flush();
69 if (m_pConsoleFramebuffer) {
70 m_pConsoleFramebuffer->redraw();
71 }
72}
73
74bool X86Vga::setFramebuffer(Framebuffer* framebuffer) {
75 if (!framebuffer || framebuffer->getParent() || framebuffer->getBytesPerPixel() != 4 ||
76 framebuffer->getWidth() > UINT32_MAX || framebuffer->getHeight() > UINT32_MAX ||
77 (framebuffer->getFormat() != Graphics::Bits32_Rgb &&
78 framebuffer->getFormat() != Graphics::Bits32_Bgr)) {
79 return false;
80 }
81
82 const size_t pitch = framebuffer->getBytesPerLine();
83 if (pitch && framebuffer->getHeight() > SIZE_MAX / pitch) {
84 return false;
85 }
86
87 LockGuard<Spinlock> guard(m_ConsoleLock);
88 if (!m_Console.initialise(framebuffer->getRawBuffer(), pitch * framebuffer->getHeight(),
89 framebuffer->getWidth(), framebuffer->getHeight(), pitch,
90 framebuffer->getFormat() == Graphics::Bits32_Rgb ? 1 : 0)) {
91 return false;
92 }
93
94 m_pConsoleFramebuffer = framebuffer;
95 m_Console.flush();
96 m_pConsoleFramebuffer->redraw();
97 return true;
98}
99
100bool X86Vga::initialise() {
102 // Keep serial boot available on firmware without a usable linear framebuffer.
103 if (!g_pBootstrapInfo || !g_pBootstrapInfo->getFramebuffer(info) || info.width < 640 ||
104 info.height < 400) {
105 return true;
106 }
107 const uint64_t bytes = static_cast<uint64_t>(info.pitch) * info.height;
108 if (bytes > 256 * 1024 * 1024) {
109 return true;
110 }
111 const size_t pageSize = PhysicalMemoryManager::getPageSize();
112 const size_t offset = info.address & (pageSize - 1);
113 const size_t pages = (bytes + offset + pageSize - 1) / pageSize;
115 m_Framebuffer, pages,
120 info.address - offset)) {
121 return true;
122 }
123 m_Console.initialise(reinterpret_cast<uint8_t*>(m_Framebuffer.virtualAddress()) + offset, bytes,
124 info.width, info.height, info.pitch, info.format);
125 return true;
126}
void redraw(size_t x=~0UL, size_t y=~0UL, size_t w=~0UL, size_t h=~0UL, bool bChild=false)
void * virtualAddress() const
static PhysicalMemoryManager & instance()
virtual bool allocateRegion(MemoryRegion &Region, size_t cPages, size_t pageConstraints, size_t Flags, physical_uintptr_t start=-1)=0
virtual bool setLargestTextMode()
virtual void pokeBuffer(uint8_t *pBuffer, size_t nBufLen)
virtual void moveCursor(size_t nX, size_t nY)
virtual void peekBuffer(uint8_t *pBuffer, size_t nBufLen)