[GSoC] [ARM] Patch by Johannes Wischert.

Stubbed u-boot platform code. Mostly copied from other platforms.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31818 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
François Revol 2009-07-27 16:13:38 +00:00
parent 811662afae
commit 20cbef82a4
21 changed files with 2923 additions and 0 deletions

View File

@ -0,0 +1,45 @@
SubDir HAIKU_TOP src system boot platform u-boot ;
SubDirHdrs $(HAIKU_TOP) headers private kernel boot platform $(TARGET_BOOT_PLATFORM) ;
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
UsePrivateHeaders [ FDirName graphics common ] ;
UsePrivateHeaders [ FDirName graphics vesa ] ;
UsePrivateHeaders [ FDirName storage ] ;
{
local defines = _BOOT_MODE ;
defines = [ FDefines $(defines) ] ;
SubDirCcFlags $(defines) -Wall -Wno-multichar -g3 ;
SubDirC++Flags $(defines) -Wall -Wno-multichar -fno-rtti ;
}
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ;
KernelMergeObject boot_platform_u-boot.o :
start.S
start2.c
debug.c
console.cpp
serial.cpp
devices.cpp
keyboard.cpp
menu.cpp
cpu.cpp
video.cpp
mmu.cpp
uart.c
# generic
text_menu.cpp
: -fno-pic
;
SEARCH on [ FGristFiles text_menu.cpp ]
= [ FDirName $(HAIKU_TOP) src system boot platform generic ] ;
# Tell the build system to where stage1.bin can be found, so it can be used
# elsewhere.
SEARCH on stage1.bin = $(SUBDIR) ;

View File

@ -0,0 +1,112 @@
/*
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "console.h"
#include "keyboard.h"
#include <SupportDefs.h>
#include <util/kernel_cpp.h>
#include <boot/stage2.h>
#include <string.h>
class Console : public ConsoleNode {
public:
Console();
virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize);
virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize);
};
static Console sInput, sOutput;
FILE *stdin, *stdout, *stderr;
static void
scroll_up()
{
}
// #pragma mark -
Console::Console()
: ConsoleNode()
{
}
ssize_t
Console::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
{
// don't seek in character devices
// not implemented (and not yet? needed)
return B_ERROR;
}
ssize_t
Console::WriteAt(void *cookie, off_t /*pos*/, const void *buffer, size_t bufferSize)
{
return 0;
}
// #pragma mark -
void
console_clear_screen(void)
{
}
int32
console_width(void)
{
return 80;
}
int32
console_height(void)
{
return 25;
}
void
console_set_cursor(int32 x, int32 y)
{
}
void
console_set_color(int32 foreground, int32 background)
{
}
int
console_wait_for_key(void)
{
return 0;
}
status_t
console_init(void)
{
return B_OK;
}

View File

@ -0,0 +1,20 @@
/*
** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
** Distributed under the terms of the Haiku License.
*/
#ifndef CONSOLE_H
#define CONSOLE_H
#include <boot/platform/generic/text_console.h>
#ifdef __cplusplus
extern "C" {
#endif
extern status_t console_init(void);
#ifdef __cplusplus
}
#endif
#endif /* CONSOLE_H */

View File

@ -0,0 +1,76 @@
/*
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*
* calculate_cpu_conversion_factor() was written by Travis Geiselbrecht and
* licensed under the NewOS license.
*/
#include "cpu.h"
#include <OS.h>
#include <boot/platform.h>
#include <boot/stdio.h>
#include <boot/kernel_args.h>
#include <boot/stage2.h>
#include <arch/cpu.h>
#include <arch_kernel.h>
#include <arch_system_info.h>
#include <string.h>
//#define TRACE_CPU
#ifdef TRACE_CPU
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
//uint32 gTimeConversionFactor;
static void
calculate_cpu_conversion_factor()
{
#warning ARM:TODO!
}
static status_t
check_cpu_features()
{
#warning ARM:TODO!
return B_OK;
}
// #pragma mark -
extern "C" void
spin(bigtime_t microseconds)
{
for(bigtime_t i=0;i<microseconds;i=i+1)
{
asm volatile ("mov r0,r0");
asm volatile ("mov r0,r0");
}
#warning ARM/UBOOT:TODO!!
}
extern "C" void
cpu_init()
{
if (check_cpu_features() != B_OK)
panic("You need a Pentium or higher in order to boot!\n");
calculate_cpu_conversion_factor();
gKernelArgs.num_cpus = 1;
// this will eventually be corrected later on
}

View File

@ -0,0 +1,22 @@
/*
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef CPU_H
#define CPU_H
#include <SupportDefs.h>
#ifdef __cplusplus
extern "C" {
#endif
extern void cpu_init(void);
#ifdef __cplusplus
}
#endif
#endif /* CPU_H */

View File

@ -0,0 +1,54 @@
/*
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#include "serial.h"
#include "keyboard.h"
#include <boot/platform.h>
#include <boot/stdio.h>
#include <stdarg.h>
/*! This works only after console_init() was called.
*/
void
panic(const char *format, ...)
{
va_list list;
platform_switch_to_text_mode();
puts("*** PANIC ***");
va_start(list, format);
vprintf(format, list);
va_end(list);
puts("\nPress key to reboot.");
clear_key_buffer();
wait_for_key();
platform_exit();
}
void
dprintf(const char *format, ...)
{
char buffer[512];
va_list list;
int length;
va_start(list, format);
length = vsnprintf(buffer, sizeof(buffer), format, list);
va_end(list);
serial_puts(buffer, length);
if (platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT)
fprintf(stderr, "%s", buffer);
}

View File

@ -0,0 +1,74 @@
/*
* Copyright 2009, Johannes Wischert, johanneswi@gmail.com. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <KernelExport.h>
#include <boot/platform.h>
#include <boot/vfs.h>
#include <boot/stdio.h>
#include <boot/stage2.h>
#define TRACE_DEVICES
#ifdef TRACE_DEVICES
# define TRACE(x...) dprintf(x)
#else
# define TRACE(x...)
#endif
status_t
platform_add_boot_device(struct stage2_args *args, NodeList *devicesList)
{
#warning ARM: correct/configurable "initrd" location
uint8* data = (uint8*)0xa5000000;
size_t size = 0;
TRACE("platform_add_boot_device\n");
MemoryDisk* disk = new(nothrow) MemoryDisk(data, size, "boot.tgz");
if (!disk) {
dprintf("platform_add_boot_device(): Could not create MemoryDisk !\n");
return B_NO_MEMORY;
}
devicesList->Add(disk);
return B_OK;
}
status_t
platform_get_boot_partition(struct stage2_args *args, Node *device,
NodeList *list, boot::Partition **_partition)
{
TRACE("platform_get_boot_partition\n");
NodeIterator iterator = list->GetIterator();
boot::Partition *partition = NULL;
while ((partition = (boot::Partition *)iterator.Next()) != NULL) {
// ToDo: just take the first partition for now
*_partition = partition;
return B_OK;
}
return B_ENTRY_NOT_FOUND;
}
status_t
platform_add_block_devices(stage2_args *args, NodeList *devicesList)
{
TRACE("platform_add_block_devices\n");
return B_OK;
}
status_t
platform_register_boot_device(Node *device)
{
TRACE("platform_register_boot_device\n");
return B_OK;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,45 @@
/*
** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
#include "keyboard.h"
#include <boot/platform.h>
/** Note, checking for keys doesn't seem to work in graphics
* mode, at least in Bochs.
*/
static uint16
check_for_key(void)
{
return 0;
}
extern "C" void
clear_key_buffer(void)
{
while (check_for_key() != 0)
;
}
extern "C" union key
wait_for_key(void)
{
union key key;
key.ax=0;
return key;
}
extern "C" uint32
check_for_boot_keys(void)
{
return 0;
}

View File

@ -0,0 +1,37 @@
#ifndef KEYBOARD_H
#define KEYBOARD_H
#include <SupportDefs.h>
union key {
uint16 ax;
struct {
uint8 ascii;
uint8 bios;
} code;
};
#define BIOS_KEY_UP 0x48
#define BIOS_KEY_DOWN 0x50
#define BIOS_KEY_LEFT 0x4b
#define BIOS_KEY_RIGHT 0x4d
#define BIOS_KEY_HOME 0x47
#define BIOS_KEY_END 0x4f
#define BIOS_KEY_PAGE_UP 0x49
#define BIOS_KEY_PAGE_DOWN 0x51
#ifdef __cplusplus
extern "C" {
#endif
extern void clear_key_buffer(void);
extern union key wait_for_key(void);
extern uint32 check_for_boot_keys(void);
#ifdef __cplusplus
}
#endif
#endif /* KEYBOARD_H */

View File

@ -0,0 +1,75 @@
/*
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "smp.h"
#include "video.h"
#include <boot/menu.h>
#include <boot/platform/generic/text_menu.h>
#include <safemode.h>
void
platform_add_menus(Menu *menu)
{
MenuItem *item;
/*switch (menu->Type()) {
case MAIN_MENU:
menu->AddItem(item = new(nothrow) MenuItem("Select fail-safe video mode", video_mode_menu()));
item->SetTarget(video_mode_hook);
break;
case SAFE_MODE_MENU:
menu->AddItem(item = new(nothrow) MenuItem("Use fail-safe video mode"));
item->SetType(MENU_ITEM_MARKABLE);
item->SetData(B_SAFEMODE_FAIL_SAFE_VIDEO_MODE);
item->SetHelpText("The system will use VESA mode "
"and won't try to use any video graphics drivers.");
smp_add_safemode_menus(menu);
menu->AddItem(item = new(nothrow) MenuItem("Don't call the BIOS"));
item->SetHelpText("Stops the system from calling BIOS functions.");
item->SetType(MENU_ITEM_MARKABLE);
menu->AddItem(item = new(nothrow) MenuItem("Disable APM"));
item->SetType(MENU_ITEM_MARKABLE);
item->SetData(B_SAFEMODE_DISABLE_APM);
item->SetHelpText("Disables Advanced Power Management hardware support, "
"overriding the APM setting in the kernel settings file.");
menu->AddItem(item = new(nothrow) MenuItem("Disable ACPI"));
item->SetType(MENU_ITEM_MARKABLE);
item->SetData(B_SAFEMODE_DISABLE_ACPI);
item->SetHelpText("Disables Advanced Configuration and Power "
"Interface hardware support, overriding the ACPI setting "
"in the kernel settings file.");
menu->AddItem(item = new(nothrow) MenuItem("Disable IO-APIC"));
item->SetType(MENU_ITEM_MARKABLE);
item->SetData(B_SAFEMODE_DISABLE_IOAPIC);
item->SetHelpText("Disables using the IO APIC for interrupt handling, "
"forcing instead the use of the PIC.");
break;
default:
break;
}*/
}
void
platform_update_menu_item(Menu *menu, MenuItem *item)
{
platform_generic_update_text_menu_item(menu, item);
}
void
platform_run_menu(Menu *menu)
{
platform_generic_run_text_menu(menu);
}

View File

@ -0,0 +1,727 @@
/*
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
* Based on code written by Travis Geiselbrecht for NewOS.
*
* Distributed under the terms of the MIT License.
*/
#include "mmu.h"
#include <boot/platform.h>
#include <boot/stdio.h>
#include <boot/kernel_args.h>
#include <boot/stage2.h>
#include <arch/cpu.h>
#include <arch_kernel.h>
#include <kernel.h>
#include <OS.h>
#include <string.h>
/*! The (physical) memory layout of the boot loader is currently as follows:
0x0500 - 0x10000 protected mode stack
0x0500 - 0x09000 real mode stack
0x10000 - ? code (up to ~500 kB)
0x90000 1st temporary page table (identity maps 0-4 MB)
0x91000 2nd (4-8 MB)
0x92000 - 0x92000 further page tables
0x9e000 - 0xa0000 SMP trampoline code
[0xa0000 - 0x100000 BIOS/ROM/reserved area]
0x100000 page directory
... boot loader heap (32 kB)
... free physical memory
The first 8 MB are identity mapped (0x0 - 0x0800000); paging is turned
on. The kernel is mapped at 0x80000000, all other stuff mapped by the
loader (kernel args, modules, driver settings, ...) comes after
0x80020000 which means that there is currently only 2 MB reserved for
the kernel itself (see kMaxKernelSize).
The layout in PXE mode differs a bit from this, see definitions below.
*/
//#define TRACE_MMU
#ifdef TRACE_MMU
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
//#define TRACE_MEMORY_MAP
// Define this to print the memory map to serial debug,
// You also need to define ENABLE_SERIAL in serial.cpp
// for output to work.
struct gdt_idt_descr {
uint16 limit;
uint32 *base;
} _PACKED;
// memory structure returned by int 0x15, ax 0xe820
struct extended_memory {
uint64 base_addr;
uint64 length;
uint32 type;
};
static const uint32 kDefaultPageTableFlags = 0x07; // present, user, R/W
static const size_t kMaxKernelSize = 0x200000; // 2 MB for the kernel
// working page directory and page table
static uint32 *sPageDirectory = 0;
static addr_t sNextPhysicalAddress = 0xa4000000; //ARM:TODO usefull value...
static addr_t sNextVirtualAddress = KERNEL_BASE + kMaxKernelSize;
static addr_t sMaxVirtualAddress = KERNEL_BASE + 0x400000;
static addr_t sNextPageTableAddress = 0x90000;
static const uint32 kPageTableRegionEnd = 0x9e000;
// we need to reserve 2 pages for the SMP trampoline code
static addr_t
get_next_virtual_address(size_t size)
{
addr_t address = sNextVirtualAddress;
sNextVirtualAddress += size;
return address;
}
static addr_t
get_next_physical_address(size_t size)
{
addr_t address = sNextPhysicalAddress;
sNextPhysicalAddress += size;
return address;
}
static addr_t
get_next_virtual_page()
{
return get_next_virtual_address(B_PAGE_SIZE);
}
static addr_t
get_next_physical_page()
{
return get_next_physical_address(B_PAGE_SIZE);
}
static uint32 *
get_next_page_table()
{
TRACE(("get_next_page_table, sNextPageTableAddress %p, kPageTableRegionEnd "
"%p\n", sNextPageTableAddress, kPageTableRegionEnd));
addr_t address = sNextPageTableAddress;
if (address >= kPageTableRegionEnd)
return (uint32 *)get_next_physical_page();
sNextPageTableAddress += B_PAGE_SIZE;
return (uint32 *)address;
}
/*! Adds a new page table for the specified base address */
static void
add_page_table(addr_t base)
{
/* TRACE(("add_page_table(base = %p)\n", (void *)base));
// Get new page table and clear it out
uint32 *pageTable = get_next_page_table();
if (pageTable > (uint32 *)(8 * 1024 * 1024)) {
panic("tried to add page table beyond the indentity mapped 8 MB "
"region\n");
}
gKernelArgs.arch_args.pgtables[gKernelArgs.arch_args.num_pgtables++]
= (uint32)pageTable;
for (int32 i = 0; i < 1024; i++)
pageTable[i] = 0;
// put the new page table into the page directory
sPageDirectory[base / (4 * 1024 * 1024)]
= (uint32)pageTable | kDefaultPageTableFlags;*/
}
static void
unmap_page(addr_t virtualAddress)
{
/* TRACE(("unmap_page(virtualAddress = %p)\n", (void *)virtualAddress));
if (virtualAddress < KERNEL_BASE) {
panic("unmap_page: asked to unmap invalid page %p!\n",
(void *)virtualAddress);
}
// unmap the page from the correct page table
uint32 *pageTable = (uint32 *)(sPageDirectory[virtualAddress
/ (B_PAGE_SIZE * 1024)] & 0xfffff000);
pageTable[(virtualAddress % (B_PAGE_SIZE * 1024)) / B_PAGE_SIZE] = 0;
asm volatile("invlpg (%0)" : : "r" (virtualAddress));*/
}
/*! Creates an entry to map the specified virtualAddress to the given
physicalAddress.
If the mapping goes beyond the current page table, it will allocate
a new one. If it cannot map the requested page, it panics.
*/
static void
map_page(addr_t virtualAddress, addr_t physicalAddress, uint32 flags)
{
/* TRACE(("map_page: vaddr 0x%lx, paddr 0x%lx\n", virtualAddress, physicalAddress));
if (virtualAddress < KERNEL_BASE) {
panic("map_page: asked to map invalid page %p!\n",
(void *)virtualAddress);
}
if (virtualAddress >= sMaxVirtualAddress) {
// we need to add a new page table
add_page_table(sMaxVirtualAddress);
sMaxVirtualAddress += B_PAGE_SIZE * 1024;
if (virtualAddress >= sMaxVirtualAddress) {
panic("map_page: asked to map a page to %p\n",
(void *)virtualAddress);
}
}
physicalAddress &= ~(B_PAGE_SIZE - 1);
// map the page to the correct page table
uint32 *pageTable = (uint32 *)(sPageDirectory[virtualAddress
/ (B_PAGE_SIZE * 1024)] & 0xfffff000);
uint32 tableEntry = (virtualAddress % (B_PAGE_SIZE * 1024)) / B_PAGE_SIZE;
TRACE(("map_page: inserting pageTable %p, tableEntry %ld, physicalAddress "
"%p\n", pageTable, tableEntry, physicalAddress));
pageTable[tableEntry] = physicalAddress | flags;
asm volatile("invlpg (%0)" : : "r" (virtualAddress));
TRACE(("map_page: done\n"));*/
}
static void
sort_addr_range(addr_range *range, int count)
{
addr_range tempRange;
bool done;
int i;
do {
done = true;
for (i = 1; i < count; i++) {
if (range[i].start < range[i - 1].start) {
done = false;
memcpy(&tempRange, &range[i], sizeof(addr_range));
memcpy(&range[i], &range[i - 1], sizeof(addr_range));
memcpy(&range[i - 1], &tempRange, sizeof(addr_range));
}
}
} while (!done);
}
#ifdef TRACE_MEMORY_MAP
static const char *
e820_memory_type(uint32 type)
{
switch (type) {
case 1: return "memory";
case 2: return "reserved";
case 3: return "ACPI reclaim";
case 4: return "ACPI NVS";
default: return "unknown/reserved";
}
}
#endif
static uint32
get_memory_map(extended_memory **_extendedMemory)
{
/* extended_memory *block = (extended_memory *)kExtraSegmentScratch;
bios_regs regs = {0, 0, sizeof(extended_memory), 0, 0, (uint32)block, 0, 0};
uint32 count = 0;
TRACE(("get_memory_map()\n"));
do {
regs.eax = 0xe820;
regs.edx = 'SMAP';
call_bios(0x15, &regs);
if (regs.flags & CARRY_FLAG)
return 0;
regs.edi += sizeof(extended_memory);
count++;
} while (regs.ebx != 0);
*_extendedMemory = block;
#ifdef TRACE_MEMORY_MAP
dprintf("extended memory info (from 0xe820):\n");
for (uint32 i = 0; i < count; i++) {
dprintf(" base 0x%08Lx, len 0x%08Lx, type %lu (%s)\n",
block[i].base_addr, block[i].length,
block[i].type, e820_memory_type(block[i].type));
}
#endif
return count;*/return 0;
}
static void
init_page_directory(void)
{
TRACE(("init_page_directory\n"));
/*
// allocate a new pgdir
sPageDirectory = (uint32 *)get_next_physical_page();
gKernelArgs.arch_args.phys_pgdir = (uint32)sPageDirectory;
// clear out the pgdir
for (int32 i = 0; i < 1024; i++) {
sPageDirectory[i] = 0;
}
// Identity map the first 8 MB of memory so that their
// physical and virtual address are the same.
// These page tables won't be taken over into the kernel.
// make the first page table at the first free spot
uint32 *pageTable = get_next_page_table();
for (int32 i = 0; i < 1024; i++) {
pageTable[i] = (i * 0x1000) | kDefaultPageFlags;
}
sPageDirectory[0] = (uint32)pageTable | kDefaultPageFlags;
// make the second page table
pageTable = get_next_page_table();
for (int32 i = 0; i < 1024; i++) {
pageTable[i] = (i * 0x1000 + 0x400000) | kDefaultPageFlags;
}
sPageDirectory[1] = (uint32)pageTable | kDefaultPageFlags;
gKernelArgs.arch_args.num_pgtables = 0;
add_page_table(KERNEL_BASE);
// switch to the new pgdir and enable paging
asm("movl %0, %%eax;"
"movl %%eax, %%cr3;" : : "m" (sPageDirectory) : "eax");
// Important. Make sure supervisor threads can fault on read only pages...
asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1));*/
}
// #pragma mark -
extern "C" addr_t
mmu_map_physical_memory(addr_t physicalAddress, size_t size, uint32 flags)
{
addr_t address = sNextVirtualAddress;
addr_t pageOffset = physicalAddress & (B_PAGE_SIZE - 1);
physicalAddress -= pageOffset;
for (addr_t offset = 0; offset < size; offset += B_PAGE_SIZE) {
map_page(get_next_virtual_page(), physicalAddress + offset, flags);
}
return address + pageOffset;
}
extern "C" void *
mmu_allocate(void *virtualAddress, size_t size)
{
TRACE(("mmu_allocate: requested vaddr: %p, next free vaddr: 0x%lx, size: "
"%ld\n", virtualAddress, sNextVirtualAddress, size));
size = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE;
// get number of pages to map
if (virtualAddress != NULL) {
// This special path is almost only useful for loading the
// kernel into memory; it will only allow you to map the
// 'kMaxKernelSize' bytes following the kernel base address.
// Also, it won't check for already mapped addresses, so
// you better know why you are here :)
addr_t address = (addr_t)virtualAddress;
// is the address within the valid range?
if (address < KERNEL_BASE
|| address + size >= KERNEL_BASE + kMaxKernelSize)
return NULL;
for (uint32 i = 0; i < size; i++) {
map_page(address, get_next_physical_page(), kDefaultPageFlags);
address += B_PAGE_SIZE;
}
return virtualAddress;
}
void *address = (void *)sNextVirtualAddress;
for (uint32 i = 0; i < size; i++) {
map_page(get_next_virtual_page(), get_next_physical_page(),
kDefaultPageFlags);
}
return address;
}
/*! This will unmap the allocated chunk of memory from the virtual
address space. It might not actually free memory (as its implementation
is very simple), but it might.
*/
extern "C" void
mmu_free(void *virtualAddress, size_t size)
{
TRACE(("mmu_free(virtualAddress = %p, size: %ld)\n", virtualAddress, size));
addr_t address = (addr_t)virtualAddress;
size = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE;
// get number of pages to map
// is the address within the valid range?
if (address < KERNEL_BASE
|| address + size >= KERNEL_BASE + kMaxKernelSize) {
panic("mmu_free: asked to unmap out of range region (%p, size %lx)\n",
(void *)address, size);
}
// unmap all pages within the range
for (uint32 i = 0; i < size; i++) {
unmap_page(address);
address += B_PAGE_SIZE;
}
if (address == sNextVirtualAddress) {
// we can actually reuse the virtual address space
sNextVirtualAddress -= size;
}
}
/*! Sets up the final and kernel accessible GDT and IDT tables.
BIOS calls won't work any longer after this function has
been called.
*/
extern "C" void
mmu_init_for_kernel(void)
{
/* TRACE(("mmu_init_for_kernel\n"));
// set up a new idt
{
struct gdt_idt_descr idtDescriptor;
uint32 *idt;
// find a new idt
idt = (uint32 *)get_next_physical_page();
gKernelArgs.arch_args.phys_idt = (uint32)idt;
TRACE(("idt at %p\n", idt));
// map the idt into virtual space
gKernelArgs.arch_args.vir_idt = (uint32)get_next_virtual_page();
map_page(gKernelArgs.arch_args.vir_idt, (uint32)idt, kDefaultPageFlags);
// clear it out
uint32* virtualIDT = (uint32*)gKernelArgs.arch_args.vir_idt;
for (int32 i = 0; i < IDT_LIMIT / 4; i++) {
virtualIDT[i] = 0;
}
// load the idt
idtDescriptor.limit = IDT_LIMIT - 1;
idtDescriptor.base = (uint32 *)gKernelArgs.arch_args.vir_idt;
asm("lidt %0;"
: : "m" (idtDescriptor));
TRACE(("idt at virtual address 0x%lx\n", gKernelArgs.arch_args.vir_idt));
}
// set up a new gdt
{
struct gdt_idt_descr gdtDescriptor;
segment_descriptor *gdt;
// find a new gdt
gdt = (segment_descriptor *)get_next_physical_page();
gKernelArgs.arch_args.phys_gdt = (uint32)gdt;
TRACE(("gdt at %p\n", gdt));
// map the gdt into virtual space
gKernelArgs.arch_args.vir_gdt = (uint32)get_next_virtual_page();
map_page(gKernelArgs.arch_args.vir_gdt, (uint32)gdt, kDefaultPageFlags);
// put standard segment descriptors in it
segment_descriptor* virtualGDT
= (segment_descriptor*)gKernelArgs.arch_args.vir_gdt;
clear_segment_descriptor(&virtualGDT[0]);
// seg 0x08 - kernel 4GB code
set_segment_descriptor(&virtualGDT[1], 0, 0xffffffff, DT_CODE_READABLE,
DPL_KERNEL);
// seg 0x10 - kernel 4GB data
set_segment_descriptor(&virtualGDT[2], 0, 0xffffffff, DT_DATA_WRITEABLE,
DPL_KERNEL);
// seg 0x1b - ring 3 user 4GB code
set_segment_descriptor(&virtualGDT[3], 0, 0xffffffff, DT_CODE_READABLE,
DPL_USER);
// seg 0x23 - ring 3 user 4GB data
set_segment_descriptor(&virtualGDT[4], 0, 0xffffffff, DT_DATA_WRITEABLE,
DPL_USER);
// virtualGDT[5] and above will be filled later by the kernel
// to contain the TSS descriptors, and for TLS (one for every CPU)
// load the GDT
gdtDescriptor.limit = GDT_LIMIT - 1;
gdtDescriptor.base = (uint32 *)gKernelArgs.arch_args.vir_gdt;
asm("lgdt %0;"
: : "m" (gdtDescriptor));
TRACE(("gdt at virtual address %p\n", (void *)gKernelArgs.arch_args.vir_gdt));
}
// save the memory we've physically allocated
gKernelArgs.physical_allocated_range[0].size
= sNextPhysicalAddress - gKernelArgs.physical_allocated_range[0].start;
// Save the memory we've virtually allocated (for the kernel and other
// stuff)
gKernelArgs.virtual_allocated_range[0].start = KERNEL_BASE;
gKernelArgs.virtual_allocated_range[0].size
= sNextVirtualAddress - KERNEL_BASE;
gKernelArgs.num_virtual_allocated_ranges = 1;
// sort the address ranges
sort_addr_range(gKernelArgs.physical_memory_range,
gKernelArgs.num_physical_memory_ranges);
sort_addr_range(gKernelArgs.physical_allocated_range,
gKernelArgs.num_physical_allocated_ranges);
sort_addr_range(gKernelArgs.virtual_allocated_range,
gKernelArgs.num_virtual_allocated_ranges);
#ifdef TRACE_MEMORY_MAP
{
uint32 i;
dprintf("phys memory ranges:\n");
for (i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) {
dprintf(" base 0x%08lx, length 0x%08lx\n", gKernelArgs.physical_memory_range[i].start, gKernelArgs.physical_memory_range[i].size);
}
dprintf("allocated phys memory ranges:\n");
for (i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) {
dprintf(" base 0x%08lx, length 0x%08lx\n", gKernelArgs.physical_allocated_range[i].start, gKernelArgs.physical_allocated_range[i].size);
}
dprintf("allocated virt memory ranges:\n");
for (i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) {
dprintf(" base 0x%08lx, length 0x%08lx\n", gKernelArgs.virtual_allocated_range[i].start, gKernelArgs.virtual_allocated_range[i].size);
}
}
#endif*/
}
extern "C" void
mmu_init(void)
{
/* TRACE(("mmu_init\n"));
gKernelArgs.physical_allocated_range[0].start = sNextPhysicalAddress;
gKernelArgs.physical_allocated_range[0].size = 0;
gKernelArgs.num_physical_allocated_ranges = 1;
// remember the start of the allocated physical pages
init_page_directory();
// Map the page directory into kernel space at 0xffc00000-0xffffffff
// this enables a mmu trick where the 4 MB region that this pgdir entry
// represents now maps the 4MB of potential pagetables that the pgdir
// points to. Thrown away later in VM bringup, but useful for now.
sPageDirectory[1023] = (uint32)sPageDirectory | kDefaultPageFlags;
// also map it on the next vpage
gKernelArgs.arch_args.vir_pgdir = get_next_virtual_page();
map_page(gKernelArgs.arch_args.vir_pgdir, (uint32)sPageDirectory,
kDefaultPageFlags);
// map in a kernel stack
gKernelArgs.cpu_kstack[0].start = (addr_t)mmu_allocate(NULL,
KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE);
gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE
+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
TRACE(("kernel stack at 0x%lx to 0x%lx\n", gKernelArgs.cpu_kstack[0].start,
gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size));
extended_memory *extMemoryBlock;
uint32 extMemoryCount = get_memory_map(&extMemoryBlock);
// figure out the memory map
if (extMemoryCount > 0) {
gKernelArgs.num_physical_memory_ranges = 0;
for (uint32 i = 0; i < extMemoryCount; i++) {
// Type 1 is available memory
if (extMemoryBlock[i].type == 1) {
// round everything up to page boundaries, exclusive of pages
// it partially occupies
if ((extMemoryBlock[i].base_addr % B_PAGE_SIZE) != 0) {
extMemoryBlock[i].length -= B_PAGE_SIZE
- extMemoryBlock[i].base_addr % B_PAGE_SIZE;
}
extMemoryBlock[i].base_addr
= ROUNDUP(extMemoryBlock[i].base_addr, B_PAGE_SIZE);
extMemoryBlock[i].length
= ROUNDOWN(extMemoryBlock[i].length, B_PAGE_SIZE);
// we ignore all memory beyond 4 GB
if (extMemoryBlock[i].base_addr > 0xffffffffULL)
continue;
if (extMemoryBlock[i].base_addr + extMemoryBlock[i].length
> 0xffffffffULL) {
extMemoryBlock[i].length
= 0x100000000ULL - extMemoryBlock[i].base_addr;
}
if (gKernelArgs.num_physical_memory_ranges > 0) {
// we might want to extend a previous hole
addr_t previousEnd = gKernelArgs.physical_memory_range[
gKernelArgs.num_physical_memory_ranges - 1].start
+ gKernelArgs.physical_memory_range[
gKernelArgs.num_physical_memory_ranges - 1].size;
addr_t holeSize = extMemoryBlock[i].base_addr - previousEnd;
// If the hole is smaller than 1 MB, we try to mark the
// memory as allocated and extend the previous memory range
if (previousEnd <= extMemoryBlock[i].base_addr
&& holeSize < 0x100000
&& insert_physical_allocated_range(previousEnd,
extMemoryBlock[i].base_addr - previousEnd)
== B_OK) {
gKernelArgs.physical_memory_range[
gKernelArgs.num_physical_memory_ranges - 1].size
+= holeSize;
}
}
insert_physical_memory_range(extMemoryBlock[i].base_addr,
extMemoryBlock[i].length);
}
}
} else {
// TODO: for now!
dprintf("No extended memory block - using 32 MB (fix me!)\n");
uint32 memSize = 32 * 1024 * 1024;
// We dont have an extended map, assume memory is contiguously mapped
// at 0x0
gKernelArgs.physical_memory_range[0].start = 0;
gKernelArgs.physical_memory_range[0].size = memSize;
gKernelArgs.num_physical_memory_ranges = 1;
// mark the bios area allocated
uint32 biosRange = gKernelArgs.num_physical_allocated_ranges++;
gKernelArgs.physical_allocated_range[biosRange].start = 0x9f000;
// 640k - 1 page
gKernelArgs.physical_allocated_range[biosRange].size = 0x61000;
}
gKernelArgs.arch_args.page_hole = 0xffc00000;
*/
}
// #pragma mark -
extern "C" status_t
platform_allocate_region(void **_address, size_t size, uint8 protection,
bool /*exactAddress*/)
{
void *address = mmu_allocate(*_address, size);
if (address == NULL)
return B_NO_MEMORY;
*_address = address;
return B_OK;
}
extern "C" status_t
platform_free_region(void *address, size_t size)
{
mmu_free(address, size);
return B_OK;
}
void
platform_release_heap(struct stage2_args *args, void *base)
{
// It will be freed automatically, since it is in the
// identity mapped region, and not stored in the kernel's
// page tables.
}
status_t
platform_init_heap(struct stage2_args *args, void **_base, void **_top)
{
void *heap = (void *)get_next_physical_address(args->heap_size);
if (heap == NULL)
return B_NO_MEMORY;
*_base = heap;
*_top = (void *)((int8 *)heap + args->heap_size);
return B_OK;
}

View File

@ -0,0 +1,29 @@
/*
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef MMU_H
#define MMU_H
#include <SupportDefs.h>
// For use with mmu_map_physical_memory()
static const uint32 kDefaultPageFlags = 0x3; // present, R/W
#ifdef __cplusplus
extern "C" {
#endif
extern void mmu_init(void);
extern void mmu_init_for_kernel(void);
extern addr_t mmu_map_physical_memory(addr_t physicalAddress, size_t size, uint32 flags);
extern void *mmu_allocate(void *virtualAddress, size_t size);
extern void mmu_free(void *virtualAddress, size_t size);
#ifdef __cplusplus
}
#endif
#endif /* MMU_H */

View File

@ -0,0 +1,102 @@
/*
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#include "serial.h"
#include "uart.h"
#include <boot/platform.h>
#include <arch/cpu.h>
#include <boot/stage2.h>
#include <string.h>
// serial output should always be enabled on u-boot platforms..
#define ENABLE_SERIAL
static int32 sSerialEnabled = 0;
static char sBuffer[16384];
static uint32 sBufferPosition;
static void
serial_putc(char c)
{
uart_putc(0,c);
}
extern "C" void
serial_puts(const char* string, size_t size)
{
if (sSerialEnabled <= 0)
return;
if (sBufferPosition + size < sizeof(sBuffer)) {
memcpy(sBuffer + sBufferPosition, string, size);
sBufferPosition += size;
}
while (size-- != 0) {
char c = string[0];
if (c == '\n') {
serial_putc('\r');
serial_putc('\n');
} else if (c != '\r')
serial_putc(c);
string++;
}
}
extern "C" void
serial_disable(void)
{
#ifdef ENABLE_SERIAL
sSerialEnabled = 0;
#else
sSerialEnabled--;
#endif
}
extern "C" void
serial_enable(void)
{
uart_init_early();
uart_init();//todo
uart_init_port(0,9600);
//uart_init_port(1,9600);
//uart_init_port(2,9600);
sSerialEnabled++;
}
extern "C" void
serial_cleanup(void)
{
if (sSerialEnabled <= 0)
return;
gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition);
if (gKernelArgs.debug_output != NULL) {
memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition);
gKernelArgs.debug_size = sBufferPosition;
}
}
extern "C" void
serial_init(void)
{
#ifdef ENABLE_SERIAL
serial_enable();
#endif
}

View File

@ -0,0 +1,28 @@
/*
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef SERIAL_H
#define SERIAL_H
#include <SupportDefs.h>
#ifdef __cplusplus
extern "C" {
#endif
extern void serial_init(void);
extern void serial_cleanup(void);
extern void serial_puts(const char *string, size_t size);
extern void serial_disable(void);
extern void serial_enable(void);
#ifdef __cplusplus
}
#endif
#endif /* SERIAL_H */

View File

@ -0,0 +1,13 @@
#include <arch/arm/arch_cpu.h>
#include <asm_defs.h>
/*
* Entry point to the loader that U-Boot passes control to.
*/
.text
.globl _start
_start:
/* I'm to stupid to get _start in a c file to work ..... */
b start2

View File

@ -0,0 +1,128 @@
/*
* Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#include "serial.h"
#include "console.h"
#include "cpu.h"
#include "smp.h"
#include "keyboard.h"
#include <KernelExport.h>
#include <boot/platform.h>
#include <boot/heap.h>
#include <boot/stage2.h>
#include <arch/cpu.h>
#include <string.h>
#define HEAP_SIZE (128 * 1024)
// GCC defined globals
extern void (*__ctor_list)(void);
extern void (*__ctor_end)(void);
extern uint8 __bss_start;
extern uint8 _end;
extern int main(stage2_args *args);
void _start(void);
uint32 sBootOptions;
static void
clear_bss(void)
{
memset(&__bss_start, 0, &_end - &__bss_start);
}
static void
call_ctors(void)
{
void (**f)(void);
for (f = &__ctor_list; f < &__ctor_end; f++) {
(**f)();
}
}
void
platform_start_kernel(void)
{
static struct kernel_args *args = &gKernelArgs;
// something goes wrong when we pass &gKernelArgs directly
// to the assembler inline below - might be a bug in GCC
// or I don't see something important...
addr_t stackTop
= gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size;
// smp_init_other_cpus();
serial_cleanup();
// mmu_init_for_kernel();
// smp_boot_other_cpus();
dprintf("kernel entry at %lx\n",
gKernelArgs.kernel_image.elf_header.e_entry);
/* asm("movl %0, %%eax; " // move stack out of way
"movl %%eax, %%esp; "
: : "m" (stackTop));
asm("pushl $0x0; " // we're the BSP cpu (0)
"pushl %0; " // kernel args
"pushl $0x0;" // dummy retval for call to main
"pushl %1; " // this is the start address
"ret; " // jump.
: : "g" (args), "g" (gKernelArgs.kernel_image.elf_header.e_entry));
*/
panic("kernel returned!\n");
}
void
platform_exit(void)
{
}
void
start2(void)
{
stage2_args args;
clear_bss();
// call C++ constructors before doing anything else
call_ctors();
args.heap_size = HEAP_SIZE;
serial_init();
console_init();
cpu_init();
// mmu_init();
// wait a bit to give the user the opportunity to press a key
// spin(750000);
// reading the keyboard doesn't seem to work in graphics mode
// (maybe a bochs problem)
// sBootOptions = check_for_boot_keys();
//if (sBootOptions & BOOT_OPTION_DEBUG_OUTPUT)
serial_enable();
main(&args);
}
uint32
platform_boot_options(void)
{
return sBootOptions;
}

View File

@ -0,0 +1,170 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <arch/arm/reg.h>
#include <arch/arm/uart.h>
#include <arch/arm/pxa270.h>
//#include <target/debugconfig.h>
//TODO: beaglespecific ?...
#define DEBUG_UART 2
struct uart_stat {
addr_t base;
uint shift;
};
static struct uart_stat uart[3] = {
{ FFUART_BASE, 2 },
{ BTUART_BASE, 2 },
{ STUART_BASE, 2 },
};
static inline void write_uart_reg(int port, uint reg, unsigned char data)
{
*(volatile unsigned char *)(uart[port].base + (reg << uart[port].shift)) = data;
}
static inline unsigned char read_uart_reg(int port, uint reg)
{
return *(volatile unsigned char *)(uart[port].base + (reg << uart[port].shift));
}
#define LCR_8N1 0x03
#define FCR_FIFO_EN 0x01 /* Fifo enable */
#define FCR_RXSR 0x02 /* Receiver soft reset */
#define FCR_TXSR 0x04 /* Transmitter soft reset */
#define MCR_DTR 0x01
#define MCR_RTS 0x02
#define MCR_DMA_EN 0x04
#define MCR_TX_DFR 0x08
#define LCR_WLS_MSK 0x03 /* character length select mask */
#define LCR_WLS_5 0x00 /* 5 bit character length */
#define LCR_WLS_6 0x01 /* 6 bit character length */
#define LCR_WLS_7 0x02 /* 7 bit character length */
#define LCR_WLS_8 0x03 /* 8 bit character length */
#define LCR_STB 0x04 /* Number of stop Bits, off = 1, on = 1.5 or 2) */
#define LCR_PEN 0x08 /* Parity eneble */
#define LCR_EPS 0x10 /* Even Parity Select */
#define LCR_STKP 0x20 /* Stick Parity */
#define LCR_SBRK 0x40 /* Set Break */
#define LCR_BKSE 0x80 /* Bank select enable */
#define LSR_DR 0x01 /* Data ready */
#define LSR_OE 0x02 /* Overrun */
#define LSR_PE 0x04 /* Parity error */
#define LSR_FE 0x08 /* Framing error */
#define LSR_BI 0x10 /* Break */
#define LSR_THRE 0x20 /* Xmit holding register empty */
#define LSR_TEMT 0x40 /* Xmitter empty */
#define LSR_ERR 0x80 /* Error */
#define LCRVAL LCR_8N1 /* 8 data, 1 stop, no parity */
#define MCRVAL (MCR_DTR | MCR_RTS) /* RTS/DTR */
#define FCRVAL (FCR_FIFO_EN | FCR_RXSR | FCR_TXSR) /* Clear & enable FIFOs */
#define V_NS16550_CLK (48000000) /* 48MHz (APLL96/2) */
void uart_init_port(int port, uint baud)
{
/* clear the tx & rx fifo and disable */
uint16 baud_divisor = (V_NS16550_CLK / 16 / baud);
write_uart_reg(port, UART_IER, 0);
write_uart_reg(port, UART_LCR, LCR_BKSE | LCRVAL); // config mode A
write_uart_reg(port, UART_DLL, baud_divisor & 0xff);
write_uart_reg(port, UART_DLH, (baud_divisor >> 8) & 0xff);
write_uart_reg(port, UART_LCR, LCRVAL); // operational mode
write_uart_reg(port, UART_MCR, MCRVAL);
write_uart_reg(port, UART_FCR, FCRVAL);
write_uart_reg(port, UART_MDR1, 0); // UART 16x mode
// write_uart_reg(port, UART_LCR, 0xBF); // config mode B
// write_uart_reg(port, UART_EFR, (1<<7)|(1<<6)); // hw flow control
// write_uart_reg(port, UART_LCR, LCRVAL); // operational mode
}
void uart_init_early(void)
{
#warning INTITIALIZE UART!!!!!
/* UART1 */
// RMWREG32(CKEN1, 13, 1, 1),
// RMWREG32(CM_ICLKEN1_CORE, 13, 1, 1),
/* UART2 */
// RMWREG32(CM_FCLKEN1_CORE, 14, 1, 1),
// RMWREG32(CM_ICLKEN1_CORE, 14, 1, 1),
/* UART3 */
// RMWREG32(CM_FCLKEN_PER, 11, 1, 1),
// RMWREG32(CM_ICLKEN_PER, 11, 1, 1),
uart_init_port(DEBUG_UART, 115200);
}
void uart_init(void)
{
}
int uart_putc(int port, char c )
{
// while (!(read_uart_reg(port, UART_LSR) & (1<<6))) // wait for the last char to get out
// ;
write_uart_reg(port, UART_THR, c);
return 0;
}
int uart_getc(int port, bool wait) /* returns -1 if no data available */
{
// if (wait) {
// while (!(read_uart_reg(port, UART_LSR) & (1<<0))) // wait for data to show up in the rx fifo
// ;
// } else {
// if (!(read_uart_reg(port, UART_LSR) & (1<<0)))
// return -1;
// }
return read_uart_reg(port, UART_RHR);
}
void uart_flush_tx(int port)
{
while (!(read_uart_reg(port, UART_LSR) & (1<<6))) // wait for the last char to get out
;
}
void uart_flush_rx(int port)
{
// empty the rx fifo
while (read_uart_reg(port, UART_LSR) & (1<<0)) {
volatile char c = read_uart_reg(port, UART_RHR);
(void)c;
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __DEV_UART_H
#define __DEV_UART_H
//#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
void uart_init(void);
void uart_init_early(void);
int uart_putc(int port, char c);
int uart_getc(int port, bool wait);
void uart_flush_tx(int port);
void uart_flush_rx(int port);
void uart_init_port(int port, uint baud);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,90 @@
/*
* Copyright 2009, Johannes Wischert
* Distributed under the terms of the MIT License.
*/
#include "video.h"
#include <arch/cpu.h>
#include <boot/stage2.h>
#include <boot/platform.h>
#include <boot/menu.h>
#include <boot/kernel_args.h>
#include <boot/images.h>
#include <util/list.h>
#include <drivers/driver_settings.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRACE_VIDEO
#ifdef TRACE_VIDEO
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
// #pragma mark -
bool
video_mode_hook(Menu *menu, MenuItem *item)
{
return true;
}
Menu *
video_mode_menu()
{
Menu *menu = new(nothrow) Menu(CHOICE_MENU, "Select Video Mode");
MenuItem *item;
menu->AddItem(item = new(nothrow) MenuItem("Default"));
item->SetMarked(true);
item->Select(true);
item->SetHelpText("The Default video mode is the one currently configured "
"in the system. If there is no mode configured yet, a viable mode will "
"be chosen automatically.");
menu->AddSeparatorItem();
menu->AddItem(item = new(nothrow) MenuItem("Return to main menu"));
item->SetType(MENU_ITEM_NO_CHOICE);
return menu;
}
// #pragma mark -
extern "C" void
platform_switch_to_logo(void)
{
// in debug mode, we'll never show the logo
if ((platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) != 0)
return;
#warning ARM:TODO
}
extern "C" void
platform_switch_to_text_mode(void)
{
#warning ARM:TODO
}
extern "C" status_t
platform_init_video(void)
{
#warning ARM:TODO
return B_OK;
}

View File

@ -0,0 +1,18 @@
/*
** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
** Distributed under the terms of the Haiku License.
*/
#ifndef VIDEO_H
#define VIDEO_H
#include <SupportDefs.h>
class Menu;
class MenuItem;
bool video_mode_hook(Menu *menu, MenuItem *item);
Menu *video_mode_menu();
#endif /* VIDEO_H */