diff --git a/build/jam/ArchitectureRules b/build/jam/ArchitectureRules index 65309cbc7e..96878252bb 100644 --- a/build/jam/ArchitectureRules +++ b/build/jam/ArchitectureRules @@ -314,7 +314,7 @@ rule KernelArchitectureSetup architecture case 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) { case atari_m68k : { @@ -325,6 +325,10 @@ rule KernelArchitectureSetup architecture # for now we have trouble reading from double-sided images 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)) HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 260 ; # in kB diff --git a/src/system/boot/Jamfile b/src/system/boot/Jamfile index 728a1f11ab..6a1f525502 100644 --- a/src/system/boot/Jamfile +++ b/src/system/boot/Jamfile @@ -28,6 +28,10 @@ rule BuildOpenFirmwareLoader { rule BuildAoutLoader { local haikuLoader = $(1) ; local bootLoader = $(2) ; + + Depends $(haikuLoader) : $(bootLoader) ; + MakeLocateDebug $(haikuLoader) ; + ELF2AOUT on $(haikuLoader) = elf2aout ; Depends $(haikuLoader) : elf2aout ; } @@ -375,6 +379,9 @@ for platform in [ MultiBootSubDirSetup ] { : -Bstatic ; + case next_m68k : + BuildAoutLoader haiku_loader.$(TARGET_BOOT_PLATFORM) : boot_loader_$(TARGET_BOOT_PLATFORM) ; + case * : Exit "Currently unsupported haiku_loader:" $(TARGET_BOOT_PLATFORM) ; } diff --git a/src/system/boot/arch/m68k/Jamfile b/src/system/boot/arch/m68k/Jamfile index 3460f071f7..f287e9d987 100644 --- a/src/system/boot/arch/m68k/Jamfile +++ b/src/system/boot/arch/m68k/Jamfile @@ -1,7 +1,7 @@ SubDir HAIKU_TOP src system boot arch m68k ; local platform ; -for platform in [ MultiBootSubDirSetup amiga_m68k atari_m68k ] { +for platform in [ MultiBootSubDirSetup amiga_m68k atari_m68k next_m68k ] { on $(platform) { DEFINES += _BOOT_MODE ; diff --git a/src/system/boot/platform/next_m68k/Jamfile b/src/system/boot/platform/next_m68k/Jamfile new file mode 100644 index 0000000000..ead6f371db --- /dev/null +++ b/src/system/boot/platform/next_m68k/Jamfile @@ -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 diff --git a/src/system/boot/platform/next_m68k/aligntest.c b/src/system/boot/platform/next_m68k/aligntest.c new file mode 100644 index 0000000000..9aee62263c --- /dev/null +++ b/src/system/boot/platform/next_m68k/aligntest.c @@ -0,0 +1,16 @@ +#include +#include +#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; +} + diff --git a/src/system/boot/platform/next_m68k/console.cpp b/src/system/boot/platform/next_m68k/console.cpp new file mode 100644 index 0000000000..09de985967 --- /dev/null +++ b/src/system/boot/platform/next_m68k/console.cpp @@ -0,0 +1,276 @@ +/* + * Copyright 2007-2010, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT license. + * + * Author: + * François Revol, revol@free.fr. + */ + +#include +#include +#include "nextrom.h" +#include + +#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; +} + diff --git a/src/system/boot/platform/next_m68k/console.h b/src/system/boot/platform/next_m68k/console.h new file mode 100644 index 0000000000..216c923cfd --- /dev/null +++ b/src/system/boot/platform/next_m68k/console.h @@ -0,0 +1,24 @@ +/* + * Copyright 2007, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT license. + * + * Author: + * François Revol, revol@free.fr. + */ + +#ifndef CONSOLE_H +#define CONSOLE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern status_t console_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* CONSOLE_H */ diff --git a/src/system/boot/platform/next_m68k/cpu.cpp b/src/system/boot/platform/next_m68k/cpu.cpp new file mode 100644 index 0000000000..3bc38bd234 --- /dev/null +++ b/src/system/boot/platform/next_m68k/cpu.cpp @@ -0,0 +1,94 @@ +/* + * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "cpu.h" +#include "nextrom.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +//#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) +{ +} + diff --git a/src/system/boot/platform/next_m68k/cpu.h b/src/system/boot/platform/next_m68k/cpu.h new file mode 100644 index 0000000000..f8eff4f44a --- /dev/null +++ b/src/system/boot/platform/next_m68k/cpu.h @@ -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 + + +#ifdef __cplusplus +extern "C" { +#endif + +extern void cpu_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* CPU_H */ diff --git a/src/system/boot/platform/next_m68k/debug.cpp b/src/system/boot/platform/next_m68k/debug.cpp new file mode 100644 index 0000000000..2778b7f81f --- /dev/null +++ b/src/system/boot/platform/next_m68k/debug.cpp @@ -0,0 +1,76 @@ +/* + * Copyright 2008-2010, François Revol, revol@free.fr. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "keyboard.h" +#include "nextrom.h" + +#include +#include +#include +#include + +#include + +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; +} diff --git a/src/system/boot/platform/next_m68k/devices.cpp b/src/system/boot/platform/next_m68k/devices.cpp new file mode 100644 index 0000000000..bf94817a4a --- /dev/null +++ b/src/system/boot/platform/next_m68k/devices.cpp @@ -0,0 +1,64 @@ +/* + * Copyright 2008-2010, François Revol, revol@free.fr. All rights reserved. + * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include +#include +#include +#include +#include + +#include + +#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() +{ +} diff --git a/src/system/boot/platform/next_m68k/keyboard.cpp b/src/system/boot/platform/next_m68k/keyboard.cpp new file mode 100644 index 0000000000..d1c14079e3 --- /dev/null +++ b/src/system/boot/platform/next_m68k/keyboard.cpp @@ -0,0 +1,66 @@ +/* + * Copyright 2008-2010, François Revol, revol@free.fr. All rights reserved. + * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "keyboard.h" +#include "nextrom.h" + +#include + + +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; +} + diff --git a/src/system/boot/platform/next_m68k/keyboard.h b/src/system/boot/platform/next_m68k/keyboard.h new file mode 100644 index 0000000000..306a80c04c --- /dev/null +++ b/src/system/boot/platform/next_m68k/keyboard.h @@ -0,0 +1,40 @@ +#ifndef KEYBOARD_H +#define KEYBOARD_H + + +#include + + +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 */ diff --git a/src/system/boot/platform/next_m68k/menu.cpp b/src/system/boot/platform/next_m68k/menu.cpp new file mode 100644 index 0000000000..2c7f5718a0 --- /dev/null +++ b/src/system/boot/platform/next_m68k/menu.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2008-2010, François Revol, revol@free.fr. All rights reserved. + * 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 +#include +#include + + +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); +} diff --git a/src/system/boot/platform/next_m68k/mmu.cpp b/src/system/boot/platform/next_m68k/mmu.cpp new file mode 100644 index 0000000000..43e8e4726a --- /dev/null +++ b/src/system/boot/platform/next_m68k/mmu.cpp @@ -0,0 +1,168 @@ +/* + * Copyright 2008-2010, François Revol, revol@free.fr. All rights reserved. + * Copyright 2004-2007, 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 "nextrom.h" +#include "mmu.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#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; +} + + diff --git a/src/system/boot/platform/next_m68k/mmu.h b/src/system/boot/platform/next_m68k/mmu.h new file mode 100644 index 0000000000..b8f4ec14d9 --- /dev/null +++ b/src/system/boot/platform/next_m68k/mmu.h @@ -0,0 +1,53 @@ +/* + * Copyright 2008-2010, François Revol, revol@free.fr. All rights reserved. + * 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 + + +// 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 */ diff --git a/src/system/boot/platform/next_m68k/nextrom.h b/src/system/boot/platform/next_m68k/nextrom.h new file mode 100644 index 0000000000..02b86d0482 --- /dev/null +++ b/src/system/boot/platform/next_m68k/nextrom.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 + +#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 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 +#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 diff --git a/src/system/boot/platform/next_m68k/shell.S b/src/system/boot/platform/next_m68k/shell.S new file mode 100644 index 0000000000..713cc6125c --- /dev/null +++ b/src/system/boot/platform/next_m68k/shell.S @@ -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 + + +// 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) + + diff --git a/src/system/boot/platform/next_m68k/start.cpp b/src/system/boot/platform/next_m68k/start.cpp new file mode 100644 index 0000000000..4fe2636680 --- /dev/null +++ b/src/system/boot/platform/next_m68k/start.cpp @@ -0,0 +1,187 @@ +/* + * Copyright 2008-2020, François Revol, revol@free.fr. All rights reserved. + * Copyright 2003-2010, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include +#include +#include +#include +#include + +#include + +#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( + 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; +} diff --git a/src/system/boot/platform/next_m68k/video.cpp b/src/system/boot/platform/next_m68k/video.cpp new file mode 100644 index 0000000000..aecfbdb22f --- /dev/null +++ b/src/system/boot/platform/next_m68k/video.cpp @@ -0,0 +1,114 @@ +/* + * Copyright 2008-2010, François Revol, revol@free.fr. All rights reserved. + * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include "nextrom.h" +#include "video.h" +#include "mmu.h" +//#include "images.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#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; +} + diff --git a/src/system/boot/platform/next_m68k/video.h b/src/system/boot/platform/next_m68k/video.h new file mode 100644 index 0000000000..850da51919 --- /dev/null +++ b/src/system/boot/platform/next_m68k/video.h @@ -0,0 +1,18 @@ +/* + * Copyright 2008-2010, François Revol, revol@free.fr. All rights reserved. + * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef VIDEO_H +#define VIDEO_H + + +#include + +class Menu; +class MenuItem; + +bool video_mode_hook(Menu *menu, MenuItem *item); +Menu *video_mode_menu(); + +#endif /* VIDEO_H */ diff --git a/src/system/ldscripts/m68k/boot_loader_next_m68k.ld b/src/system/ldscripts/m68k/boot_loader_next_m68k.ld new file mode 100644 index 0000000000..16d5b7ffef --- /dev/null +++ b/src/system/ldscripts/m68k/boot_loader_next_m68k.ld @@ -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) } +}