m68k: add next_m68k boot platform

Since the boot ROM API structure is declared with a custom alignment, we
simulate it with padding bytes around, and use aligntest.prg to verify
using ARAnyM + TOS/MiNT as we know how to link simple PRG files.

It now prints something to the screen then panics when initializing the
heap.

For now one must insert the loader manually into an existing floppy
image:
dd if=generated-m68k/objects/haiku/m68k/release/system/boot/next_m68k/haiku_loader.next_m68k bs=$((0x8000)) seek=1 of=next_floppy.img conv=notrunc

Change-Id: I06d74e9d85a352aab68dedce545bbe5fe9e990d5
Reviewed-on: https://review.haiku-os.org/c/haiku/+/2220
Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
François Revol
2020-08-19 13:35:19 +00:00
committed by Alex von Gluck IV
parent 53b97f0d18
commit ec5a799719
22 changed files with 1671 additions and 2 deletions
+5 -1
View File
@@ -314,7 +314,7 @@ rule KernelArchitectureSetup architecture
case m68k : case m68k :
HAIKU_KERNEL_PLATFORM ?= atari_m68k ; HAIKU_KERNEL_PLATFORM ?= atari_m68k ;
HAIKU_BOOT_TARGETS += amiga_m68k atari_m68k ; HAIKU_BOOT_TARGETS += amiga_m68k atari_m68k next_m68k ;
switch $(HAIKU_KERNEL_PLATFORM) { switch $(HAIKU_KERNEL_PLATFORM) {
case atari_m68k : case atari_m68k :
{ {
@@ -325,6 +325,10 @@ rule KernelArchitectureSetup architecture
# for now we have trouble reading from double-sided images # for now we have trouble reading from double-sided images
HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 880 ; # in kB HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 880 ; # in kB
} }
case next_m68k :
{
HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 1440 ; # in kB
}
} }
# offset in floppy image (>= sizeof(haiku_loader)) # offset in floppy image (>= sizeof(haiku_loader))
HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 260 ; # in kB HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 260 ; # in kB
+7
View File
@@ -28,6 +28,10 @@ rule BuildOpenFirmwareLoader {
rule BuildAoutLoader { rule BuildAoutLoader {
local haikuLoader = $(1) ; local haikuLoader = $(1) ;
local bootLoader = $(2) ; local bootLoader = $(2) ;
Depends $(haikuLoader) : $(bootLoader) ;
MakeLocateDebug $(haikuLoader) ;
ELF2AOUT on $(haikuLoader) = <build>elf2aout ; ELF2AOUT on $(haikuLoader) = <build>elf2aout ;
Depends $(haikuLoader) : <build>elf2aout ; Depends $(haikuLoader) : <build>elf2aout ;
} }
@@ -375,6 +379,9 @@ for platform in [ MultiBootSubDirSetup ] {
: -Bstatic : -Bstatic
; ;
case next_m68k :
BuildAoutLoader haiku_loader.$(TARGET_BOOT_PLATFORM) : boot_loader_$(TARGET_BOOT_PLATFORM) ;
case * : case * :
Exit "Currently unsupported haiku_loader:" $(TARGET_BOOT_PLATFORM) ; Exit "Currently unsupported haiku_loader:" $(TARGET_BOOT_PLATFORM) ;
} }
+1 -1
View File
@@ -1,7 +1,7 @@
SubDir HAIKU_TOP src system boot arch m68k ; SubDir HAIKU_TOP src system boot arch m68k ;
local platform ; local platform ;
for platform in [ MultiBootSubDirSetup amiga_m68k atari_m68k ] { for platform in [ MultiBootSubDirSetup amiga_m68k atari_m68k next_m68k ] {
on $(platform) { on $(platform) {
DEFINES += _BOOT_MODE ; DEFINES += _BOOT_MODE ;
@@ -0,0 +1,95 @@
SubDir HAIKU_TOP src system boot platform next_m68k ;
SubDirHdrs $(HAIKU_TOP) headers private kernel boot platform next_m68k ;
UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ;
UsePrivateHeaders [ FDirName kernel 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) ; # -save-temps
SubDirC++Flags $(defines) -fno-rtti ;
}
local platform ;
for platform in [ MultiBootSubDirSetup next_m68k ] {
on $(platform) {
#SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ;
BootMergeObject boot_platform_next_m68k_shell.o :
shell.S
: -Wa,--pcrel
;
# cpu-specific stuff
# should be moved to boot/arch/m68k/...
# TODO: add 020+68851 support
BootMergeObject boot_platform_next_m68k_other.o :
# shell.S
start.cpp
debug.cpp
#bios.S
console.cpp
#serial.cpp
# Handle.cpp
devices.cpp
keyboard.cpp
menu.cpp
mmu.cpp
cpu.cpp
#smp.cpp
#smp_trampoline.S
# support.S
video.cpp
#apm.cpp
# VESA/DDC EDID
#decode_edid.c
#dump_edid.c
: #-Wa,--pcrel
: boot_platform_generic_next_m68k.a
;
BootMergeObject boot_platform_next_m68k.o :
: :
boot_platform_next_m68k_shell.o
boot_platform_next_m68k_other.o
# boot_arch_m68k_030.o
# boot_arch_m68k_040.o
;
BootMergeObject aligntest_prg.o :
aligntest.c
: -Wa,--pcrel
;
# used to check alignment of struct mon_global
# The simplest way to do it was to build a program on a platform we know how to link and run
# and we can already build Atari programs as long as they don't need relocations.
AtariBootPrgLd aligntest.prg :
aligntest_prg.o
: $(HAIKU_TOP)/src/system/ldscripts/$(TARGET_ARCH)/boot_prg_atari_m68k.ld
: -Bstatic
;
}
}
SEARCH on [ FGristFiles $(genericPlatformSources) ]
= [ 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) ;
# cf pxe_ia32 Jamfile for stage1
@@ -0,0 +1,16 @@
#include <stddef.h>
#include <unistd.h>
#include "nextrom.h"
#include "../atari_m68k/toscalls.h"
/* we compile this code as an atari TOS PRG to verify offsets in mon_global */
int main()
{
int o = offsetof(struct mon_global, mg_board_rev);
/* let's return the value to the shell. Only on 8bit, so it's %256 */
/* return doesn't work without using the crt files so we must Pterm() */
Pterm(o);
return o;
}
@@ -0,0 +1,276 @@
/*
* Copyright 2007-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT license.
*
* Author:
* François Revol, [email protected].
*/
#include <SupportDefs.h>
#include <string.h>
#include "nextrom.h"
#include <util/kernel_cpp.h>
#include "console.h"
#include "keyboard.h"
static bool sForceBW = false; // force black & white for Milan
// bootrom has more console info but we don't know the structure
// so we just use getc & putc for now.
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);
void PutChar(char c);
void PutChars(const char *buffer, int count);
char GetChar();
};
static Console sInput;
static Console sOutput;
FILE *stdin, *stdout, *stderr;
Console::Console()
: ConsoleNode()
{
}
ssize_t
Console::ReadAt(void */*cookie*/, off_t /*pos*/, void *_buffer,
size_t bufferSize)
{
char *buffer = (char*)_buffer;
int c;
ssize_t bytesTotal = 0;
while (bytesTotal < bufferSize && (c = mg->mg_try_getc())) {
*buffer++ = (char)c;
bytesTotal++;
}
return bytesTotal;
}
ssize_t
Console::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
size_t bufferSize)
{
const char *string = (const char *)buffer;
size_t i;
for (i = 0; i < bufferSize; i++) {
if (string[i] == '\0')
break;
mg->mg_putc(string[i]);
}
return bufferSize;
}
void
Console::PutChar(char c)
{
mg->mg_putc(c);
}
void
Console::PutChars(const char *buffer, int count)
{
for (int i = 0; i < count; i++)
mg->mg_putc(buffer[i]);
}
char
Console::GetChar()
{
return (char)(mg->mg_getc());
}
// #pragma mark -
static void
dump_colors()
{
int bg, fg;
dprintf("colors:\n");
for (bg = 0; bg < 16; bg++) {
for (fg = 0; fg < 16; fg++) {
console_set_color(fg, bg);
dprintf("#");
}
console_set_color(0, 15);
dprintf("\n");
}
}
status_t
console_init(void)
{
// now that we're initialized, enable stdio functionality
stdin = (FILE *)&sInput;
stdout = stderr = (FILE *)&sOutput;
//dump_colors();
return B_OK;
}
// #pragma mark -
void
console_clear_screen(void)
{
sInput.WriteAt(NULL, 0LL, "\033E", 2);
}
int32
console_width(void)
{
int columnCount = 80; //XXX: check video mode
return columnCount;
}
int32
console_height(void)
{
int lineCount = 25; //XXX: check video mode
return lineCount;
}
void
console_set_cursor(int32 x, int32 y)
{
char buff[] = "\033Y ";
x = MIN(79,MAX(0,x));
y = MIN(24,MAX(0,y));
buff[3] += (char)x;
buff[2] += (char)y;
sInput.WriteAt(NULL, 0LL, buff, 4);
}
static int
translate_color(int32 color)
{
/*
r g b
0: 0 0 0 // black
1: 0 0 aa // dark blue
2: 0 aa 0 // dark green
3: 0 aa aa // cyan
4: aa 0 0 // dark red
5: aa 0 aa // purple
6: aa 55 0 // brown
7: aa aa aa // light gray
8: 55 55 55 // dark gray
9: 55 55 ff // light blue
a: 55 ff 55 // light green
b: 55 ff ff // light cyan
c: ff 55 55 // light red
d: ff 55 ff // magenta
e: ff ff 55 // yellow
f: ff ff ff // white
*/
// cf. http://www.fortunecity.com/skyscraper/apple/308/html/chap4.htm
static const char cmap[] = {
15, 4, 2, 6, 1, 5, 3, 7,
8, 12, 10, 14, 9, 13, 11, 0 };
if (color < 0 || color >= 16)
return 0;
return cmap[color];
//return color;
}
void
console_set_color(int32 foreground, int32 background)
{
char buff[] = "\033b \033c ";
if (sForceBW) {
if (background == 0)
foreground = 15;
else {
background = 15;
foreground = 0;
}
}
buff[2] += (char)translate_color(foreground);
buff[5] += (char)translate_color(background);
sInput.WriteAt(NULL, 0LL, buff, 6);
}
void
console_show_cursor(void)
{
}
void
console_hide_cursor(void)
{
}
int
console_wait_for_key(void)
{
#if 0
// XXX: do this way and remove keyboard.cpp ?
// wait for a key
char buffer[3];
ssize_t bytesRead;
do {
bytesRead = sInput.ReadAt(NULL, 0, buffer, 3);
if (bytesRead < 0)
return 0;
} while (bytesRead == 0);
#endif
union key key = wait_for_key();
if (key.code.ascii == 0) {
switch (key.code.bios) {
case BIOS_KEY_UP:
return TEXT_CONSOLE_KEY_UP;
case BIOS_KEY_DOWN:
return TEXT_CONSOLE_KEY_DOWN;
case BIOS_KEY_PAGE_UP:
return TEXT_CONSOLE_KEY_PAGE_UP;
case BIOS_KEY_PAGE_DOWN:
return TEXT_CONSOLE_KEY_PAGE_DOWN;
case BIOS_KEY_HOME:
return TEXT_CONSOLE_KEY_HOME;
case BIOS_KEY_END:
return TEXT_CONSOLE_KEY_END;
default:
return 0;
}
} else
return key.code.ascii;
}
@@ -0,0 +1,24 @@
/*
* Copyright 2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT license.
*
* Author:
* François Revol, [email protected].
*/
#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 */
@@ -0,0 +1,94 @@
/*
* Copyright 2004-2005, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "cpu.h"
#include "nextrom.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_platform.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
#warning M68K: add set_vbr()
static status_t
check_cpu_features()
{
int cpu = 0;
int fpu = 0;
//TODO: The ROM only tells which machine. NetBSD probes using CACR instead.
cpu = fpu = 68040;
if (!cpu || !fpu)
return B_ERROR;
gKernelArgs.arch_args.cpu_type = cpu;
gKernelArgs.arch_args.mmu_type = cpu;
gKernelArgs.arch_args.fpu_type = fpu;
// if ((flags & AFF_68060) != 0) true
gKernelArgs.arch_args.has_lpstop = false;
gKernelArgs.arch_args.platform = M68K_PLATFORM_NEXT;
gKernelArgs.arch_args.machine = 0; //XXX
return B_OK;
}
#warning M68K: move and implement system_time()
static bigtime_t gSystemTimeCounter = 0; //HACK
extern "C" bigtime_t
system_time(void)
{
return gSystemTimeCounter++;
}
// #pragma mark -
extern "C" void
spin(bigtime_t microseconds)
{
bigtime_t time = system_time();
while ((system_time() - time) < microseconds)
asm volatile ("nop;");
}
extern "C" void
cpu_init()
{
if (check_cpu_features() != B_OK)
panic("You need a 68030 or higher in order to boot!\n");
gKernelArgs.num_cpus = 1;
// this will eventually be corrected later on
// ...or not!
}
extern "C" void
platform_load_ucode(BootVolume& volume)
{
}
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright 2004-2005, Axel Dörfler, [email protected]. 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 */
@@ -0,0 +1,76 @@
/*
* Copyright 2008-2010, François Revol, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "keyboard.h"
#include "nextrom.h"
#include <boot/stage2.h>
#include <boot/platform.h>
#include <boot/stdio.h>
#include <stdarg.h>
#include <Errors.h>
void mon_put(const char *s)
{
while (s && *s)
mg->mg_putc(*s++);
}
void mon_puts(const char *s)
{
mon_put(s);
mg->mg_putc('\n');
}
/*! This works only after console_init() was called.
*/
void
panic(const char *format, ...)
{
const char greetings[] = "\n*** PANIC ***";
char buffer[512];
va_list list;
//platform_switch_to_text_mode();
mon_puts(greetings);
va_start(list, format);
vsnprintf(buffer, sizeof(buffer), format, list);
va_end(list);
mon_puts(buffer);
mon_puts("\nPress key to reboot.");
clear_key_buffer();
wait_for_key();
platform_exit();
}
void
dprintf(const char *format, ...)
{
char buffer[512];
va_list list;
va_start(list, format);
vsnprintf(buffer, sizeof(buffer), format, list);
va_end(list);
//if (platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT)
if (!gKernelArgs.frame_buffer.enabled)
mon_put(buffer);
}
char*
platform_debug_get_log_buffer(size_t* _size)
{
return NULL;
}
@@ -0,0 +1,64 @@
/*
* Copyright 2008-2010, François Revol, [email protected]. All rights reserved.
* Copyright 2003-2006, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <KernelExport.h>
#include <boot/platform.h>
#include <boot/partitions.h>
#include <boot/stdio.h>
#include <boot/stage2.h>
#include <string.h>
#include "nextrom.h"
//#define TRACE_DEVICES
#ifdef TRACE_DEVICES
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
static bool sBlockDevicesAdded = false;
// #pragma mark -
status_t
platform_add_boot_device(struct stage2_args *args, NodeList *devicesList)
{
return B_UNSUPPORTED;
}
status_t
platform_get_boot_partition(struct stage2_args *args, Node *bootDevice,
NodeList *list, boot::Partition **_partition)
{
return B_ENTRY_NOT_FOUND;
}
status_t
platform_add_block_devices(stage2_args *args, NodeList *devicesList)
{
return B_UNSUPPORTED;
}
status_t
platform_register_boot_device(Node *device)
{
return B_UNSUPPORTED;
}
void
platform_cleanup_devices()
{
}
@@ -0,0 +1,66 @@
/*
* Copyright 2008-2010, François Revol, [email protected]. All rights reserved.
* Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "keyboard.h"
#include "nextrom.h"
#include <boot/platform.h>
static uint32
check_for_key(void)
{
union key k;
k.d0 = mg->mg_try_getc();
return k.d0;
}
extern "C" void
clear_key_buffer(void)
{
while (check_for_key() != 0)
;
}
extern "C" union key
wait_for_key(void)
{
union key key;
key.d0 = mg->mg_getc();
return key;
}
extern "C" uint32
check_for_boot_keys(void)
{
union key key;
uint32 options = 0;
while ((key.d0 = check_for_key()) != 0) {
switch (key.code.ascii) {
case ' ':
options |= BOOT_OPTION_MENU;
break;
case 0x1b: // escape
options |= BOOT_OPTION_DEBUG_OUTPUT;
break;
case 0:
// evaluate BIOS scan codes
// ...
break;
}
}
dprintf("options = %ld\n", options);
return options;
}
@@ -0,0 +1,40 @@
#ifndef KEYBOARD_H
#define KEYBOARD_H
#include <SupportDefs.h>
union key {
uint32 d0;
struct {
uint8 modifiers; // not always present!
uint8 bios; // scan code
uint8 dummy;
uint8 ascii;
} code;
};
#define BIOS_KEY_UP 0x48
#define BIOS_KEY_DOWN 0x50
#define BIOS_KEY_LEFT 0x4b
#define BIOS_KEY_RIGHT 0x4d
// XXX: FIXME
#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 */
@@ -0,0 +1,52 @@
/*
* Copyright 2008-2010, François Revol, [email protected]. All rights reserved.
* Copyright 2004-2007, Axel Dörfler, [email protected]. 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:
break;
case SAFE_MODE_MENU:
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);
}
size_t
platform_get_user_input_text(Menu *menu, MenuItem *item, char *buffer,
size_t bufferSize)
{
return platform_generic_get_user_input_text(menu, item, buffer,
bufferSize);
}
+168
View File
@@ -0,0 +1,168 @@
/*
* Copyright 2008-2010, François Revol, [email protected]. All rights reserved.
* Copyright 2004-2007, Axel Dörfler, [email protected].
* Based on code written by Travis Geiselbrecht for NewOS.
*
* Distributed under the terms of the MIT License.
*/
#include "nextrom.h"
#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>
#warning TODO: M68K: NEXT: mmu
//XXX: x86
/** 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
* 0x81000000 which means that there is currently only 1 MB reserved for
* the kernel itself (see kMaxKernelSize).
*/
// notes m68k:
/** The (physical) memory layout of the boot loader is currently as follows:
* 0x0800 - 0x10000 supervisor mode stack (1) XXX: more ? x86 starts at 500
* 0x10000 - ? code (up to ~500 kB)
* 0x100000 or FAST_RAM_BASE if any:
* ... page root directory
* ... interrupt vectors (VBR)
* ... page directory
* ... boot loader heap (32 kB)
* ... free physical memory
* 0xdNNNNN video buffer usually there, as per v_bas_ad
* (=Logbase() but Physbase() is better)
*
* The first 32 MB (2) are identity mapped (0x0 - 0x1000000); paging
* is turned on. The kernel is mapped at 0x80000000, all other stuff
* mapped by the loader (kernel args, modules, driver settings, ...)
* comes after 0x81000000 which means that there is currently only
* 1 MB reserved for the kernel itself (see kMaxKernelSize).
*
* (1) no need for user stack, we are already in supervisor mode in the
* loader.
* (2) maps the whole regular ST space; transparent translation registers
* have larger granularity anyway.
*/
#warning M68K: check for Physbase() < ST_RAM_TOP
#define TRACE_MMU
#ifdef TRACE_MMU
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
// since the page root directory doesn't take a full page (1k)
// we stuff some other stuff after it, like the interrupt vectors (1k)
#define VBR_PAGE_OFFSET 1024
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
addr_t gPageRoot = 0;
static addr_t sNextPhysicalAddress = 0x100000;
static addr_t sNextVirtualAddress = KERNEL_LOAD_BASE + kMaxKernelSize;
static addr_t sMaxVirtualAddress = KERNEL_LOAD_BASE /*+ 0x400000*/;
#if 0
static addr_t sNextPageTableAddress = 0x90000;
static const uint32 kPageTableRegionEnd = 0x9e000;
// we need to reserve 2 pages for the SMP trampoline code XXX:no
#endif
/** 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));
}
/** 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"));
}
extern "C" void
mmu_init(void)
{
TRACE(("mmu_init\n"));
}
// #pragma mark -
extern "C" status_t
platform_allocate_region(void **_address, size_t size, uint8 protection,
bool /*exactAddress*/)
{
return B_UNSUPPORTED;
}
extern "C" status_t
platform_free_region(void *address, size_t size)
{
return B_UNSUPPORTED;
}
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)
{
return B_UNSUPPORTED;
}
+53
View File
@@ -0,0 +1,53 @@
/*
* Copyright 2008-2010, François Revol, [email protected]. All rights reserved.
* Copyright 2004-2005, Axel Dörfler, [email protected]. 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);
extern addr_t mmu_get_next_page_tables();
struct boot_mmu_ops {
void (*initialize)(void);
/* len=0 to disable */
status_t (*set_tt)(int which, addr_t pa, size_t len, uint32 perms);
/* load root pointers */
status_t (*load_rp)(addr_t pa);
status_t (*allocate_kernel_pgdirs)(void);
status_t (*enable_paging)(void);
status_t (*add_page_table)(addr_t virtualAddress);
void (*unmap_page)(addr_t virtualAddress);
void (*map_page)(addr_t virtualAddress, addr_t pa, uint32 flags);
};
extern const struct boot_mmu_ops k030MMUOps;
extern const struct boot_mmu_ops k040MMUOps;
extern const struct boot_mmu_ops k060MMUOps;
#ifdef __cplusplus
}
#endif
#endif /* MMU_H */
@@ -0,0 +1,195 @@
/* parts from: */
/* $NetBSD: nextrom.h,v 1.11 2011/12/18 04:29:32 tsutsui Exp $ */
/*
* Copyright (c) 1998 Darrin B. Jewell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define N_SIMM 4 /* number of SIMMs in machine */
/* SIMM types */
#define SIMM_SIZE 0x03
#define SIMM_SIZE_EMPTY 0x00
#define SIMM_SIZE_16MB 0x01
#define SIMM_SIZE_4MB 0x02
#define SIMM_SIZE_1MB 0x03
#define SIMM_PAGE_MODE 0x04
#define SIMM_PARITY 0x08 /* ?? */
/* Space for onboard RAM
*/
#define MAX_PHYS_SEGS (N_SIMM + 1)
/* Machine types, used in both assembler and C sources. */
#define NeXT_CUBE 0
#define NeXT_WARP9 1
#define NeXT_X15 2
#define NeXT_WARP9C 3
#define NeXT_TURBO_MONO 4
#define NeXT_TURBO_COLOR 5 /* probed witnessed */
#define ROM_STACK_SIZE (8192 - 2048)
#if 0
/*
* The ROM monitor uses the old structure alignment for backward
* compatibility with previous ROMs. The old alignment is enabled
* with the following pragma. The kernel uses the "MG" macro to
* construct an old alignment offset into the mon_global structure.
* The kernel file <mon/assym.h> should be copied from the "assym.h"
* found in the build directory of the current ROM release.
* It will contain the proper old alignment offset constants.
*/
#if MONITOR
#pragma CC_OLD_STORAGE_LAYOUT_ON
#else MONITOR
#import <mon/assym.h>
#define MG(type, off) \
((type) ((u_int) (mg) + off))
#endif /* MONITOR */
#endif
#define LMAX 128
#define NBOOTFILE 64
#define NADDR 8
/* NetBSD defines macros and other stuff to deal with old alignment
of this structure, we rather declare it as packed aligned at 2.
(the __attribute__ directive does not support an argument so we use pragma)
(cf. src/sys/arch/next68k/next68k/nextrom.h in NetBSD)
*/
/* fake structs to get correct size, calculated from offset deltas */
struct nvram_info {
char data[54-22];
};
struct mon_region {
char data[(232-200)/N_SIMM];
};
enum SIO_ARGS {
SIO_ARGS_max = 1
};
struct km_mon {
char data[370-324];
};
struct km_console_info {
char data[(936-4)-(788+16)];
};
#pragma pack(push,2)
struct mon_global {
char mg_simm[N_SIMM]; /* MUST BE FIRST (accesed early by locore) */
char mg_flags; /* MUST BE SECOND */
#define MGF_LOGINWINDOW 0x80
#define MGF_UART_SETUP 0x40
#define MGF_UART_STOP 0x20
#define MGF_UART_TYPE_AHEAD 0x10
#define MGF_ANIM_RUN 0x08
#define MGF_SCSI_INTR 0x04
#define MGF_KM_EVENT 0x02
#define MGF_KM_TYPE_AHEAD 0x01
u_int mg_sid, mg_pagesize, mg_mon_stack, mg_vbr;
struct nvram_info mg_nvram;
char mg_inetntoa[18];
char mg_inputline[LMAX];
struct mon_region mg_region[N_SIMM];
void *mg_alloc_base, *mg_alloc_brk;
char *mg_boot_dev, *mg_boot_arg, *mg_boot_info, *mg_boot_file;
char mg_bootfile[NBOOTFILE];
enum SIO_ARGS mg_boot_how;
struct km_mon km;
int mon_init;
struct sio *mg_si;
int mg_time;
char *mg_sddp;
char *mg_dgp;
char *mg_s5cp;
char *mg_odc, *mg_odd;
char mg_radix;
int mg_dmachip;
int mg_diskchip;
volatile int *mg_intrstat;
volatile int *mg_intrmask;
void (*mg_nofault)();
char fmt;
int addr[NADDR], na;
int mx, my; /* mouse location */
u_int cursor_save[2][32];
int (*mg_getc)(), (*mg_try_getc)(), (*mg_putc)(int);
int (*mg_alert)(), (*mg_alert_confirm)();
void *(*mg_alloc)();
int (*mg_boot_slider)();
volatile u_char *eventc_latch;
volatile u_int event_high;
struct animation *mg_animate;
int mg_anim_time;
void (*mg_scsi_intr)();
int mg_scsi_intrarg;
short mg_minor, mg_seq;
int (*mg_anim_run)();
short mg_major;
char *mg_clientetheraddr;
int mg_console_i;
int mg_console_o;
#define CONS_I_KBD 0
#define CONS_I_SCC_A 1
#define CONS_I_SCC_B 2
#define CONS_I_NET 3
#define CONS_O_BITMAP 0
#define CONS_O_SCC_A 1
#define CONS_O_SCC_B 2
#define CONS_O_NET 3
char *test_msg;
/* Next entry should be km_coni. Mach depends on this! */
struct km_console_info km_coni; /* Console configuration info. See kmreg.h */
char *mg_fdgp;
char mg_machine_type, mg_board_rev;
int (*mg_as_tune)();
int mg_flags2;
#define MGF2_PARITY 0x80000000
};
#pragma pack(pop)
extern struct mon_global *mg;
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,39 @@
/*
* Copyright 2020, François Revol, revol@free.fr. All rights reserved.
* Copyright 2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT license.
*/
/** This file contains the entry point for the NeXT loader.
*/
/*
* references :
* NetBSD sys/arch/next68k/stand/boot/srt0.s
*/
#include <asm_defs.h>
// 1 enable verbose output
//#define DEBUG 1
#define GLOBAL(x) .globl x ; x
//#define FUNCTION(x) .global x; .type x,@function; x
.text
SYMBOL(_start):
// find the monitor vector and push it
movec %vbr,%a3
movel %a3@(4),-(%sp)
// push the arg (bootarg)
movel %sp@(8),-(%sp)
jsr start_next
addql #8,%sp
rts
SYMBOL_END(_start)
@@ -0,0 +1,187 @@
/*
* Copyright 2008-2020, François Revol, [email protected]. All rights reserved.
* Copyright 2003-2010, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <KernelExport.h>
#include <boot/platform.h>
#include <boot/heap.h>
#include <boot/stage2.h>
#include <arch/cpu.h>
#include <string.h>
#include "console.h"
#include "cpu.h"
#include "mmu.h"
#include "keyboard.h"
#include "nextrom.h"
#define HEAP_SIZE 65536
// GCC defined globals
extern void (*__ctor_list)(void);
extern void (*__ctor_end)(void);
extern uint8 __bss_start;
extern uint8 _end;
extern "C" int main(stage2_args *args);
extern "C" void _start(void);
// the boot rom monitor entry point
struct mon_global *mg = NULL;
static 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)();
}
}
extern "C" uint32
platform_boot_options(void)
{
#if 0
if (!gKernelArgs.fb.enabled)
sBootOptions |= check_for_boot_keys();
#endif
return sBootOptions;
}
extern "C" void
platform_start_kernel(void)
{
#if 0
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;
preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
gKernelArgs.kernel_image.Pointer());
//smp_init_other_cpus();
//serial_cleanup();
mmu_init_for_kernel();
//smp_boot_other_cpus();
#warning M68K: stop ints
dprintf("kernel entry at %lx\n", image->elf_header.e_entry);
asm volatile (
"move.l %0,%%sp; " // move stack out of way
: : "m" (stackTop));
asm volatile (
"or #0x0700,%%sr; " : : ); // disable interrupts
asm volatile (
"move.l #0x0,-(%%sp); " // we're the BSP cpu (0)
"move.l %0,-(%%sp); " // kernel args
"move.l #0x0,-(%%sp);" // dummy retval for call to main
"move.l %1,-(%%sp); " // this is the start address
"rts; " // jump.
: : "g" (args), "g" (image->elf_header.e_entry));
// Huston, we have a problem!
asm volatile (
"and #0xf8ff,%%sr; " : : ); // reenable interrupts
panic("kernel returned!\n");
#endif
}
extern "C" void
platform_exit(void)
{
// TODO
while (true);
}
inline void dump_mg(struct mon_global *mg)
{
dprintf("mg@ %p\n", (void*)mg);
dprintf("mg_flags\t%x\n", (unsigned char)mg->mg_flags);
dprintf("mg_sid\t%x\n", mg->mg_sid);
dprintf("mg_pagesize\t%x\n", mg->mg_pagesize);
dprintf("mg_mon_stack\t%x\n", mg->mg_mon_stack);
dprintf("mg_vbr\t%x\n", mg->mg_vbr);
dprintf("mg_console_i\t%x\n", mg->mg_console_i);
dprintf("mg_console_o\t%x\n", mg->mg_console_o);
}
extern "C" void *
start_next(const char *boot_args, struct mon_global *monitor)
{
stage2_args args;
monitor->mg_putc('H');
//asm("cld"); // Ain't nothing but a GCC thang.
//asm("fninit"); // initialize floating point unit
clear_bss();
/* save monitor ROM entry */
mg = monitor;
// DEBUG
mg->mg_putc('A');
call_ctors();
// call C++ constructors before doing anything else
mg->mg_putc('I');
args.heap_size = HEAP_SIZE;
args.arguments = NULL;
//serial_init();
mg->mg_putc('K');
console_init();
mg->mg_putc('U');
mg->mg_putc('\n');
dump_mg(mg);
//while(1);
//return NULL;
#if 0
// TODO
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();
//apm_init();
//smp_init();
#endif
main(&args);
return NULL;
}
@@ -0,0 +1,114 @@
/*
* Copyright 2008-2010, François Revol, [email protected]. All rights reserved.
* Copyright 2004-2007, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "nextrom.h"
#include "video.h"
#include "mmu.h"
//#include "images.h"
#include <arch/cpu.h>
#include <boot/stage2.h>
#include <boot/platform.h>
#include <boot/menu.h>
#include <boot/kernel_args.h>
#include <boot/platform/generic/video.h>
#include <util/list.h>
#include <drivers/driver_settings.h>
#include <GraphicsDefs.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->AddItem(new(nothrow) MenuItem("Standard VGA"));
menu->AddSeparatorItem();
menu->AddItem(item = new(nothrow) MenuItem("Return to main menu"));
item->SetType(MENU_ITEM_NO_CHOICE);
return menu;
}
void
platform_blit4(addr_t frameBuffer, const uint8 *data,
uint16 width, uint16 height, uint16 imageWidth, uint16 left, uint16 top)
{
if (!data)
return;
}
extern "C" void
platform_set_palette(const uint8 *palette)
{
}
// #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;
}
extern "C" void
platform_switch_to_text_mode(void)
{
if (!gKernelArgs.frame_buffer.enabled) {
return;
}
gKernelArgs.frame_buffer.enabled = 0;
}
extern "C" status_t
platform_init_video(void)
{
gKernelArgs.frame_buffer.enabled = 0;
return B_OK;
}
@@ -0,0 +1,18 @@
/*
* Copyright 2008-2010, François Revol, [email protected]. All rights reserved.
* Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT 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 */
@@ -0,0 +1,59 @@
OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k")
OUTPUT_ARCH(m68k)
ENTRY(_start)
PHDRS
{
/* have a non-loadable program chunk with the headers, then a loadable one
* with the actual data. This eases the work of elf2aout. */
headers PT_NULL FILEHDR PHDRS ;
text PT_LOAD ;
}
SECTIONS
{
/* Execution address.
* The NetBSD loader uses this, not sure if it's a ROM constant or not.
*/
. = 0x04380000;
__text_begin = .;
/* text/read-only data */
.text : {
/* Make sure entry point is at start of file. Not required, since
* it is set using ENTRY above, but it looks nicer and makes it
* clearer we jumped at the correct address. */
*(.text.start)
*(.text .text.* .gnu.linkonce.t.*)
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.sdata2)
} :text
/*. = ALIGN(0x4);*/
.data : {
__ctor_list = .;
*(.ctors)
__ctor_end = .;
__data_start = .;
*(.data .gnu.linkonce.d.*)
*(.data.rel.ro.local .data.rel.ro*)
*(.got .got2)
*(.sdata .sdata.* .gnu.linkonce.s.* .fixup)
} :text
/* uninitialized data (in same segment as writable data) */
__bss_start = .;
.bss : {
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.bss .bss.* .gnu.linkonce.b.*)
. = ALIGN(0x1000);
} :text
_end = . ;
/* Strip unnecessary stuff */
/DISCARD/ : { *(.comment .note .eh_frame .dtors .stab .stabstr .debug* .debug_* .gnu.attributes) }
}