boot/platform/u-boot: Drop ARM support.

Newer versions of u-boot support EFI natively, which is what we
have been making use of instead.

There may be some use for the "native" u-boot loader still on PowerPC,
but otherwise the EFI support is much more advanced and even in u-boot
supports as or more features than "native" loaders, so there is no
reason to keep this around.
This commit is contained in:
Augustin Cavalier
2022-06-28 12:27:06 -04:00
parent 7c09ef1255
commit 63816858af
21 changed files with 2 additions and 2682 deletions
-80
View File
@@ -1,80 +0,0 @@
# BeagleBoard board-specific definitions
HAIKU_BOARD_DESCRIPTION = "BeagleBoard" ;
HAIKU_BOARD_FDT_NAME = "omap3-beagle-xm" ;
#
# Various hardcoded addresses
#
# load address for haiku_loader
HAIKU_BOARD_LOADER_BASE = 0x80800000 ;
# entry points (raw binary, and netbsd loader emulation)
HAIKU_BOARD_LOADER_ENTRY_RAW = $(HAIKU_BOARD_LOADER_BASE) ;
HAIKU_BOARD_LOADER_ENTRY_NBSD = `printf \"obase=16;ibase=16;8 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
HAIKU_BOARD_LOADER_ENTRY_LINUX = `printf \"obase=16;ibase=16;10 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
HAIKU_BOARD_LOADER_ENTRY = $(HAIKU_BOARD_LOADER_ENTRY_NBSD) ;
HAIKU_BOARD_LOADER_FAKE_OS = netbsd ;
# load address for haiku_loader uimage
# (must be different than real load address)
HAIKU_BOARD_LOADER_UIBASE = 0x82800000 ;
#
# Flash image
#
# OMAP x-loader image, must be first file on FAT partition
HAIKU_BOARD_MLO_IMAGE ?= MLO ;
HAIKU_BOARD_MLO_IMAGE_URL =
http://downloads.angstrom-distribution.org/demo/beagleboard/MLO ;
# u-boot binary image filename, to build the flash image
# XXX: Locate it somehow (for now just put it in generated/)
HAIKU_BOARD_UBOOT_IMAGE ?= u-boot.img ;
HAIKU_BOARD_UBOOT_IMAGE_URL =
http://downloads.angstrom-distribution.org/demo/beagleboard/u-boot.img ;
#
# mmc/SD image
#
# in MB
HAIKU_BOARD_SDIMAGE_SIZE = 64 ;
# in MB
HAIKU_BOARD_SDIMAGE_FAT_SIZE = 32 ;
mloFile = [ DownloadFile $(HAIKU_BOARD_MLO_IMAGE)
: $(HAIKU_BOARD_MLO_IMAGE_URL) ] ;
ubootFile = [ DownloadFile $(HAIKU_BOARD_UBOOT_IMAGE)
: $(HAIKU_BOARD_UBOOT_IMAGE_URL) ] ;
# U-Boot environment
# We load the uImage 2MB above its final destination, bootm will decode
# it to the proper location. Our image is smaller than 2MB so this works.
#HAIKU_BOARD_SDIMAGE_UBOOT_UENV_NAME = uEnv.txt ;
HAIKU_BOARD_SDIMAGE_UBOOT_UENV = "uenvcmd=run loadImage; run mmcboot; \
loadImage=fatload mmc0 0 $(HAIKU_BOARD_LOADER_UIBASE) haiku_loader_linux.ub; fatload mmc 0 0x80100000 /fdt/$(HAIKU_BOARD_FDT_NAME).dtb; fatload mmc 0 0x81200000 haiku-floppyboot.tgz.ub; \
mmcboot=bootm $(HAIKU_BOARD_LOADER_UIBASE) 0x81200000 0x80100000" ;
HAIKU_BOARD_SDIMAGE_FILES =
$(mloFile)
$(ubootFile)
haiku_loader_nbsd.ub
haiku_loader_linux.ub
haiku-floppyboot.tgz.ub
;
#
# gcc flags for the specific cpu
local flags = -mcpu=cortex-a8 -mfpu=vfpv3 -mfloat-abi=hard ;
HAIKU_ASFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
HAIKU_CCFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
HAIKU_C++FLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
-60
View File
@@ -1,60 +0,0 @@
# BeagleBone board-specific definitions
HAIKU_BOARD_DESCRIPTION = "BeagleBone" ;
HAIKU_BOARD_FDT_NAME = "boneblack" ;
# Not that many in the wild
#HAIKU_BOARD_FDT_NAME = "beaglebone" ;
#
# Various hardcoded addresses
#
# load address for haiku_loader
HAIKU_BOARD_LOADER_BASE = 0x80800000 ;
HAIKU_BOARD_LOADER_ENTRY_RAW = $(HAIKU_BOARD_LOADER_BASE) ;
HAIKU_BOARD_LOADER_ENTRY_NBSD = `printf \"obase=16;ibase=16;8 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
HAIKU_BOARD_LOADER_ENTRY_LINUX = `printf \"obase=16;ibase=16;10 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
#
# mmc/SD image
#
# in MB
HAIKU_BOARD_SDIMAGE_SIZE = 64 ;
HAIKU_BOARD_SDIMAGE_FAT_SIZE = 32 ;
# OMAP x-loader image, must be first file on FAT partition
HAIKU_BOARD_MLO_IMAGE_URL = https://github.com/haiku/firmware/raw/master/arm/beaglebone ;
mloFile = [ DownloadFile MLO : $(HAIKU_BOARD_MLO_IMAGE_URL)/MLO ] ;
# u-boot image
HAIKU_BOARD_UBOOT_IMAGE_URL = https://github.com/haiku/firmware/raw/master/arm/beaglebone ;
ubootFile = [ DownloadFile u-boot.img : $(HAIKU_BOARD_UBOOT_IMAGE_URL)/u-boot.img ] ;
# U-Boot environment
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME = boot.scr ;
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT = "\
fatload mmc 0 ${fdt_addr_r} /fdt/$(HAIKU_BOARD_FDT_NAME).dtb \
fdt addr ${fdt_addr_r} \
fatload mmc 0 ${ramdisk_addr_r} haiku-floppyboot.tgz.ub \
fatload mmc 0 ${kernel_addr_r} haiku_loader_linux.ub \
bootm ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}" ;
HAIKU_BOARD_SDIMAGE_FILES =
$(mloFile)
$(ubootFile)
haiku_loader_linux.ub
haiku-floppyboot.tgz.ub
$(HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME)
;
#
# gcc flags for the specific cpu
local flags = -mcpu=cortex-a8 -mfpu=vfpv3 -mfloat-abi=hard ;
HAIKU_ASFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
HAIKU_CCFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
HAIKU_C++FLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
-72
View File
@@ -1,72 +0,0 @@
# Cubieboard 4 board-specific definitions
# This likely could be easily used for other Allwinner chipsets
HAIKU_BOARD_DESCRIPTION = "Cubieboard 4 (CC-A80)" ;
HAIKU_BOARD_FDT_NAME = "cubieboard4" ;
#
# Various hardcoded addresses
#
# 0x20000000 = SDRAM start
# 0x20007800 = haiku_loader_linux.ub
# 0x20087800 = BASE
HAIKU_BOARD_LOADER_BASE = 0x20087800 ;
HAIKU_BOARD_LOADER_ENTRY_RAW = $(HAIKU_BOARD_LOADER_BASE) ;
HAIKU_BOARD_LOADER_ENTRY_NBSD = `printf \"obase=16;ibase=16;8 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
HAIKU_BOARD_LOADER_ENTRY_LINUX = `printf \"obase=16;ibase=16;10 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
#
# mmc/SD image
#
HAIKU_BOARD_FIRMWARE_URL = "https://github.com/cubieboard/CC-A80-binaries/raw/master/bin" ;
# u-boot image
# Dear Cubbieboard, add fdt_addr_r, ramdisk_addr_r, kernel_addr_r to u-boot
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME = boot.scr ;
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT = "\
fatload mmc 0 0x20800000 haiku-floppyboot.tgz.ub \
fatload mmc 0 0x20007800 haiku_loader_linux.ub \
bootm 0x20007800 0x20800000" ;
HAIKU_BOARD_SDIMAGE_FAT_SIZE = 32 ;
HAIKU_BOARD_SDIMAGE_FILES =
haiku_loader_linux.ub
haiku-floppyboot.tgz.ub
$(HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME)
;
HAIKU_BOARD_SDIMAGE_BEGIN = 40950 ; # 512-byte sectors (divisible by 63)
HAIKU_BOARD_SDIMAGE_SIZE = 128 ; # MiB
boot0File = [ DownloadFile sdcard-boot0 : $(HAIKU_BOARD_FIRMWARE_URL)/sdcard-boot0 ] ;
boot1File = [ DownloadFile sdcard-boot1 : $(HAIKU_BOARD_FIRMWARE_URL)/sdcard-boot1 ] ;
# The Allwinner chips require an SD card "blessed" with
# the boot0 SPL and boot1 (u-boot) at a fixed location on
# the SD card. (Dear AW, please support loading from FAT)
HAIKU_BOARD_SDIMAGE_BOOT0_FILE = $(boot0File) ;
HAIKU_BOARD_SDIMAGE_BOOT0_SEEK = 8192 ;
HAIKU_BOARD_SDIMAGE_BOOT1_FILE = $(boot1File) ;
HAIKU_BOARD_SDIMAGE_BOOT1_SEEK = 19554304 ;
#
# gcc flags for the specific cpu
#
local flags = -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard ;
HAIKU_ASFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
HAIKU_CCFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
HAIKU_C++FLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
# Workaround for ld using 32k for alignment despite forcing it in the config...
# should definitely not be needed!
HAIKU_KERNEL_LINKFLAGS +=
-Wl,-z -Wl,max-page-size=0x1000
-Wl,-z -Wl,common-page-size=0x1000 ;
HAIKU_LINKFLAGS_$(HAIKU_PACKAGING_ARCH) +=
-Wl,-z -Wl,max-page-size=0x1000
-Wl,-z -Wl,common-page-size=0x1000 ;
-77
View File
@@ -1,77 +0,0 @@
# Gumstix Verdex board-specific definitions
HAIKU_BOARD_DESCRIPTION = "Openmoko Neo FreeRunner" ;
#
# Various hardcoded addresses
#
# load address for haiku_loader
HAIKU_BOARD_LOADER_BASE = 0x32000000 ;
# entry points (raw binary, and netbsd loader emulation)
HAIKU_BOARD_LOADER_ENTRY_RAW = 0x32000000 ;
HAIKU_BOARD_LOADER_ENTRY_NBSD = 0x32000008 ;
HAIKU_BOARD_LOADER_ENTRY = $(HAIKU_BOARD_LOADER_ENTRY_NBSD) ;
HAIKU_BOARD_LOADER_FAKE_OS = netbsd ;
# load address for haiku_loader uimage
# (must be different than real load address)
HAIKU_BOARD_LOADER_UIBASE = 0x34000000 ;
#
# Flash image
#
# u-boot binary image filename, to build the flash image
# XXX: Locate it somehow (for now just put it in generated/)
#HAIKU_BOARD_UBOOT_IMAGE ?= u-boot-verdex-400-r1604.bin ;
#HAIKU_BOARD_UBOOT_IMAGE_URL =
# http://www.gumstix.net/feeds/u-boot/u-boot-verdex-400-r1604.bin ;
#
# mmc/SD image
#
# in MB
HAIKU_BOARD_SDIMAGE_SIZE = 256 ;
# in MB
HAIKU_BOARD_SDIMAGE_FAT_SIZE = 32 ;
# autoboot script
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME = uImage.bin ;
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT = "\
if mmcinit; then \
neo backlight off; \
fatload mmc 0 $(HAIKU_BOARD_LOADER_UIBASE) haiku_loader_nbsd.ub; \
neo backlight on; \
bootm $(HAIKU_BOARD_LOADER_UIBASE); \
fi" ;
HAIKU_BOARD_SDIMAGE_FILES =
haiku_loader
haiku_loader.ub
haiku_loader_nbsd.ub
$(HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME)
;
#
# gcc flags for the specific cpu
#
HAIKU_CCFLAGS_$(HAIKU_PACKAGING_ARCH) += -mcpu=arm920t ;
HAIKU_C++FLAGS_$(HAIKU_PACKAGING_ARCH) += -mcpu=arm920t ;
# Workaround for ld using 32k for alignment despite forcing it in the config...
# should definitely not be needed!
HAIKU_KERNEL_LINKFLAGS +=
-Wl,-z -Wl,max-page-size=0x1000
-Wl,-z -Wl,common-page-size=0x1000 ;
HAIKU_LINKFLAGS_$(HAIKU_PACKAGING_ARCH) +=
-Wl,-z -Wl,max-page-size=0x1000
-Wl,-z -Wl,common-page-size=0x1000 ;
-101
View File
@@ -1,101 +0,0 @@
# Gumstix Overo board-specific definitions
HAIKU_BOARD_DESCRIPTION = "Gumstix Overo" ;
HAIKU_BOARD_FDT_NAME = "omap3-overo-tobi" ;
#
# Various hardcoded addresses
#
# load address for haiku_loader
HAIKU_BOARD_LOADER_BASE = 0x80800000 ;
# entry points (raw binary, and netbsd loader emulation)
HAIKU_BOARD_LOADER_ENTRY_RAW = 0x80800000 ;
HAIKU_BOARD_LOADER_ENTRY_NBSD = 0x80800008 ;
HAIKU_BOARD_LOADER_ENTRY_LINUX = 0x80800010 ;
HAIKU_BOARD_LOADER_ENTRY = $(HAIKU_BOARD_LOADER_ENTRY_NBSD) ;
HAIKU_BOARD_LOADER_FAKE_OS = netbsd ;
# load address for haiku_loader uimage
# (must be different than real load address)
HAIKU_BOARD_LOADER_UIBASE = 0x82800000 ;
#
# Flash image
#
# cf. http://gumstix.org/how-to/70-writing-images-to-flash.html
# OMAP x-loader image, must be first file in Flash image
HAIKU_BOARD_MLO_IMAGE ?= MLO ;
HAIKU_BOARD_MLO_IMAGE_URL =
http://cumulus.gumstix.org/images/angstrom/developer/current/MLO ;
# u-boot binary image filename, to build the flash image
# XXX: Locate it somehow (for now just put it in generated/)
HAIKU_BOARD_UBOOT_IMAGE ?= u-boot.bin ;
HAIKU_BOARD_UBOOT_IMAGE_URL =
http://cumulus.gumstix.org/images/angstrom/developer/current/u-boot.bin ;
mloFile = [ DownloadFile $(HAIKU_BOARD_MLO_IMAGE)
: $(HAIKU_BOARD_MLO_IMAGE_URL) ] ;
ubootFile = [ DownloadFile $(HAIKU_BOARD_UBOOT_IMAGE)
: $(HAIKU_BOARD_UBOOT_IMAGE_URL) ] ;
FLASH_IMAGE_PARTS =
$(mloFile)
$(ubootFile)
;
# flash offsets:
# in kB
FLASH_IMAGE_LOADER_OFFSET = 31744 ;
FLASH_OFFSET on $(mloFile) = 0 ;
FLASH_OFFSET on $(ubootFile) = 512 ;
#
# mmc/SD image
#
# in MB
HAIKU_BOARD_SDIMAGE_SIZE = 256 ;
# in MB
HAIKU_BOARD_SDIMAGE_FAT_SIZE = 32 ;
# autoboot script
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME = boot.scr ;
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT = "\
setenv bootargs debug_screen true; \
if mmc rescan; then \
fatload mmc 0 0x80100000 /fdt/$(HAIKU_BOARD_FDT_NAME).dtb ; \
fatload mmc 0 0x81200000 haiku-floppyboot.tgz.ub; \
fatload mmc 0 $(HAIKU_BOARD_LOADER_UIBASE) haiku_loader_linux.ub; \
bootm $(HAIKU_BOARD_LOADER_UIBASE) 0x81200000 0x80100000; \
fi" ;
HAIKU_BOARD_SDIMAGE_FILES =
$(mloFile)
$(ubootFile)
haiku_loader
haiku_loader.ub
haiku_loader_linux.ub
haiku_loader_nbsd.ub
haiku-floppyboot.tgz.ub
$(HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME)
;
#
# gcc flags for the specific cpu
#
local flags = -mcpu=cortex-a8 -mfpu=vfpv3 -mfloat-abi=hard ;
HAIKU_ASFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
HAIKU_CCFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
HAIKU_C++FLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
-74
View File
@@ -1,74 +0,0 @@
# Raspberry Pi 2 board-specific definitions
HAIKU_BOARD_DESCRIPTION = "Raspberry Pi 2" ;
HAIKU_BOARD_FDT_NAME = "rpi2" ;
#
# Various hardcoded addresses
#
HAIKU_BOARD_LOADER_BASE = 0x00080000 ;
HAIKU_BOARD_LOADER_ENTRY_RAW = $(HAIKU_BOARD_LOADER_BASE) ;
HAIKU_BOARD_LOADER_ENTRY_NBSD = `printf \"obase=16;ibase=16;8 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
HAIKU_BOARD_LOADER_ENTRY_LINUX = `printf \"obase=16;ibase=16;10 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
#
# mmc/SD image
#
# u-boot image
HAIKU_BOARD_UBOOT_IMAGE_URL = https://github.com/haiku/firmware/raw/master/arm/rpi2 ;
ubootFile = [ DownloadFile u-boot.bin : $(HAIKU_BOARD_UBOOT_IMAGE_URL)/u-boot.bin ] ;
configFile = [ DownloadFile config.txt : $(HAIKU_BOARD_UBOOT_IMAGE_URL)/config.txt ] ;
# Raspberry Pi foundation loader
HAIKU_BOARD_FIRMWARE_URL = https://github.com/raspberrypi/firmware/raw/master/boot ;
bootcodeFile = [ DownloadFile bootcode.bin : $(HAIKU_BOARD_FIRMWARE_URL)/bootcode.bin ] ;
startFile = [ DownloadFile start.elf : $(HAIKU_BOARD_FIRMWARE_URL)/start.elf ] ;
licenseFile = [ DownloadFile LICENCE.broadcom : $(HAIKU_BOARD_FIRMWARE_URL)/LICENCE.broadcom ] ;
HAIKU_BOARD_FIRMWARE_FILES =
$(bootcodeFile)
$(startFile)
$(licenseFile)
;
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME = boot.scr ;
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT = "\
fatload mmc 0 ${fdt_addr_r} /fdt/$(HAIKU_BOARD_FDT_NAME).dtb \
fdt addr ${fdt_addr_r} \
fatload mmc 0 ${ramdisk_addr_r} haiku-floppyboot.tgz.ub \
fatload mmc 0 ${kernel_addr_r} haiku_loader_linux.ub \
bootm ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}" ;
HAIKU_BOARD_SDIMAGE_FAT_SIZE = 32 ;
HAIKU_BOARD_SDIMAGE_FILES =
$(HAIKU_BOARD_FIRMWARE_FILES)
$(configFile)
$(ubootFile)
haiku_loader_linux.ub
haiku-floppyboot.tgz.ub
$(HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME)
;
HAIKU_BOARD_SDIMAGE_SIZE = 128 ;
#
# gcc flags for the specific cpu
#
local flags = -march=armv7-a -mfloat-abi=hard ;
HAIKU_ASFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
HAIKU_CCFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
HAIKU_C++FLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
# Workaround for ld using 32k for alignment despite forcing it in the config...
# should definitely not be needed!
HAIKU_KERNEL_LINKFLAGS +=
-Wl,-z -Wl,max-page-size=0x1000
-Wl,-z -Wl,common-page-size=0x1000 ;
HAIKU_LINKFLAGS_$(HAIKU_PACKAGING_ARCH) +=
-Wl,-z -Wl,max-page-size=0x1000
-Wl,-z -Wl,common-page-size=0x1000 ;
-25
View File
@@ -1,25 +0,0 @@
##### CPU Speed
#arm_freq 700
##### Memory layout
#gpu_mem 64
# Memory based on model.. overrides gpu_mem
#gpu_mem_256 64
#gpu_mem_512 64
##### Low level
kernel=haiku_loader
kernel_address=0x0
ramfsfile=haiku-floppyboot.tgz
ramfsaddr=0x04000000
# Skip boot tags for non-linux platforms
disable_commandline_tags=1
#device_tree=bcm2835.dtb
#device_tree_address=0x100
##### UART Settings
# Default is 115200
#init_uart_baud=9600
#init_uart_clock=
+1 -1
View File
@@ -24,7 +24,7 @@ local kernelGenericDriverSources =
; ;
local platform ; local platform ;
for platform in [ MultiBootSubDirSetup u-boot efi ] { for platform in [ MultiBootSubDirSetup efi ] {
on $(platform) { on $(platform) {
DEFINES += _BOOT_MODE ; DEFINES += _BOOT_MODE ;
BootMergeObject [ FGristFiles boot_arch_$(TARGET_KERNEL_ARCH).o ] : BootMergeObject [ FGristFiles boot_arch_$(TARGET_KERNEL_ARCH).o ] :
+1 -1
View File
@@ -32,7 +32,7 @@ local kernelGenericDriverSources =
; ;
local platform ; local platform ;
for platform in [ MultiBootSubDirSetup u-boot efi riscv ] { for platform in [ MultiBootSubDirSetup efi riscv ] {
on $(platform) { on $(platform) {
DEFINES += _BOOT_MODE ; DEFINES += _BOOT_MODE ;
BootMergeObject [ FGristFiles boot_arch_$(TARGET_KERNEL_ARCH).o ] : BootMergeObject [ FGristFiles boot_arch_$(TARGET_KERNEL_ARCH).o ] :
@@ -1,48 +0,0 @@
SubDir HAIKU_TOP src system boot platform u-boot arch arm ;
SubDirHdrs $(HAIKU_TOP) src system boot platform $(TARGET_BOOT_PLATFORM) ;
SubDirHdrs $(HAIKU_TOP) src system boot arch $(TARGET_KERNEL_ARCH_DIR) ;
SubDirHdrs $(HAIKU_TOP) src add-ons kernel bus_managers fdt ;
UseLibraryHeaders [ FDirName libfdt ] ;
UsePrivateSystemHeaders ;
UsePrivateHeaders kernel [ FDirName kernel platform u-boot ] ;
UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_KERNEL_ARCH_DIR) ]
[ FDirName kernel boot platform $(HAIKU_BOOT_PLATFORM) ] ;
SubDirC++Flags -fno-rtti ;
# Things we borrow from the kernel due to lack of bios services
local kernelArchDriverSources =
#arch_uart_8250.cpp
arch_uart_8250_omap.cpp
arch_uart_pl011.cpp
;
BootMergeObject boot_platform_u-boot_arm.o :
# must come first to have _start_* at correct locations
shell.S
# Kernel entry calls
arch_start_kernel.S
# Framebuffer drivers
arch_framebuffer_920.cpp
arch_framebuffer_bcm2835.cpp
arch_framebuffer_omap3.cpp
arch_framebuffer_pxa.cpp
$(kernelArchDriverSources)
# Mailbox drivers
arch_mailbox_bcm2835.cpp
# u-boot mmu setup
arch_mmu.cpp
;
SEARCH on [ FGristFiles $(kernelArchDriverSources) ]
= [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH_DIR) ] ;
#SEARCH on [ FGristFiles arch_cpu_asm.S ]
# = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH_DIR) ] ;
@@ -1,60 +0,0 @@
/*
* Copyright 2011-2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alexander von Gluck IV, [email protected]
*/
#ifndef _ARCH_FRAMEBUFFER_H
#define _ARCH_FRAMEBUFFER_H
#include <boot/platform.h>
#include <SupportDefs.h>
#define TRACE_VIDEO
#ifdef TRACE_VIDEO
# define TRACE(x...) dprintf(x)
# define CALLED() dprintf("%s()\n", __func__);
#else
# define TRACE(x...) ;
# define CALLED() ;
#endif
#define ERROR(x...) dprintf(x)
class ArchFramebuffer {
public:
ArchFramebuffer(addr_t base)
:
fBase(base) {};
~ArchFramebuffer() {};
virtual status_t Init() { return B_OK; };
virtual status_t Probe() { return B_OK; };
virtual status_t SetDefaultMode() { return B_OK; };
virtual status_t SetVideoMode(int width, int height, int depth)
{ return B_OK; };
virtual addr_t Base() { return fBase; };
addr_t PhysicalBase() { return fPhysicalBase; };
size_t Size() { return fSize; };
int Width() { return fCurrentWidth; };
int Height() { return fCurrentHeight; };
int Depth() { return fCurrentDepth; };
int BytesPerRow() { return fCurrentBytesPerRow; };
protected:
addr_t fBase;
phys_addr_t fPhysicalBase;
size_t fSize;
int fCurrentWidth;
int fCurrentHeight;
int fCurrentDepth;
int fCurrentBytesPerRow;
};
#endif /* _ARCH_FRAMEBUFFER_H */
@@ -1,96 +0,0 @@
/*
* Copyright 2009-2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* François Revol, [email protected]
* Alexander von Gluck IV, [email protected]
*/
#include "arch_framebuffer.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 <drivers/driver_settings.h>
class ArchFBArm920 : public ArchFramebuffer {
public:
ArchFBArm920(addr_t base)
: ArchFramebuffer(base) {}
~ArchFBArm920() {}
status_t Init();
status_t Probe();
status_t SetDefaultMode();
status_t SetVideoMode(int width, int height, int depth);
};
extern "C" ArchFramebuffer *arch_get_fb_arm_920(addr_t base)
{
return new ArchFBArm920(base);
}
status_t
ArchFBArm920::Init()
{
gKernelArgs.frame_buffer.enabled = true;
#warning TODO: ARM920 init
return B_OK;
}
status_t
ArchFBArm920::Probe()
{
#if 0
// TODO: More dynamic framebuffer base?
if (!fBase) {
int err = platform_allocate_region(&gFrameBufferBase,
gKernelArgs.frame_buffer.physical_buffer.size, 0, false);
if (err < B_OK)
return err;
gKernelArgs.frame_buffer.physical_buffer.start
= (addr_t)gFrameBufferBase;
dprintf("video framebuffer: %p\n", gFrameBufferBase);
}
#else
gKernelArgs.frame_buffer.physical_buffer.start = fBase;
#endif
gKernelArgs.frame_buffer.depth = 16;
gKernelArgs.frame_buffer.width = 1024;
gKernelArgs.frame_buffer.height = 768;
gKernelArgs.frame_buffer.bytes_per_row = gKernelArgs.frame_buffer.width * 2;
gKernelArgs.frame_buffer.physical_buffer.size
= gKernelArgs.frame_buffer.width
* gKernelArgs.frame_buffer.height
* gKernelArgs.frame_buffer.depth / 8;
dprintf("video mode: %ux%ux%u\n", gKernelArgs.frame_buffer.width,
gKernelArgs.frame_buffer.height, gKernelArgs.frame_buffer.depth);
return B_OK;
}
status_t
ArchFBArm920::SetDefaultMode()
{
return SetVideoMode(gKernelArgs.frame_buffer.width,
gKernelArgs.frame_buffer.height,
gKernelArgs.frame_buffer.depth);
}
status_t
ArchFBArm920::SetVideoMode(int width, int height, int depth)
{
#warning TODO: ArchFBArm920 SetVideoMode
return B_OK;
}
@@ -1,201 +0,0 @@
/*
* Copyright 2012-2015 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz, [email protected]
* François Revol, [email protected]
* Alexander von Gluck IV, [email protected]
*/
#include "arch_framebuffer.h"
#include <arch/arm/bcm283X.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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "arch_mailbox.h"
#include "fdt_support.h"
#include "mmu.h"
//XXX
extern "C" bool
mmu_get_virtual_mapping(addr_t virtualAddress, phys_addr_t *_physicalAddress);
extern "C" ArchMailbox*
arch_get_mailbox_arm_bcm2835(addr_t base);
extern void* gFDT;
struct framebuffer_config {
uint32 width;
uint32 height;
uint32 virtual_width;
uint32 virtual_height;
uint32 bytes_per_row; // from GPU
uint32 bits_per_pixel;
uint32 x_offset;
uint32 y_offset;
uint32 frame_buffer_address; // from GPU
uint32 screen_size; // from GPU
uint16 color_map[256];
};
static framebuffer_config sFramebufferConfig __attribute__((aligned(16)));
class ArchFBArmBCM2835 : public ArchFramebuffer {
public:
ArchFBArmBCM2835(addr_t base)
: ArchFramebuffer(base) {}
~ArchFBArmBCM2835() {}
virtual status_t Init();
virtual status_t Probe();
virtual status_t SetDefaultMode();
virtual status_t SetVideoMode(int width, int height, int depth);
private:
ArchMailbox* fMailbox;
};
extern "C" ArchFramebuffer*
arch_get_fb_arm_bcm2835(addr_t base)
{
return new ArchFBArmBCM2835(base);
}
status_t
ArchFBArmBCM2835::Init()
{
if (!gFDT) {
dprintf("ERROR: FDT access is unavailable!");
return B_ERROR;
}
phys_addr_t mboxBase = fdt_get_device_reg_byname(gFDT, "/axi/mbox");
if (!mboxBase) {
dprintf("ERROR: /axi/mbox is unavailable!");
return B_ERROR;
}
fMailbox = arch_get_mailbox_arm_bcm2835(mboxBase);
if (fMailbox == NULL) {
dprintf("ERROR: Broadcom mailbox is unavailable!");
return B_ERROR;
}
gKernelArgs.frame_buffer.enabled = true;
return B_OK;
}
status_t
ArchFBArmBCM2835::Probe()
{
return B_OK;
}
status_t
ArchFBArmBCM2835::SetDefaultMode()
{
status_t result;
do {
result = SetVideoMode(1920, 1080, 16);
} while (result != B_OK);
return B_OK;
}
status_t
ArchFBArmBCM2835::SetVideoMode(int width, int height, int depth)
{
//debug_assert(((uint32)&sFramebufferConfig & 0x0f) == 0);
sFramebufferConfig.width = width;
sFramebufferConfig.height = height;
sFramebufferConfig.virtual_width = sFramebufferConfig.width;
sFramebufferConfig.virtual_height = sFramebufferConfig.height;
sFramebufferConfig.bytes_per_row = 0; // from GPU
sFramebufferConfig.bits_per_pixel = depth;
sFramebufferConfig.x_offset = 0;
sFramebufferConfig.y_offset = 0;
sFramebufferConfig.frame_buffer_address = 0; // from GPU
sFramebufferConfig.screen_size = 0; // from GPU
if (depth < 16) {
const int colorMapEntries = sizeof(sFramebufferConfig.color_map)
/ sizeof(sFramebufferConfig.color_map[0]);
for (int i = 0; i < colorMapEntries; i++)
sFramebufferConfig.color_map[i] = 0x1111 * i;
}
status_t result = fMailbox->Write(ARM_MAILBOX_CHANNEL_FRAMEBUFFER,
(uint32)&sFramebufferConfig | BCM283X_VIDEO_CORE_L2_COHERENT);
if (result != B_OK)
return result;
uint32 value;
result = fMailbox->Read(ARM_MAILBOX_CHANNEL_FRAMEBUFFER, value);
if (result != B_OK)
return result;
if (value != 0) {
dprintf("failed to configure framebuffer: %" B_PRIx32 "\n", value);
return B_ERROR;
}
if (sFramebufferConfig.frame_buffer_address == 0) {
dprintf("didn't get the framebuffer address\n");
return B_ERROR;
}
//debug_assert(sFramebufferConfig.x_offset == 0
// && sFramebufferConfig.y_offset == 0
// && sFramebufferConfig.width == (uint32)width
// && sFramebufferConfig.height == (uint32)height
// && sFramebufferConfig.virtual_width == sFramebufferConfig.width
// && sFramebufferConfig.virtual_height == sFramebufferConfig.height
// && sFramebufferConfig.bits_per_pixel == (uint32)depth
// && sFramebufferConfig.bytes_per_row
// >= sFramebufferConfig.bits_per_pixel / 8
// * sFramebufferConfig.width
// && sFramebufferConfig.screen_size >= sFramebufferConfig.bytes_per_row
// * sFramebufferConfig.height);
fPhysicalBase
= BCM283X_BUS_TO_PHYSICAL(sFramebufferConfig.frame_buffer_address);
fSize = sFramebufferConfig.screen_size;
fBase = (addr_t)mmu_map_physical_memory(fPhysicalBase, fSize, kDefaultPageFlags);
dprintf("video framebuffer: va: %p pa: %p\n", (void *)fBase,
(void *)fPhysicalBase);
fCurrentWidth = width;
fCurrentHeight = height;
fCurrentDepth = depth;
fCurrentBytesPerRow = sFramebufferConfig.bytes_per_row;
gKernelArgs.frame_buffer.physical_buffer.start = (addr_t)fPhysicalBase;
return B_OK;
}
@@ -1,383 +0,0 @@
/*
* Copyright 2009-2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* François Revol, [email protected]
* Alexander von Gluck IV, [email protected]
*/
#include "arch_framebuffer.h"
#include <arch/arm/omap3.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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "graphics/omap/omap3_regs.h"
//XXX
extern "C" addr_t mmu_map_physical_memory(addr_t physicalAddress, size_t size,
uint32 flags);
extern "C" bool
mmu_get_virtual_mapping(addr_t virtualAddress, phys_addr_t *_physicalAddress);
#define write_io_32(a, v) ((*(vuint32 *)a) = v)
#define read_io_32(a) (*(vuint32 *)a)
#define dumpr(a) dprintf("LCC:%s:0x%lx\n", #a, read_io_32(a))
class ArchFBArmOmap3 : public ArchFramebuffer {
public:
ArchFBArmOmap3(addr_t base)
: ArchFramebuffer(base) {}
~ArchFBArmOmap3() {}
status_t Init();
status_t Probe();
status_t SetDefaultMode();
status_t SetVideoMode(int width, int height, int depth);
};
extern "C" ArchFramebuffer *arch_get_fb_arm_omap3(addr_t base)
{
return new ArchFBArmOmap3(base);
}
// #pragma mark -
struct video_mode {
short width, height;
const char *name;
uint32 dispc_timing_h;
uint32 dispc_timing_v;
uint32 dispc_divisor;
uint32 dss_divisor;
};
// Master clock (PLL4) is 864 Mhz, and changing it is a pita since it
// cascades to other devices.
// Pixel clock is 864 / cm_clksel_dss.dss1_alwan_fclk / dispc_divisor.divisor.pcd
// So most of these modes are just approximate (1280x1024 is correct)
// List must be in ascending order.
struct video_mode modes[] = {
{
640, 480, "640x480-71",
(128 << DISPCB_HBP) | (24 << DISPCB_HFP) | (40 << DISPCB_HSW),
(28 << DISPCB_VBP) | (9 << DISPCB_VFP) | (3 << DISPCB_VSW),
2, 14
},
{
800, 600, "800x600-59",
(88 << DISPCB_HBP) | (40 << DISPCB_HFP) | (128 << DISPCB_HSW),
(23 << DISPCB_VBP) | (1 << DISPCB_VFP) | (4 << DISPCB_VSW),
2, 11
},
{
1024, 768, "1024x768-61",
(160 << DISPCB_HBP) | (24 << DISPCB_HFP) | (136 << DISPCB_HSW),
(29 << DISPCB_VBP) | (3 << DISPCB_VFP) | (6 << DISPCB_VSW),
1, 13
},
{
1280, 1024, "1280x1024-60",
(248 << DISPCB_HBP) | (48 << DISPCB_HFP) | (112 << DISPCB_HSW),
(38 << DISPCB_VBP) | (1 << DISPCB_VFP) | (3 << DISPCB_VSW),
1, 8
},
};
static inline void
setaddr(uint32 reg, unsigned int v)
{
*((volatile uint32 *)(reg)) = v;
}
static inline void
modaddr(unsigned int reg, unsigned int m, unsigned int v)
{
uint32 o;
o = *((volatile uint32 *)(reg));
o &= ~m;
o |= v;
*((volatile uint32 *)(reg)) = o;
}
static inline
void setreg(uint32 base, unsigned int reg, unsigned int v)
{
*((volatile uint32 *)(base + reg)) = v;
}
static inline
uint32 readreg(uint32 base, unsigned int reg)
{
return *((volatile uint32 *)(base + reg));
}
static inline void
modreg(uint32 base, unsigned int reg, unsigned int m, unsigned int v)
{
uint32 o;
o = *((volatile uint32 *)(base + reg));
o &= ~m;
o |= v;
*((volatile uint32 *)(base + reg)) = o;
}
// init beagle gpio for video
static void
omap_beagle_init(void)
{
// setup GPIO stuff, i can't find any references to these
setreg(GPIO1_BASE, GPIO_OE, 0xfefffedf);
setreg(GPIO1_BASE, GPIO_SETDATAOUT, 0x01000120);
// DVI-D is enabled by GPIO 170?
}
static void
omap_clock_init(void)
{
// sets pixel clock to 72MHz
// sys_clk = 26.0 Mhz
// DPLL4 = sys_clk * 432 / 13 = 864
// DSS1_ALWON_FCLK = 864 / 6 = 144
// Pixel clock (DISPC_DIVISOR) = 144 / 2 = 72Mhz
// and also VENC clock = 864 / 16 = 54MHz
// The clock multiplier/divider cannot be changed
// without affecting other system clocks - do don't.
// pll4 clock multiplier/divider
setaddr(CM_CLKSEL2_PLL, (432 << 8) | 12);
// tv clock divider, dss1 alwon fclk divider
setaddr(CM_CLKSEL_DSS, (16 << 8) | 6);
// core/peripheral PLL to 1MHz
setaddr(CM_CLKEN_PLL, 0x00370037);
}
static void
omap_dss_init(void)
{
setreg(DSS_BASE, DSS_SYSCONFIG, DSS_AUTOIDLE);
// Select DSS1 ALWON as clock source
setreg(DSS_BASE, DSS_CONTROL, DSS_VENC_OUT_SEL | DSS_DAC_POWERDN_BGZ
| DSS_DAC_DEMEN | DSS_VENC_CLOCK_4X_ENABLE);
}
static void
omap_dispc_init(void)
{
uint32 DISPC = DISPC_BASE;
setreg(DISPC, DISPC_SYSCONFIG,
DISPC_MIDLEMODE_SMART
| DISPC_SIDLEMODE_SMART
| DISPC_ENWAKEUP
| DISPC_AUTOIDLE);
setreg(DISPC, DISPC_CONFIG, DISPC_LOADMODE_FRAME);
// LCD default colour = black
setreg(DISPC, DISPC_DEFAULT_COLOR0, 0x000000);
setreg(DISPC, DISPC_POL_FREQ,
DISPC_POL_IPC
| DISPC_POL_IHS
| DISPC_POL_IVS
| (2<<DISPCB_POL_ACBI)
| (8<<DISPCB_POL_ACB));
// Set pixel clock divisor = 2
setreg(DISPC, DISPC_DIVISOR,
(1<<DISPCB_DIVISOR_LCD)
| (2<<DISPCB_DIVISOR_PCD));
// Disable graphical output
setreg(DISPC, DISPC_GFX_ATTRIBUTES, 0);
// Turn on the LCD output
setreg(DISPC, DISPC_CONTROL,
DISPC_GPOUT1
| DISPC_GPOUT0
| DISPC_TFTDATALINES_24
| DISPC_STDITHERENABLE
| DISPC_GOLCD
| DISPC_STNTFT
| DISPC_LCDENABLE
);
while ((readreg(DISPC, DISPC_CONTROL) & DISPC_GOLCD))
;
}
static void
omap_set_lcd_mode(int w, int h)
{
uint32 DISPC = DISPC_BASE;
unsigned int i;
struct video_mode *m;
dprintf("omap3: set_lcd_mode %d,%d\n", w, h);
for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) {
if (w <= modes[i].width
&& h <= modes[i].height)
goto found;
}
i -= 1;
found:
m = &modes[i];
dprintf("omap3: found mode[%s]\n", m->name);
setreg(DISPC, DISPC_SIZE_LCD, (m->width - 1) | ((m->height - 1) << 16));
setreg(DISPC, DISPC_TIMING_H, m->dispc_timing_h);
setreg(DISPC, DISPC_TIMING_V, m->dispc_timing_v);
modreg(DISPC, DISPC_DIVISOR, 0xffff, m->dispc_divisor);
modaddr(CM_CLKSEL_DSS, 0x3f, m->dss_divisor);
// Tell hardware to update, and wait for it
modreg(DISPC, DISPC_CONTROL,
DISPC_GOLCD,
DISPC_GOLCD);
while ((readreg(DISPC, DISPC_CONTROL) & DISPC_GOLCD))
;
}
static void
omap_attach_framebuffer(addr_t data, int width, int height, int depth)
{
uint32 DISPC = DISPC_BASE;
uint32 gsize = ((height - 1) << 16) | (width - 1);
dprintf("omap3: attach bitmap (%d,%d) to screen\n", width, height);
setreg(DISPC, DISPC_GFX_BA0, (uint32)data);
setreg(DISPC, DISPC_GFX_BA1, (uint32)data);
setreg(DISPC, DISPC_GFX_POSITION, 0);
setreg(DISPC, DISPC_GFX_SIZE, gsize);
setreg(DISPC, DISPC_GFX_FIFO_THRESHOLD, (0x3ff << 16) | 0x3c0);
setreg(DISPC, DISPC_GFX_ROW_INC, 1);
setreg(DISPC, DISPC_GFX_PIXEL_INC, 1);
setreg(DISPC, DISPC_GFX_WINDOW_SKIP, 0);
setreg(DISPC, DISPC_GFX_ATTRIBUTES, DISPC_GFXFORMAT_RGB16
| DISPC_GFXBURSTSIZE_16x32 | DISPC_GFXENABLE);
// Tell hardware to update, and wait for it
modreg(DISPC, DISPC_CONTROL, DISPC_GOLCD, DISPC_GOLCD);
while ((readreg(DISPC, DISPC_CONTROL) & DISPC_GOLCD))
;
}
status_t
ArchFBArmOmap3::Init()
{
gKernelArgs.frame_buffer.enabled = true;
setreg(DISPC_BASE, DISPC_IRQENABLE, 0x00000);
setreg(DISPC_BASE, DISPC_IRQSTATUS, 0x1ffff);
omap_beagle_init();
omap_clock_init();
omap_dss_init();
omap_dispc_init();
return B_OK;
}
status_t
ArchFBArmOmap3::Probe()
{
gKernelArgs.frame_buffer.depth = 16;
gKernelArgs.frame_buffer.width = 1024;
gKernelArgs.frame_buffer.height = 768;
gKernelArgs.frame_buffer.bytes_per_row = gKernelArgs.frame_buffer.width * 2;
gKernelArgs.frame_buffer.physical_buffer.size
= gKernelArgs.frame_buffer.width
* gKernelArgs.frame_buffer.height
* gKernelArgs.frame_buffer.depth / 8;
#if 1
//dprintf("fBase %p\n", (void *)fBase);
if (!fBase || true) {
fBase = 0;
int err = platform_allocate_region((void **)&fBase,
gKernelArgs.frame_buffer.physical_buffer.size, 0, false);
if (err < B_OK) return err;
if (!mmu_get_virtual_mapping(fBase, &fPhysicalBase))
return B_ERROR;
gKernelArgs.frame_buffer.physical_buffer.start
= (addr_t)fPhysicalBase;
dprintf("video framebuffer: va: %p pa: %p\n", (void *)fBase,
(void *)fPhysicalBase);
}
#else
// TODO: More dynamic framebuffer base?
fPhysicalBase = fBase;
gKernelArgs.frame_buffer.physical_buffer.start = fPhysicalBase;
#endif
TRACE("video mode: %ux%ux%u\n", gKernelArgs.frame_buffer.width,
gKernelArgs.frame_buffer.height, gKernelArgs.frame_buffer.depth);
return B_OK;
}
status_t
ArchFBArmOmap3::SetVideoMode(int width, int height, int depth)
{
TRACE("%s: %dx%d@%d\n", __func__, width, height, depth);
omap_set_lcd_mode(width, height);
omap_attach_framebuffer(fPhysicalBase, width, height, depth);
return B_OK;
}
status_t
ArchFBArmOmap3::SetDefaultMode()
{
CALLED();
return SetVideoMode(gKernelArgs.frame_buffer.width,
gKernelArgs.frame_buffer.height,
gKernelArgs.frame_buffer.depth);
}
@@ -1,230 +0,0 @@
/*
* Copyright 2009-2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* François Revol, [email protected]
* Alexander von Gluck IV, [email protected]
*/
#include "arch_framebuffer.h"
#include <arch/arm/pxa270.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 <stdio.h>
#include <stdlib.h>
#include <string.h>
//XXX
extern "C" addr_t mmu_map_physical_memory(addr_t physicalAddress, size_t size,
uint32 flags);
class ArchFBArmPxa270 : public ArchFramebuffer {
public:
ArchFBArmPxa270(addr_t base)
: ArchFramebuffer(base) {}
~ArchFBArmPxa270() {}
status_t Init();
status_t Probe();
status_t SetDefaultMode();
status_t SetVideoMode(int width, int height, int depth);
};
extern "C" ArchFramebuffer *arch_get_fb_arm_pxa270(addr_t base)
{
return new ArchFBArmPxa270(base);
}
// #pragma mark -
#define write_io_32(a, v) ((*(vuint32 *)a) = v)
#define read_io_32(a) (*(vuint32 *)a)
#define dumpr(a) dprintf("LCC:%s:0x%lx\n", #a, read_io_32(a))
static struct pxa27x_lcd_dma_descriptor sVideoDMADesc;
static uint32 scratch[128] __attribute__((aligned(16)));
status_t
ArchFBArmPxa270::Init()
{
gKernelArgs.frame_buffer.enabled = true;
return B_OK;
}
status_t
ArchFBArmPxa270::Probe()
{
CALLED();
#if 0
// TODO: More dynamic framebuffer base?
if (!fBase) {
// XXX: realloc if larger !!!
err = platform_allocate_region(&gFrameBufferBase, fbSize, 0, false);
dprintf("error %08x\n", err);
if (err < B_OK)
return err;
gKernelArgs.frame_buffer.physical_buffer.start
= (addr_t)gFrameBufferBase;
/*
gFrameBufferBase = (void *)mmu_map_physical_memory(
0xa8000000, fbSize, 0);
if (gFrameBufferBase == NULL)
return B_NO_MEMORY;
gKernelArgs.frame_buffer.physical_buffer.start
= (addr_t)gFrameBufferBase; // 0xa8000000;
*/
}
#else
gKernelArgs.frame_buffer.physical_buffer.start = fBase;
#endif
uint32 bppCode;
uint32 pixelFormat;
struct pxa27x_lcd_dma_descriptor *dma;
// check if LCD controller is enabled
if (!(read_io_32(LCCR0) & 0x00000001)) {
// not enabled, so return suggested mode
gKernelArgs.frame_buffer.depth = 32;
gKernelArgs.frame_buffer.width = 640;
gKernelArgs.frame_buffer.height = 480;
return B_NO_INIT;
}
pixelFormat = bppCode = read_io_32(LCCR3);
bppCode = ((bppCode >> 26) & 0x08) | ((bppCode >> 24) & 0x07);
pixelFormat >>= 30;
dma = (struct pxa27x_lcd_dma_descriptor *)(read_io_32(FDADR0) & ~0x0f);
if (!dma)
return B_ERROR;
switch (bppCode) {
case 2:
gKernelArgs.frame_buffer.depth = 4;
break;
case 3:
gKernelArgs.frame_buffer.depth = 8;
break;
case 4:
gKernelArgs.frame_buffer.depth = 16;
break;
case 9:
case 10:
gKernelArgs.frame_buffer.depth = 32; // RGB888
break;
default:
return B_ERROR;
}
gKernelArgs.frame_buffer.physical_buffer.start = (dma->fsadr & ~0x0f);
gKernelArgs.frame_buffer.width = (read_io_32(LCCR1) & ((1 << 10) - 1)) + 1;
gKernelArgs.frame_buffer.height = (read_io_32(LCCR2) & ((1 << 10) - 1)) + 1;
gKernelArgs.frame_buffer.bytes_per_row = gKernelArgs.frame_buffer.width
* sizeof(uint32);
gKernelArgs.frame_buffer.physical_buffer.size
= gKernelArgs.frame_buffer.width
* gKernelArgs.frame_buffer.height
* gKernelArgs.frame_buffer.depth / 8;
dprintf("video mode: %ux%ux%u\n", gKernelArgs.frame_buffer.width,
gKernelArgs.frame_buffer.height, gKernelArgs.frame_buffer.depth);
return B_OK;
}
status_t
ArchFBArmPxa270::SetVideoMode(int width, int height, int depth)
{
dprintf("%s(%d, %d, %d)\n", __FUNCTION__, width, height, depth);
void *fb;
uint32 fbSize = width * height * depth / 8;
fb = (void*)fBase;
dprintf("fb @ %p\n", fb);
sVideoDMADesc.fdadr = ((uint32)&sVideoDMADesc & ~0x0f) | 0x01;
sVideoDMADesc.fsadr = (uint32)(fb) & ~0x0f;
sVideoDMADesc.fidr = 0;
sVideoDMADesc.ldcmd = fbSize;
// if not already enabled, set a default mode
if (!(read_io_32(LCCR0) & 0x00000001)) {
int bpp;
int pdfor;
dprintf("Setting video mode\n");
switch (depth) {
case 4:
bpp = 2;
break;
case 8:
bpp = 3;
break;
case 16:
bpp = 3;
break;
case 32:
bpp = 9;
pdfor = 0x3;
break;
default:
return EINVAL;
}
write_io_32(LCCR1, (0 << 0) | (width - 1));
write_io_32(LCCR2, (0 << 0) | (height - 1));
write_io_32(LCCR3, (pdfor << 30) | ((bpp >> 3) << 29)
| ((bpp & 0x07) << 24));
write_io_32(FDADR0, sVideoDMADesc.fdadr);
write_io_32(LCCR0, read_io_32(LCCR0) | 0x01800001); // no ints +ENB
write_io_32(FBR0, sVideoDMADesc.fdadr);
dumpr(LCCR0);
dumpr(LCCR1);
dumpr(LCCR2);
dumpr(LCCR3);
dumpr(LCCR4);
} else
return B_OK; // assume we're already setup
// clear the video memory
memset((void *)fb, 0, fbSize);
// XXX test pattern
for (int i = 0; i < 128; i++) {
((uint32 *)fb)[i + 16] = 0x000000ff << ((i%4) * 8);
scratch[i] = 0x000000ff << ((i%4) * 8);
}
// update framebuffer descriptor
return Probe();
}
status_t
ArchFBArmPxa270::SetDefaultMode()
{
CALLED();
return SetVideoMode(gKernelArgs.frame_buffer.width,
gKernelArgs.frame_buffer.height,
gKernelArgs.frame_buffer.depth);
}
@@ -1,50 +0,0 @@
/*
* Copyright 2011-2015 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alexander von Gluck IV, [email protected]
*/
#ifndef _ARCH_MAILBOX_H
#define _ARCH_MAILBOX_H
#include <boot/platform.h>
#include <SupportDefs.h>
#define TRACE_MAILBOX
#ifdef TRACE_MAILBOX
# define TRACE(x...) dprintf(x)
# define CALLED() dprintf("%s()\n", __func__);
#else
# define TRACE(x...) ;
# define CALLED() ;
#endif
#define ERROR(x...) dprintf(x)
class ArchMailbox {
public:
ArchMailbox(addr_t base)
:
fBase(base) {};
~ArchMailbox() {};
virtual status_t Init() { return B_OK; };
virtual status_t Probe() { return B_OK; };
virtual addr_t Base() { return fBase; };
addr_t PhysicalBase() { return fPhysicalBase; };
virtual status_t Write(uint8 channel, uint32 value) { return B_OK; };
virtual status_t Read(uint8 channel, uint32& value) { return B_OK; };
protected:
addr_t fBase;
addr_t fPhysicalBase;
};
#endif /* _ARCH_MAILBOX_H */
@@ -1,98 +0,0 @@
/*
* Copyright 2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz, [email protected]
* François Revol, [email protected]
* Alexander von Gluck IV, [email protected]
*/
#include "arch_mailbox.h"
#include <atomic>
#include <arch/arm/bcm283X.h>
#include "arch_cpu.h"
class ArchMailboxArmBCM2835 final : public ArchMailbox {
public:
ArchMailboxArmBCM2835(addr_t base)
:
ArchMailbox(base) {}
~ArchMailboxArmBCM2835() {}
virtual status_t Write(uint8 channel, uint32 value) override;
virtual status_t Read(uint8 channel, uint32& value) override;
private:
auto& GetRegister(unsigned reg);
void RegisterWrite(addr_t reg, uint32 value);
uint32 RegisterRead(addr_t reg);
};
extern "C" ArchMailbox*
arch_get_mailbox_arm_bcm2835(addr_t base)
{
return new ArchMailboxArmBCM2835(base);
}
status_t
ArchMailboxArmBCM2835::Write(uint8 channel, uint32 value)
{
// We have to wait for the mailbox to drain if it is marked full.
while ((RegisterRead(ARM_MAILBOX_STATUS) & ARM_MAILBOX_FULL) != 0)
;
value &= ARM_MAILBOX_DATA_MASK;
RegisterWrite(ARM_MAILBOX_WRITE, value | channel);
return B_OK;
}
status_t
ArchMailboxArmBCM2835::Read(uint8 channel, uint32& value)
{
while (true) {
// Wait for something to arrive in the mailbox.
if ((RegisterRead(ARM_MAILBOX_STATUS) & ARM_MAILBOX_EMPTY) != 0)
continue;
value = RegisterRead(ARM_MAILBOX_READ);
if ((value & ARM_MAILBOX_CHANNEL_MASK) != channel) {
// Not for us, retry.
continue;
}
break;
}
value &= ARM_MAILBOX_DATA_MASK;
return B_OK;
}
inline auto&
ArchMailboxArmBCM2835::GetRegister(unsigned reg)
{
auto addr = fBase + reg;
return *reinterpret_cast<std::atomic<uint32_t>*>(addr);
}
inline uint32
ArchMailboxArmBCM2835::RegisterRead(addr_t reg)
{
return GetRegister(reg).load(std::memory_order_acquire);
}
inline void
ArchMailboxArmBCM2835::RegisterWrite(addr_t reg, uint32 value)
{
GetRegister(reg).store(value, std::memory_order_release);
}
@@ -1,816 +0,0 @@
/*
* Copyright 2004-2008, Axel Dörfler, [email protected].
* 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 <arm_mmu.h>
#include <kernel.h>
#include <OS.h>
#include <string.h>
#include "fdt_support.h"
extern "C" {
#include <fdt.h>
#include <libfdt.h>
#include <libfdt_env.h>
};
#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.
/*
TODO:
-recycle bit!
*/
/*! The (physical) memory layout of the boot loader is currently as follows:
0x00000000 u-boot (run from NOR flash)
0xa0000000 u-boot stuff like kernel arguments afaik
0xa0100000 - 0xa0ffffff boot.tgz (up to 15MB probably never needed so big...)
0xa1000000 - 0xa1ffffff pagetables
0xa2000000 - ? code (up to 1MB)
0xa2100000 boot loader heap / free physical memory
The kernel is mapped at KERNEL_LOAD_BASE, 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).
*/
// 8 MB for the kernel, kernel args, modules, driver settings, ...
static const size_t kMaxKernelSize = 0x800000;
// Start and end of ourselfs (from ld script)
extern int _start, _end;
/*
*defines a block in memory
*/
struct memblock {
const char name[16];
// the name will be used for debugging etc later perhaps...
addr_t start;
// start of the block
addr_t end;
// end of the block
uint32 flags;
// which flags should be applied (device/normal etc..)
};
static struct memblock LOADER_MEMORYMAP[] = {
{
"RAM_kernel", // 8MB space for kernel, drivers etc
KERNEL_LOAD_BASE,
KERNEL_LOAD_BASE + kMaxKernelSize - 1,
ARM_MMU_L2_FLAG_C,
},
#ifdef FB_BASE
{
"framebuffer", // 2MB framebuffer ram
FB_BASE,
FB_BASE + FB_SIZE - 1,
ARM_MMU_L2_FLAG_AP_RW | ARM_MMU_L2_FLAG_C,
},
#endif
};
//static const uint32 kDefaultPageTableFlags = MMU_FLAG_READWRITE;
// not cached not buffered, R/W
static addr_t sNextPhysicalAddress = 0; //will be set by mmu_init
static addr_t sNextVirtualAddress = 0;
static addr_t sNextPageTableAddress = 0;
//the page directory is in front of the pagetable
static uint32 sPageTableRegionEnd = 0;
static uint32 sSmallPageType = ARM_MMU_L2_TYPE_SMALLEXT;
// working page directory and page table
static uint32 *sPageDirectory = 0 ;
//page directory has to be on a multiple of 16MB for
//some arm processors
static addr_t
get_next_virtual_address_aligned(size_t size, uint32 mask)
{
addr_t address = (sNextVirtualAddress) & mask;
sNextVirtualAddress = address + size;
return address;
}
static addr_t
get_next_physical_address_aligned(size_t size, uint32 mask)
{
addr_t address = sNextPhysicalAddress & mask;
sNextPhysicalAddress = address + size;
return address;
}
static addr_t
get_next_virtual_page(size_t pagesize)
{
return get_next_virtual_address_aligned(pagesize, 0xffffffc0);
}
static addr_t
get_next_physical_page(size_t pagesize)
{
return get_next_physical_address_aligned(pagesize, 0xffffffc0);
}
/*
* Set translation table base
*/
void
mmu_set_TTBR(uint32 ttb)
{
ttb &= 0xffffc000;
asm volatile("MCR p15, 0, %[adr], c2, c0, 0"::[adr] "r" (ttb));
}
/*
* Flush the TLB
*/
void
mmu_flush_TLB()
{
uint32 value = 0;
asm volatile("MCR p15, 0, %[c8format], c8, c7, 0"::[c8format] "r" (value));
}
/*
* Read MMU Control Register
*/
uint32
mmu_read_C1()
{
uint32 controlReg = 0;
asm volatile("MRC p15, 0, %[c1out], c1, c0, 0":[c1out] "=r" (controlReg));
return controlReg;
}
/*
* Write MMU Control Register
*/
void
mmu_write_C1(uint32 value)
{
asm volatile("MCR p15, 0, %[c1in], c1, c0, 0"::[c1in] "r" (value));
}
/*
* Dump current MMU Control Register state
* For debugging, can be added to loader temporarly post-serial-init
*/
void
mmu_dump_C1()
{
uint32 cpValue = mmu_read_C1();
dprintf("MMU CP15:c1 State:\n");
if ((cpValue & (1 << 0)) != 0)
dprintf(" - MMU Enabled\n");
else
dprintf(" - MMU Disabled\n");
if ((cpValue & (1 << 2)) != 0)
dprintf(" - Data Cache Enabled\n");
else
dprintf(" - Data Cache Disabled\n");
if ((cpValue & (1 << 3)) != 0)
dprintf(" - Write Buffer Enabled\n");
else
dprintf(" - Write Buffer Disabled\n");
if ((cpValue & (1 << 12)) != 0)
dprintf(" - Instruction Cache Enabled\n");
else
dprintf(" - Instruction Cache Disabled\n");
if ((cpValue & (1 << 13)) != 0)
dprintf(" - Vector Table @ 0xFFFF0000\n");
else
dprintf(" - Vector Table @ 0x00000000\n");
}
void
mmu_write_DACR(uint32 value)
{
asm volatile("MCR p15, 0, %[c1in], c3, c0, 0"::[c1in] "r" (value));
}
static uint32 *
get_next_page_table(uint32 type)
{
TRACE(("get_next_page_table, sNextPageTableAddress 0x%" B_PRIxADDR
", sPageTableRegionEnd 0x%" B_PRIxADDR ", type 0x%" B_PRIx32 "\n",
sNextPageTableAddress, sPageTableRegionEnd, type));
size_t size = 0;
size_t entryCount = 0;
switch (type) {
case ARM_MMU_L1_TYPE_COARSE:
size = ARM_MMU_L2_COARSE_TABLE_SIZE;
entryCount = ARM_MMU_L2_COARSE_ENTRY_COUNT;
break;
case ARM_MMU_L1_TYPE_FINE:
size = ARM_MMU_L2_FINE_TABLE_SIZE;
entryCount = ARM_MMU_L2_FINE_ENTRY_COUNT;
break;
default:
panic("asked for unknown page table type: %#" B_PRIx32 "\n", type);
return NULL;
}
addr_t address = sNextPageTableAddress;
if (address < sPageTableRegionEnd)
sNextPageTableAddress += size;
else {
TRACE(("page table allocation outside of pagetable region!\n"));
address = get_next_physical_address_aligned(size, 0xffffffc0);
}
uint32 *pageTable = (uint32 *)address;
for (size_t i = 0; i < entryCount; i++)
pageTable[i] = 0;
return pageTable;
}
static uint32 *
get_or_create_page_table(addr_t address, uint32 type)
{
uint32 *pageTable = NULL;
uint32 pageDirectoryIndex = VADDR_TO_PDENT(address);
uint32 pageDirectoryEntry = sPageDirectory[pageDirectoryIndex];
uint32 entryType = pageDirectoryEntry & ARM_PDE_TYPE_MASK;
if (entryType == ARM_MMU_L1_TYPE_FAULT) {
// This page directory entry has not been set yet, allocate it.
pageTable = get_next_page_table(type);
sPageDirectory[pageDirectoryIndex] = (uint32)pageTable | type;
return pageTable;
}
if (entryType != type) {
// This entry has been allocated with a different type!
panic("tried to reuse page directory entry %" B_PRIu32
" with different type (entry: %#" B_PRIx32 ", new type: %#" B_PRIx32
")\n", pageDirectoryIndex, pageDirectoryEntry, type);
return NULL;
}
return (uint32 *)(pageDirectoryEntry & ARM_PDE_ADDRESS_MASK);
}
static void
mmu_map_identity(addr_t start, size_t end, int flags)
{
uint32 *pageTable = NULL;
uint32 pageTableIndex = 0;
start = ROUNDDOWN(start, B_PAGE_SIZE);
end = ROUNDUP(end, B_PAGE_SIZE);
TRACE(("mmu_map_identity: [ %" B_PRIxADDR " - %" B_PRIxADDR "]\n", start, end));
for (addr_t address = start; address < end; address += B_PAGE_SIZE) {
if (pageTable == NULL
|| pageTableIndex >= ARM_MMU_L2_COARSE_ENTRY_COUNT) {
pageTable = get_or_create_page_table(address,
ARM_MMU_L1_TYPE_COARSE);
pageTableIndex = VADDR_TO_PTENT(address);
}
pageTable[pageTableIndex++]
= address | flags | sSmallPageType;
}
}
static void
map_pages_loader()
{
for (uint32 i = 0; i < B_COUNT_OF(LOADER_MEMORYMAP); i++) {
TRACE(("BLOCK: %s START: %lx END %lx\n", LOADER_MEMORYMAP[i].name,
LOADER_MEMORYMAP[i].start, LOADER_MEMORYMAP[i].end));
addr_t address = LOADER_MEMORYMAP[i].start;
ASSERT((address & ~ARM_PTE_ADDRESS_MASK) == 0);
mmu_map_identity(LOADER_MEMORYMAP[i].start, LOADER_MEMORYMAP[i].end,
LOADER_MEMORYMAP[i].flags);
}
}
//TODO:move this to generic/ ?
static status_t
fdt_map_memory_ranges(void* fdt, const char* path, bool physical = false)
{
int node;
const void *prop;
int len;
uint64 total;
dprintf("checking FDT for %s...\n", path);
node = fdt_path_offset(fdt, path);
total = 0;
int32 regAddressCells = 1;
int32 regSizeCells = 1;
fdt_get_cell_count(fdt, node, regAddressCells, regSizeCells);
prop = fdt_getprop(fdt, node, "reg", &len);
if (prop == NULL) {
dprintf("Unable to locate %s in FDT!\n", path);
return B_ERROR;
}
const uint32 *p = (const uint32 *)prop;
for (int32 i = 0; len; i++) {
uint64 base;
uint64 size;
if (regAddressCells == 2)
base = fdt64_to_cpu(*(uint64_t *)p);
else
base = fdt32_to_cpu(*(uint32_t *)p);
p += regAddressCells;
if (regSizeCells == 2)
size = fdt64_to_cpu(*(uint64_t *)p);
else
size = fdt32_to_cpu(*(uint32_t *)p);
p += regSizeCells;
len -= sizeof(uint32) * (regAddressCells + regSizeCells);
if (size <= 0) {
dprintf("%ld: empty region\n", i);
continue;
}
dprintf("%" B_PRIu32 ": base = %" B_PRIu64 ","
"size = %" B_PRIu64 "\n", i, base, size);
total += size;
if (physical) {
if (insert_physical_memory_range(base, size) != B_OK) {
dprintf("cannot map physical memory range "
"(num ranges = %" B_PRIu32 ")!\n",
gKernelArgs.num_physical_memory_ranges);
return B_ERROR;
}
} else {
mmu_map_identity(base, base + size, ARM_MMU_L2_FLAG_B);
}
}
dprintf("total '%s' physical memory = %" B_PRId64 "MB\n", path,
total / (1024 * 1024));
return B_OK;
}
static void
fdt_map_peripheral(void* fdt)
{
if (fdt == NULL) {
dprintf("Invalid FDT provided to %s!", __func__);
return;
}
// map peripheral devices (such as uart) from fdt
#warning Map peripherals from the fdt we want to use in the bootloader!
// this assumes /pl011@9000000 which is the qemu virt uart
fdt_map_memory_ranges(fdt, "/pl011@9000000");
// this assumes /axi which is broadcom!
fdt_map_memory_ranges(fdt, "/axi");
}
static void
init_page_directory(void* fdt)
{
TRACE(("init_page_directory\n"));
gKernelArgs.arch_args.phys_pgdir =
gKernelArgs.arch_args.vir_pgdir = (uint32)sPageDirectory;
// clear out the page directory
for (uint32 i = 0; i < ARM_MMU_L1_TABLE_ENTRY_COUNT; i++)
sPageDirectory[i] = 0;
// map ourselfs first... just to make sure
mmu_map_identity((addr_t)&_start, (addr_t)&_end, ARM_MMU_L2_FLAG_C);
// map our page directory region (TODO should not be identity mapped)
mmu_map_identity((addr_t)sPageDirectory, sPageTableRegionEnd, ARM_MMU_L2_FLAG_C);
// map our well known / static pages
map_pages_loader();
// map our fdt peripherals
fdt_map_peripheral(fdt);
mmu_flush_TLB();
/* set up the translation table base */
mmu_set_TTBR((uint32)sPageDirectory);
mmu_flush_TLB();
/* set up the domain access register */
mmu_write_DACR(0xFFFFFFFF);
/* turn on the mmu */
mmu_write_C1(mmu_read_C1() | 0x1);
}
/*! 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_LOAD_BASE) {
panic("map_page: asked to map invalid page %p!\n",
(void *)virtualAddress);
}
physicalAddress &= ~(B_PAGE_SIZE - 1);
// map the page to the correct page table
uint32 *pageTable = get_or_create_page_table(virtualAddress,
ARM_MMU_L1_TYPE_COARSE);
uint32 pageTableIndex = VADDR_TO_PTENT(virtualAddress);
TRACE(("map_page: inserting pageTable %p, tableEntry 0x%" B_PRIx32
", physicalAddress 0x%" B_PRIxADDR "\n", pageTable, pageTableIndex,
physicalAddress));
pageTable[pageTableIndex] = physicalAddress | flags;
mmu_flush_TLB();
TRACE(("map_page: done\n"));
}
// #pragma mark -
extern "C" addr_t
mmu_map_physical_memory(addr_t physicalAddress, size_t size, uint32 flags)
{
TRACE(("mmu_map_physical_memory(phAddr=%lx, %lx, %lu)\n", physicalAddress, size, flags));
addr_t address = sNextVirtualAddress;
addr_t pageOffset = physicalAddress & (B_PAGE_SIZE - 1);
physicalAddress -= pageOffset;
if (pageOffset)
size += B_PAGE_SIZE;
for (addr_t offset = 0; offset < size; offset += B_PAGE_SIZE) {
map_page(get_next_virtual_page(B_PAGE_SIZE), physicalAddress + offset,
flags);
}
return address + pageOffset;
}
static void
unmap_page(addr_t virtualAddress)
{
TRACE(("unmap_page(virtualAddress = %p)\n", (void *)virtualAddress));
if (virtualAddress < KERNEL_LOAD_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[VADDR_TO_PDENT(virtualAddress)]
& ARM_PDE_ADDRESS_MASK);
pageTable[VADDR_TO_PTENT(virtualAddress)] = 0;
mmu_flush_TLB();
}
// XXX: use phys_addr_t ?
extern "C" bool
mmu_get_virtual_mapping(addr_t virtualAddress, /*phys_*/addr_t *_physicalAddress)
{
if (virtualAddress < KERNEL_LOAD_BASE) {
panic("mmu_get_virtual_mapping: asked to lookup invalid page %p!\n",
(void *)virtualAddress);
return false;
}
// map the page to the correct page table
uint32 *pageTable = get_or_create_page_table(virtualAddress,
ARM_MMU_L1_TYPE_COARSE);
uint32 pageTableIndex = VADDR_TO_PTENT(virtualAddress);
*_physicalAddress = pageTable[pageTableIndex] & ~(B_PAGE_SIZE - 1);
return true;
}
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_LOAD_BASE || address + size * B_PAGE_SIZE
>= KERNEL_LOAD_BASE + kMaxKernelSize) {
TRACE(("mmu_allocate in illegal range\n address: %" B_PRIx32
" KERNELBASE: %" B_PRIx32 " KERNEL_LOAD_BASE + kMaxKernelSize:"
" %" B_PRIx32 " address + size : %" B_PRIx32 "\n",
(uint32)address, (uint32)KERNEL_LOAD_BASE,
(uint32)KERNEL_LOAD_BASE + kMaxKernelSize,
(uint32)(address + size)));
return NULL;
}
for (uint32 i = 0; i < size; i++) {
map_page(address, get_next_physical_page(B_PAGE_SIZE),
kDefaultPageFlags);
address += B_PAGE_SIZE;
}
return virtualAddress;
}
void *address = (void *)sNextVirtualAddress;
for (uint32 i = 0; i < size; i++) {
map_page(get_next_virtual_page(B_PAGE_SIZE),
get_next_physical_page(B_PAGE_SIZE), 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;
addr_t pageOffset = address % B_PAGE_SIZE;
address -= pageOffset;
size = (size + pageOffset + B_PAGE_SIZE - 1) / B_PAGE_SIZE * B_PAGE_SIZE;
// is the address within the valid range?
if (address < KERNEL_LOAD_BASE || address + size > sNextVirtualAddress) {
panic("mmu_free: asked to unmap out of range region (%p, size %lx)\n",
(void *)address, size);
}
// unmap all pages within the range
for (size_t i = 0; i < size; i += B_PAGE_SIZE) {
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"));
// store next available pagetable in our pagedir mapping, for
// the kernel to use in early vm setup
gKernelArgs.arch_args.next_pagetable = sNextPageTableAddress - (addr_t)sPageDirectory;
// save the memory we've physically allocated
insert_physical_allocated_range((addr_t)sPageDirectory, sNextPhysicalAddress - (addr_t)sPageDirectory);
// Save the memory we've virtually allocated (for the kernel and other
// stuff)
insert_virtual_allocated_range(KERNEL_LOAD_BASE, sNextVirtualAddress - KERNEL_LOAD_BASE);
#ifdef TRACE_MEMORY_MAP
{
uint32 i;
dprintf("phys memory ranges:\n");
for (i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) {
dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\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%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\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%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n",
gKernelArgs.virtual_allocated_range[i].start,
gKernelArgs.virtual_allocated_range[i].size);
}
}
#endif
}
extern "C" void
mmu_init(void* fdt)
{
TRACE(("mmu_init\n"));
// skip RAM check if already done (rPi)
if (gKernelArgs.num_physical_memory_ranges == 0) {
// get map of physical memory (fill in kernel_args structure)
if (fdt_map_memory_ranges(fdt, "/memory", true) != B_OK) {
panic("Error: could not find physical memory ranges from FDT!\n");
#ifdef SDRAM_BASE
dprintf("Defaulting to 32MB at %" B_PRIx64 "\n", (uint64)SDRAM_BASE);
// specify available physical memory, using 32MB for now, since our
// ARMv5 targets have very little by default.
uint64 total = 32 * 1024 * 1024;
insert_physical_memory_range(SDRAM_BASE, total);
#else
return /*B_ERROR*/;
#endif
}
}
// see if subpages are disabled
if (mmu_read_C1() & (1 << 23))
sSmallPageType = ARM_MMU_L2_TYPE_SMALLNEW;
mmu_write_C1(mmu_read_C1() & ~((1 << 29) | (1 << 28) | (1 << 0)));
// access flag disabled, TEX remap disabled, mmu disabled
// allocate page directory in memory after loader
sPageDirectory = (uint32 *)ROUNDUP((addr_t)&_end, 0x100000);
sNextPageTableAddress = (addr_t)sPageDirectory + ARM_MMU_L1_TABLE_SIZE;
sPageTableRegionEnd = (addr_t)sPageDirectory + 0x200000;
// Mark start for dynamic allocation
sNextPhysicalAddress = sPageTableRegionEnd;
// We are going to allocate early kernel stuff there, so the virtual address
// has to be in kernel space. Either put it right after the identity mapped
// RAM (if it happens to be in the 0x80000000 range), or at the start of
// the kernel address space otherwise.
sNextVirtualAddress = KERNEL_LOAD_BASE + kMaxKernelSize;
if (sPageTableRegionEnd > sNextVirtualAddress)
sNextVirtualAddress = sPageTableRegionEnd;
// mark allocated ranges, so they don't get overwritten
insert_physical_allocated_range((addr_t)&_start,
(addr_t)&_end - (addr_t)&_start);
insert_physical_allocated_range((addr_t)sPageDirectory, 0x200000);
init_page_directory(fdt);
// map in a kernel stack
gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE
+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
gKernelArgs.cpu_kstack[0].start = (addr_t)mmu_allocate(NULL,
gKernelArgs.cpu_kstack[0].size);
TRACE(("kernel stack at 0x%" B_PRIx64 " to 0x%" B_PRIx64 "\n",
gKernelArgs.cpu_kstack[0].start,
gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size));
}
// #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 = mmu_allocate(NULL, args->heap_size);
if (heap == NULL)
return B_NO_MEMORY;
*_base = heap;
*_top = (void *)((int8 *)heap + args->heap_size);
return B_OK;
}
@@ -1,38 +0,0 @@
/*
* Copyright 2011, François Revol <revol@free.fr>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include <arch/arm/arch_cpu.h>
#include <asm_defs.h>
.text
/* status_t arch_start_kernel(struct kernel_args *kernelArgs,
addr_t kernelEntry, addr_t kernelStackTop);
r0 - kernelArgs
r1 - kernelEntry
r2 - kernelStackTop
*/
FUNCTION(arch_start_kernel):
// set the kernel stack
mov sp,r2
// set up kernel _start args
//mov r0,r0 // kernelArgs
mov r4,r1
mov r1,#0 // currentCPU=0
// call the kernel
mov pc,r4
// return
mov r0,#-1 // B_ERROR
mov pc,lr
FUNCTION_END(arch_start_kernel)
@@ -1,94 +0,0 @@
#include <arch/arm/arch_cpu.h>
#include <asm_defs.h>
.text
/*
* Entry points to the loader that U-Boot passes control to.
*/
/*
* called as standalone (raw binary)
* *MUST* be first symbol
*/
SYMBOL(_start_raw):
/*
* ELF entry
*/
SYMBOL(_start):
mov r4,#0
b _start_common
SYMBOL_END(_start_raw)
SYMBOL_END(_start)
/*
* called from bootm with netbsd loader compatible args
*/
SYMBOL(_start_netbsd):
mov r4,#1
b _start_common
SYMBOL_END(_start_netbsd)
/*
* called from bootm with linux loader compatible args
*/
SYMBOL(_start_linux):
mov r4,#2
b _start_common
SYMBOL_END(_start_linux)
SYMBOL(_start_common):
strb r4,gUBootOS
str r8,gUBootGlobalData
/*
* Turn off interrupts and make sure we are in SVC mode
*/
mrs r4, cpsr
bic r4, r4, #0x1f
orr r4, r4, #0xd3
msr cpsr, r4
/*
* Turn off MMU and data cache if necessary.
* WARNING: assumes we are running with a 1-1 mapping if MMU is enabled.
*/
mrc p15, 0, r4, c1, c0, 0
bic r4, r4, #0x0000000f // WCAM bits
bic r4, r4, #0x00000300 // RS bits
mcr p15, 0, r4, c1, c0, 0
mov r4, #0
mov r4, r4
mov r4, r4
ldr sp,=__stack_top
ldrb r4,gUBootOS
cmp r4,#0
beq start_raw
cmp r4,#1
beq start_netbsd
cmp r4,#2
beq start_linux
mov pc,lr
SYMBOL_END(_start_common)
//XXX: doesn't seem to work
//.data
.global __stack_end, __stack_start
SYMBOL(gUBootGlobalData):
.long 0
SYMBOL_END(gUBootGlobalData)
SYMBOL(gUBootOS):
//XXX: bug? Using .byte makes the next asm symbol
// to be at the same address
// .byte 0
.long 0
SYMBOL_END(gUBootOS)
@@ -1,77 +0,0 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
STACK_SIZE = 16384;
ENTRY(_start)
SECTIONS
{
. = BOOT_LOADER_BASE;
/* text/read-only data */
.text : { *(.text .gnu.linkonce.t.*) }
. = ALIGN(0x4);
__ctor_list = .;
.ctors : { *(.ctors) *(.init_array) }
__ctor_end = .;
.rodata : { *(.rodata .rodata.*) }
/* writable data */
. = ALIGN(0x1000);
__data_start = .;
.data : { *(.data .gnu.linkonce.d.*) }
/* exception unwinding - should really not be needed! */
__exidx_start = .;
.ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
__exidx_end = .;
/* uninitialized data (in same segment as writable data) */
__bss_start = .;
.bss : { *(.bss) }
__bss_end = .;
.stack : {
__stack_start = .;
. += STACK_SIZE;
. = ALIGN(0x8);
__stack_top = .;
}
. = ALIGN(0x1000);
_end = . ;
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
/* Strip unnecessary stuff */
/* /DISCARD/ : { *(.comment .note .eh_frame .dtors .stab .stabstr .debug*) }*/
}