Merge branch 'uefi-support'

This commit is contained in:
Jessica Hamilton
2016-11-14 03:21:59 +13:00
72 changed files with 3600 additions and 144 deletions
+30 -12
View File
@@ -284,7 +284,7 @@ rule KernelArchitectureSetup architecture
HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 192 ; # in kB - unused yet HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 192 ; # in kB - unused yet
case x86 : case x86 :
HAIKU_BOOT_PLATFORM = bios_ia32 ; HAIKU_BOOT_PLATFORM ?= bios_ia32 ;
HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 2880 ; # in kB HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 2880 ; # in kB
# offset in floppy image (>= sizeof(haiku_loader)) # offset in floppy image (>= sizeof(haiku_loader))
HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 320 ; # in kB HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 320 ; # in kB
@@ -296,7 +296,7 @@ rule KernelArchitectureSetup architecture
case x86_64 : case x86_64 :
# x86_64 completely shares the x86 bootloader. # x86_64 completely shares the x86 bootloader.
HAIKU_BOOT_PLATFORM = bios_ia32 ; HAIKU_BOOT_PLATFORM ?= bios_ia32 ;
HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 2880 ; # in kB HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 2880 ; # in kB
# offset in floppy image (>= sizeof(haiku_loader)) # offset in floppy image (>= sizeof(haiku_loader))
HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 320 ; # in kB HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 320 ; # in kB
@@ -331,12 +331,6 @@ rule KernelArchitectureSetup architecture
Exit "Currently unsupported target CPU:" $(cpu) ; Exit "Currently unsupported target CPU:" $(cpu) ;
} }
# Include embedded board-specific file.
if $(HAIKU_BOOT_BOARD) {
include [ FDirName $(HAIKU_BUILD_RULES_DIR) board $(HAIKU_BOOT_BOARD)
BoardSetup ] ;
}
# private kernel headers to be used when compiling kernel code # private kernel headers to be used when compiling kernel code
HAIKU_PRIVATE_KERNEL_HEADERS = HAIKU_PRIVATE_KERNEL_HEADERS =
[ PrivateHeaders $(DOT) kernel libroot shared [ PrivateHeaders $(DOT) kernel libroot shared
@@ -366,6 +360,7 @@ rule KernelArchitectureSetup architecture
HAIKU_BOOT_CCFLAGS = $(HAIKU_CCFLAGS_$(architecture)) $(gccBaseFlags) ; HAIKU_BOOT_CCFLAGS = $(HAIKU_CCFLAGS_$(architecture)) $(gccBaseFlags) ;
HAIKU_BOOT_C++FLAGS = $(HAIKU_C++FLAGS_$(architecture)) $(g++BaseFlags) ; HAIKU_BOOT_C++FLAGS = $(HAIKU_C++FLAGS_$(architecture)) $(g++BaseFlags) ;
HAIKU_BOOT_LINKFLAGS = ; HAIKU_BOOT_LINKFLAGS = ;
HAIKU_BOOT_LDFLAGS = -Bstatic ;
if $(gccVersion[1]) >= 4 { if $(gccVersion[1]) >= 4 {
HAIKU_KERNEL_C++FLAGS += -std=gnu++11 ; HAIKU_KERNEL_C++FLAGS += -std=gnu++11 ;
@@ -375,6 +370,16 @@ rule KernelArchitectureSetup architecture
HAIKU_KERNEL_PIC_LINKFLAGS = ; HAIKU_KERNEL_PIC_LINKFLAGS = ;
HAIKU_KERNEL_ADDON_LINKFLAGS = ; HAIKU_KERNEL_ADDON_LINKFLAGS = ;
# Include embedded board-specific file.
if $(HAIKU_BOOT_BOARD) {
include [ FDirName $(HAIKU_BUILD_RULES_DIR) board $(HAIKU_BOOT_BOARD)
BoardSetup ] ;
if $(HAIKU_BOARD_LOADER_BASE) {
HAIKU_BOOT_LDFLAGS +=
--defsym BOARD_LOADER_BASE=$(HAIKU_BOARD_LOADER_BASE) ;
}
}
switch $(cpu) { switch $(cpu) {
case ppc : case ppc :
# Build a position independent PPC kernel. We need to be able to # Build a position independent PPC kernel. We need to be able to
@@ -406,10 +411,23 @@ rule KernelArchitectureSetup architecture
HAIKU_KERNEL_PIC_LINKFLAGS += -z max-page-size=0x1000 ; HAIKU_KERNEL_PIC_LINKFLAGS += -z max-page-size=0x1000 ;
HAIKU_KERNEL_ADDON_LINKFLAGS += -z max-page-size=0x1000 ; HAIKU_KERNEL_ADDON_LINKFLAGS += -z max-page-size=0x1000 ;
# Bootloader is 32-bit. # BIOS Bootloader is 32-bit.
HAIKU_BOOT_LINKFLAGS += -m elf_i386_haiku ; if $(HAIKU_BOOT_PLATFORM) = bios_ia32 {
HAIKU_BOOT_CCFLAGS += -m32 -march=pentium ; HAIKU_BOOT_LINKFLAGS += -m elf_i386_haiku ;
HAIKU_BOOT_C++FLAGS += -m32 -march=pentium ; HAIKU_BOOT_CCFLAGS += -m32 -march=pentium ;
HAIKU_BOOT_C++FLAGS += -m32 -march=pentium ;
}
}
if $(HAIKU_BOOT_PLATFORM) = efi {
HAIKU_BOOT_CCFLAGS += -fpic -fno-stack-protector -fPIC -fshort-wchar -mno-red-zone
-maccumulate-outgoing-args -Wno-error=unused-variable ;
HAIKU_BOOT_C++FLAGS += -fpic -fno-stack-protector -fPIC -fshort-wchar -mno-red-zone
-maccumulate-outgoing-args -Wno-error=unused-variable ;
HAIKU_BOOT_LDFLAGS = -Bstatic -Bsymbolic -shared -nostdlib -znocombreloc -nostartfiles -no-undefined ;
} else {
HAIKU_BOOT_CCFLAGS += -fno-pic ;
HAIKU_BOOT_C++FLAGS += -fno-pic ;
} }
# warning flags # warning flags
+1 -1
View File
@@ -47,7 +47,7 @@ rule BootLd
LINK on $(1) = $(TARGET_LD_$(TARGET_PACKAGING_ARCH)) ; LINK on $(1) = $(TARGET_LD_$(TARGET_PACKAGING_ARCH)) ;
LINKFLAGS on $(1) = $(4) ; LINKFLAGS on $(1) = $(TARGET_BOOT_LINKFLAGS) $(4) ;
if $(3) { LINKFLAGS on $(1) += --script=$(3) ; } if $(3) { LINKFLAGS on $(1) += --script=$(3) ; }
# Remove any preset LINKLIBS, but link against libgcc.a. Linking against # Remove any preset LINKLIBS, but link against libgcc.a. Linking against
+17
View File
@@ -624,6 +624,23 @@ if [ IsPackageAvailable expat_devel ] {
} }
# gnu-efi
if $(TARGET_PACKAGING_ARCH) = x86_64 {
if [ IsPackageAvailable gnuefi ] {
ExtractBuildFeatureArchives gnuefi :
file: base gnuefi
headers: $(developHeadersDir)/gnuefi
headersProtocol: $(developHeadersDir)/gnuefi/protocol
headersArch: $(developHeadersDir)/gnuefi/$(TARGET_ARCH)
libdir: $(libDir)/gnuefi
;
EnableBuildFeatures gnuefi ;
} else {
Echo "gnuefi support not available on $(TARGET_PACKAGING_ARCH)" ;
}
}
# GPL add-ons # GPL add-ons
if $(HAIKU_INCLUDE_GPL_ADDONS) = 1 { if $(HAIKU_INCLUDE_GPL_ADDONS) = 1 {
EnableBuildFeatures gpl ; EnableBuildFeatures gpl ;
+1 -1
View File
@@ -650,7 +650,7 @@ local buildVars =
KERNEL_CCFLAGS KERNEL_C++FLAGS KERNEL_CCFLAGS KERNEL_C++FLAGS
KERNEL_PIC_CCFLAGS KERNEL_PIC_LINKFLAGS KERNEL_ADDON_LINKFLAGS KERNEL_PIC_CCFLAGS KERNEL_PIC_LINKFLAGS KERNEL_ADDON_LINKFLAGS
BOOT_CCFLAGS BOOT_C++FLAGS BOOT_LINKFLAGS BOOT_CCFLAGS BOOT_C++FLAGS BOOT_LINKFLAGS BOOT_LDFLAGS
KERNEL_WARNING_CCFLAGS KERNEL_WARNING_C++FLAGS KERNEL_WARNING_CCFLAGS KERNEL_WARNING_C++FLAGS
@@ -38,6 +38,8 @@ typedef struct {
// hpet stuff // hpet stuff
uint32 hpet_phys; uint32 hpet_phys;
FixedWidthPointer<void> hpet; FixedWidthPointer<void> hpet;
// needed for UEFI, otherwise kernel acpi support can't find ACPI root
FixedWidthPointer<void> acpi_root;
} _PACKED arch_kernel_args; } _PACKED arch_kernel_args;
#endif /* KERNEL_ARCH_x86_KERNEL_ARGS_H */ #endif /* KERNEL_ARCH_x86_KERNEL_ARGS_H */
+2
View File
@@ -30,6 +30,8 @@ class Partition : public Node, public partition_data {
status_t Mount(Directory **_fileSystem = NULL, bool isBootDevice = false); status_t Mount(Directory **_fileSystem = NULL, bool isBootDevice = false);
status_t Scan(bool mountFileSystems, bool isBootDevice = false); status_t Scan(bool mountFileSystems, bool isBootDevice = false);
static Partition *Lookup(partition_id id, NodeList *list = NULL);
void SetParent(Partition *parent); void SetParent(Partition *parent);
Partition *Parent() const; Partition *Parent() const;
+2
View File
@@ -28,6 +28,8 @@ extern status_t platform_init_heap(struct stage2_args *args, void **_base, void
extern status_t platform_allocate_region(void **_virtualAddress, size_t size, extern status_t platform_allocate_region(void **_virtualAddress, size_t size,
uint8 protection, bool exactAddress); uint8 protection, bool exactAddress);
extern status_t platform_free_region(void *address, size_t size); extern status_t platform_free_region(void *address, size_t size);
extern status_t platform_bootloader_address_to_kernel_address(void *address, uint64_t *_result);
extern status_t platform_kernel_address_to_bootloader_address(uint64_t address, void **_result);
/* boot options */ /* boot options */
#define BOOT_OPTION_MENU 1 #define BOOT_OPTION_MENU 1
@@ -0,0 +1,46 @@
/*
* Copyright 2013-2016 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef KERNEL_BOOT_PLATFORM_EFI_KERNEL_ARGS_H
#define KERNEL_BOOT_PLATFORM_EFI_KERNEL_ARGS_H
#ifndef KERNEL_BOOT_KERNEL_ARGS_H
# error This file is included from <boot/kernel_args.h> only
#endif
// currently the EFI loader pretends to be the bios_ia32 platform.
// not quite right, as the kernel needs to be aware of efi runtime services
#include <arch/x86/apm.h>
#include <boot/disk_identifier.h>
#include <util/FixedWidthPointer.h>
#define SMP_MAX_CPUS 64
#define MAX_PHYSICAL_MEMORY_RANGE 32
#define MAX_PHYSICAL_ALLOCATED_RANGE 32
#define MAX_VIRTUAL_ALLOCATED_RANGE 32
#define MAX_SERIAL_PORTS 4
typedef struct bios_drive {
struct bios_drive *next;
uint16 drive_number;
disk_identifier identifier;
} bios_drive;
typedef struct {
uint16 serial_base_ports[MAX_SERIAL_PORTS];
FixedWidthPointer<bios_drive> drives;
// this does not contain the boot drive
// seems to be ignored entirely?
apm_info apm;
} _PACKED platform_kernel_args;
#endif /* KERNEL_BOOT_PLATFORM_BIOS_IA32_KERNEL_ARGS_H */
@@ -0,0 +1,17 @@
/*
* Copyright 2013-2016 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_BOOT_PLATFORM_EFI_STAGE2_ARGS_H
#define _KERNEL_BOOT_PLATFORM_EFI_STAGE2_ARGS_H
#ifndef KERNEL_BOOT_STAGE2_ARGS_H
# error This file is included from <boot/stage2_args.h> only
#endif
struct platform_stage2_args {
};
#endif /* _KERNEL_BOOT_PLATFORM_EFI_STAGE2_ARGS_H */
@@ -127,6 +127,7 @@
# include <dpc.h> # include <dpc.h>
# include <PCI.h> # include <PCI.h>
# include <boot_item.h>
# include <kernel.h> # include <kernel.h>
# include <vm/vm.h> # include <vm/vm.h>
#endif #endif
@@ -181,7 +182,7 @@ extern void *gDPCHandle;
extern FILE *AcpiGbl_DebugFile; extern FILE *AcpiGbl_DebugFile;
FILE *AcpiGbl_OutputFile; FILE *AcpiGbl_OutputFile;
static uint32 sACPIRoot = 0; static ACPI_PHYSICAL_ADDRESS sACPIRoot = 0;
static void *sInterruptHandlerData[32]; static void *sInterruptHandlerData[32];
@@ -233,12 +234,15 @@ AcpiOsGetRootPointer()
{ {
#ifdef _KERNEL_MODE #ifdef _KERNEL_MODE
ACPI_PHYSICAL_ADDRESS address; ACPI_PHYSICAL_ADDRESS address;
ACPI_STATUS status; ACPI_STATUS status = AE_OK;
DEBUG_FUNCTION(); DEBUG_FUNCTION();
if (sACPIRoot == 0) { if (sACPIRoot == 0) {
status = AcpiFindRootPointer(&address); sACPIRoot = (ACPI_PHYSICAL_ADDRESS)get_boot_item("ACPI_ROOT_POINTER", NULL);
if (status == AE_OK) if (sACPIRoot == 0) {
sACPIRoot = address; status = AcpiFindRootPointer(&address);
if (status == AE_OK)
sACPIRoot = address;
}
} }
return sACPIRoot; return sACPIRoot;
#else #else
+27 -9
View File
@@ -1,9 +1,17 @@
SubDir HAIKU_TOP src system boot ; SubDir HAIKU_TOP src system boot ;
SetupFeatureObjectsDir $(TARGET_BOOT_PLATFORM) ;
DEFINES += _BOOT_MODE ; DEFINES += _BOOT_MODE ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot os arch if $(TARGET_ARCH) = x86_64 && $(TARGET_BOOT_PLATFORM) != bios_ia32 {
$(TARGET_KERNEL_ARCH) ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot os arch
x86_64 ] ;
} else {
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot os arch
$(TARGET_KERNEL_ARCH) ] ;
}
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot posix string ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot posix string ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot posix stdlib ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot posix stdlib ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot posix locale ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot posix locale ] ;
@@ -41,14 +49,8 @@ BootMergeObject boot_libroot.o :
strrchr.c strrchr.c
strtol.c strtol.c
$(extraSources) $(extraSources)
: -fno-pic
; ;
local extraLinkerArgs = ;
if $(HAIKU_BOARD_LOADER_BASE) {
extraLinkerArgs += --defsym BOARD_LOADER_BASE=$(HAIKU_BOARD_LOADER_BASE) ;
}
AddResources haiku_loader : boot_loader.rdef ; AddResources haiku_loader : boot_loader.rdef ;
BootLd boot_loader_$(TARGET_BOOT_PLATFORM) : BootLd boot_loader_$(TARGET_BOOT_PLATFORM) :
@@ -76,7 +78,7 @@ BootLd boot_loader_$(TARGET_BOOT_PLATFORM) :
boot_libroot.o boot_libroot.o
: $(HAIKU_TOP)/src/system/ldscripts/$(TARGET_ARCH)/boot_loader_$(TARGET_BOOT_PLATFORM).ld : $(HAIKU_TOP)/src/system/ldscripts/$(TARGET_ARCH)/boot_loader_$(TARGET_BOOT_PLATFORM).ld
: -Bstatic $(extraLinkerArgs) : $(TARGET_BOOT_LDFLAGS)
; ;
rule BuildCoffLoader { rule BuildCoffLoader {
@@ -130,6 +132,22 @@ BuildBiosLoader haiku_loader : boot_loader_$(TARGET_BOOT_PLATFORM) ;
# different target for PXE, to be build with TARGET_BOOT_PLATFORM=pxe_ia32 jam pxehaiku-loader # different target for PXE, to be build with TARGET_BOOT_PLATFORM=pxe_ia32 jam pxehaiku-loader
BuildBiosLoader pxehaiku-loader : boot_loader_$(TARGET_BOOT_PLATFORM) ; BuildBiosLoader pxehaiku-loader : boot_loader_$(TARGET_BOOT_PLATFORM) ;
rule BuildEFILoader {
local efiLoader = $(1) ;
local bootLoader = $(2) ;
Depends $(efiLoader) : $(bootLoader) ;
MakeLocateDebug $(efiLoader) ;
}
actions BuildEFILoader {
rm -f $(1)
$(TARGET_OBJCOPY_$(TARGET_PACKAGING_ARCH)) -j .text -j .sdata -j .data -j .dynamic -j .dynsym \
-j .rel -j .rela -j .reloc --target=efi-app-x86_64 $(2) $(1)
}
BuildEFILoader haiku_loader.efi : boot_loader_$(TARGET_BOOT_PLATFORM) ;
SubInclude HAIKU_TOP src system boot arch $(TARGET_KERNEL_ARCH) ; SubInclude HAIKU_TOP src system boot arch $(TARGET_KERNEL_ARCH) ;
SubInclude HAIKU_TOP src system boot loader ; SubInclude HAIKU_TOP src system boot loader ;
SubInclude HAIKU_TOP src system boot platform ; SubInclude HAIKU_TOP src system boot platform ;
+1 -1
View File
@@ -49,7 +49,7 @@ BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o :
$(kernelDebugSources) $(kernelDebugSources)
$(librootArchObjects) $(librootArchObjects)
: -fno-pic :
: :
$(kernelLibArchObjects) $(kernelLibArchObjects)
; ;
+4 -4
View File
@@ -16,24 +16,24 @@ local kernelLibArchObjects =
BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o : BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o :
arch_elf.cpp arch_elf.cpp
$(librootArchObjects) $(librootArchObjects)
: -fno-pic :
: :
$(kernelLibArchObjects) $(kernelLibArchObjects)
; ;
BootMergeObject boot_arch_m68k_030.o : BootMergeObject boot_arch_m68k_030.o :
mmu_030.cpp mmu_030.cpp
: -fno-pic -Wno-unused -mcpu=68030 : -Wno-unused -mcpu=68030
; ;
BootMergeObject boot_arch_m68k_040.o : BootMergeObject boot_arch_m68k_040.o :
mmu_040.cpp mmu_040.cpp
: -fno-pic -Wno-unused -mcpu=68040 -Wa,-m68040 : -Wno-unused -mcpu=68040 -Wa,-m68040
; ;
BootMergeObject boot_arch_m68k_060.o : BootMergeObject boot_arch_m68k_060.o :
mmu_060.cpp mmu_060.cpp
: -fno-pic -Wno-unused -mcpu=68060 : -Wno-unused -mcpu=68060
; ;
SEARCH on [ FGristFiles arch_elf.cpp ] SEARCH on [ FGristFiles arch_elf.cpp ]
+24 -12
View File
@@ -1,18 +1,22 @@
SubDir HAIKU_TOP src system boot arch x86 ; SubDir HAIKU_TOP src system boot arch x86 ;
SetupFeatureObjectsDir $(TARGET_BOOT_PLATFORM) ;
DEFINES += _BOOT_MODE ; DEFINES += _BOOT_MODE ;
local kernelArchSources = local kernelArchSources =
arch_elf.cpp arch_elf.cpp
; ;
local kernelArch32Sources = local kernelArchSpecificSources ;
cpuid.S local kernelLibArchSpecificSources ;
; if $(TARGET_ARCH) = x86_64 && $(TARGET_BOOT_PLATFORM) != bios_ia32 {
kernelArchSpecificSources = cpuid.cpp ;
local kernelLibArchSources = kernelLibArchSpecificSources = arch_string.cpp ;
arch_string.S } else {
; kernelArchSpecificSources = cpuid.S ;
kernelLibArchSpecificSources = arch_string.S ;
}
local librootOsArchSources = local librootOsArchSources =
byteorder.S byteorder.S
@@ -20,17 +24,25 @@ local librootOsArchSources =
BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o : BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o :
$(kernelArchSources) $(kernelArchSources)
$(kernelArch32Sources) $(kernelArchSpecificSources)
$(kernelLibArchSources) $(kernelLibArchSpecificSources)
$(librootOsArchSources) $(librootOsArchSources)
: # additional flags : -std=c++11 # additional flags
; ;
SEARCH on [ FGristFiles $(kernelArchSources) ] SEARCH on [ FGristFiles $(kernelArchSources) ]
= [ FDirName $(HAIKU_TOP) src system kernel arch x86 ] ; = [ FDirName $(HAIKU_TOP) src system kernel arch x86 ] ;
SEARCH on [ FGristFiles $(kernelArch32Sources) ]
if $(TARGET_ARCH) = x86_64 && $(TARGET_BOOT_PLATFORM) != bios_ia32 {
SEARCH on [ FGristFiles $(kernelArchSpecificSources) ]
= [ FDirName $(HAIKU_TOP) src system kernel arch x86 64 ] ;
SEARCH on [ FGristFiles $(kernelLibArchSpecificSources) ]
= [ FDirName $(HAIKU_TOP) src system libroot posix string arch x86_64 ] ;
} else {
SEARCH on [ FGristFiles $(kernelArchSpecificSources) ]
= [ FDirName $(HAIKU_TOP) src system kernel arch x86 32 ] ; = [ FDirName $(HAIKU_TOP) src system kernel arch x86 32 ] ;
SEARCH on [ FGristFiles $(kernelLibArchSources) ] SEARCH on [ FGristFiles $(kernelLibArchSpecificSources) ]
= [ FDirName $(HAIKU_TOP) src system kernel lib arch x86 ] ; = [ FDirName $(HAIKU_TOP) src system kernel lib arch x86 ] ;
}
SEARCH on [ FGristFiles $(librootOsArchSources) ] SEARCH on [ FGristFiles $(librootOsArchSources) ]
= [ FDirName $(HAIKU_TOP) src system libroot os arch x86 ] ; = [ FDirName $(HAIKU_TOP) src system libroot os arch x86 ] ;
+11 -3
View File
@@ -1,5 +1,7 @@
SubDir HAIKU_TOP src system boot loader ; SubDir HAIKU_TOP src system boot loader ;
SetupFeatureObjectsDir $(TARGET_BOOT_PLATFORM) ;
SubDirHdrs $(HAIKU_TOP) src add-ons kernel partitioning_systems amiga ; SubDirHdrs $(HAIKU_TOP) src add-ons kernel partitioning_systems amiga ;
SubDirHdrs $(HAIKU_TOP) src add-ons kernel partitioning_systems apple ; SubDirHdrs $(HAIKU_TOP) src add-ons kernel partitioning_systems apple ;
SubDirHdrs $(HAIKU_TOP) src add-ons kernel partitioning_systems gpt ; SubDirHdrs $(HAIKU_TOP) src add-ons kernel partitioning_systems gpt ;
@@ -45,6 +47,15 @@ UsePrivateHeaders shared storage ;
#BOOT_SUPPORT_FILE_SYSTEM_FAT #BOOT_SUPPORT_FILE_SYSTEM_FAT
; ;
if $(HAIKU_BOOT_PLATFORM) != efi {
DEFINES +=
BOOT_SUPPORT_ELF32
;
} else {
DEFINES +=
_BOOT_PLATFORM_EFI
;
}
} }
} }
@@ -85,8 +96,6 @@ BootStaticLibrary boot_loader :
DataIO.cpp DataIO.cpp
Referenceable.cpp Referenceable.cpp
: -fno-pic
; ;
# The partition support is built in an extra static library # The partition support is built in an extra static library
@@ -105,7 +114,6 @@ BootStaticLibrary boot_partitions :
intel.cpp intel.cpp
PartitionMap.cpp PartitionMap.cpp
PartitionMapParser.cpp PartitionMapParser.cpp
: -fno-pic
; ;
# Tell Jam where to find the utility sources # Tell Jam where to find the utility sources
+32 -3
View File
@@ -61,6 +61,7 @@ private:
}; };
#ifdef BOOT_SUPPORT_ELF32
struct ELF32Class { struct ELF32Class {
static const uint8 kIdentClass = ELFCLASS32; static const uint8 kIdentClass = ELFCLASS32;
@@ -96,6 +97,7 @@ struct ELF32Class {
}; };
typedef ELFLoader<ELF32Class> ELF32Loader; typedef ELFLoader<ELF32Class> ELF32Loader;
#endif
#ifdef BOOT_SUPPORT_ELF64 #ifdef BOOT_SUPPORT_ELF64
@@ -117,6 +119,17 @@ struct ELF64Class {
AllocateRegion(AddrType* _address, AddrType size, uint8 protection, AllocateRegion(AddrType* _address, AddrType size, uint8 protection,
void **_mappedAddress) void **_mappedAddress)
{ {
#ifdef _BOOT_PLATFORM_EFI
void* address = (void*)*_address;
status_t status = platform_allocate_region(&address, size, protection,
false);
if (status != B_OK)
return status;
*_mappedAddress = address;
platform_bootloader_address_to_kernel_address(address, _address);
#else
// Assume the real 64-bit base address is KERNEL_LOAD_BASE_64_BIT and // Assume the real 64-bit base address is KERNEL_LOAD_BASE_64_BIT and
// the mappings in the loader address space are at KERNEL_LOAD_BASE. // the mappings in the loader address space are at KERNEL_LOAD_BASE.
@@ -130,14 +143,23 @@ struct ELF64Class {
*_mappedAddress = address; *_mappedAddress = address;
*_address = (AddrType)(addr_t)address + KERNEL_LOAD_BASE_64_BIT *_address = (AddrType)(addr_t)address + KERNEL_LOAD_BASE_64_BIT
- KERNEL_LOAD_BASE; - KERNEL_LOAD_BASE;
#endif
return B_OK; return B_OK;
} }
static inline void* static inline void*
Map(AddrType address) Map(AddrType address)
{ {
#ifdef _BOOT_PLATFORM_EFI
void *result;
if (platform_kernel_address_to_bootloader_address(address, &result) != B_OK) {
panic("Couldn't convert address %#lx", address);
}
return result;
#else
return (void*)(addr_t)(address - KERNEL_LOAD_BASE_64_BIT return (void*)(addr_t)(address - KERNEL_LOAD_BASE_64_BIT
+ KERNEL_LOAD_BASE); + KERNEL_LOAD_BASE);
#endif
} }
}; };
@@ -225,7 +247,7 @@ ELFLoader<Class>::Load(int fd, preloaded_image* _image)
// known but unused type // known but unused type
continue; continue;
default: default:
dprintf("unhandled pheader type 0x%lx\n", header.p_type); dprintf("unhandled pheader type 0x%" B_PRIx32 "\n", header.p_type);
continue; continue;
} }
@@ -320,7 +342,7 @@ ELFLoader<Class>::Load(int fd, preloaded_image* _image)
header.p_filesz); header.p_filesz);
if (length < (ssize_t)header.p_filesz) { if (length < (ssize_t)header.p_filesz) {
status = B_BAD_DATA; status = B_BAD_DATA;
dprintf("error reading in seg %ld\n", i); dprintf("error reading in seg %" B_PRId32 "\n", i);
goto error2; goto error2;
} }
@@ -642,13 +664,14 @@ elf_load_image(int fd, preloaded_image** _image)
return status; return status;
} }
#endif #endif
#if BOOT_SUPPORT_ELF32
if (gKernelArgs.kernel_image == NULL if (gKernelArgs.kernel_image == NULL
|| gKernelArgs.kernel_image->elf_class == ELFCLASS32) { || gKernelArgs.kernel_image->elf_class == ELFCLASS32) {
status = ELF32Loader::Create(fd, _image); status = ELF32Loader::Create(fd, _image);
if (status == B_OK) if (status == B_OK)
return ELF32Loader::Load(fd, *_image); return ELF32Loader::Load(fd, *_image);
} }
#endif
return status; return status;
} }
@@ -706,16 +729,22 @@ elf_relocate_image(preloaded_image* image)
return ELF64Loader::Relocate(image); return ELF64Loader::Relocate(image);
else else
#endif #endif
#ifdef BOOT_SUPPORT_ELF32
return ELF32Loader::Relocate(image); return ELF32Loader::Relocate(image);
#else
return B_ERROR;
#endif
} }
#ifdef BOOT_SUPPORT_ELF32
status_t status_t
boot_elf_resolve_symbol(preloaded_elf32_image* image, Elf32_Sym* symbol, boot_elf_resolve_symbol(preloaded_elf32_image* image, Elf32_Sym* symbol,
Elf32_Addr* symbolAddress) Elf32_Addr* symbolAddress)
{ {
return ELF32Loader::Resolve(image, symbol, symbolAddress); return ELF32Loader::Resolve(image, symbol, symbolAddress);
} }
#endif
#ifdef BOOT_SUPPORT_ELF64 #ifdef BOOT_SUPPORT_ELF64
@@ -107,7 +107,7 @@ Stream::ReadAt(off_t offset, uint8 *buffer, size_t size)
{ {
if (offset < 0) if (offset < 0)
return B_BAD_VALUE; return B_BAD_VALUE;
if (offset + size > fNode.Size()) if (offset + (off_t)size > fNode.Size())
size = fNode.Size() - offset; size = fNode.Size() - offset;
ssize_t bytesLeft = (ssize_t)size; ssize_t bytesLeft = (ssize_t)size;
@@ -1,5 +1,7 @@
SubDir HAIKU_TOP src system boot loader file_systems amiga_ffs ; SubDir HAIKU_TOP src system boot loader file_systems amiga_ffs ;
SetupFeatureObjectsDir $(TARGET_BOOT_PLATFORM) ;
UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ; UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ;
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
UsePrivateHeaders kernel storage ; UsePrivateHeaders kernel storage ;
@@ -13,5 +15,4 @@ BootStaticLibrary boot_amiga_ffs :
Volume.cpp Volume.cpp
Directory.cpp Directory.cpp
File.cpp File.cpp
: -fno-pic
; ;
@@ -186,7 +186,7 @@ HashIterator::GetNext(int32 &block)
fNode.SetTo(fData); fNode.SetTo(fData);
if (fNode.ValidateCheckSum() != B_OK) { if (fNode.ValidateCheckSum() != B_OK) {
dprintf("block at %ld bad checksum.\n", fBlock); dprintf("block at %" B_PRId32 " bad checksum.\n", fBlock);
return NULL; return NULL;
} }
@@ -1,5 +1,7 @@
SubDir HAIKU_TOP src system boot loader file_systems bfs ; SubDir HAIKU_TOP src system boot loader file_systems bfs ;
SetupFeatureObjectsDir $(TARGET_BOOT_PLATFORM) ;
UsePrivateKernelHeaders ; UsePrivateKernelHeaders ;
UsePrivateHeaders file_systems shared storage ; UsePrivateHeaders file_systems shared storage ;
@@ -18,7 +20,6 @@ BootStaticLibrary boot_bfs :
Stream.cpp Stream.cpp
BPlusTree.cpp BPlusTree.cpp
QueryParserUtils.cpp QueryParserUtils.cpp
: -fno-pic
; ;
SEARCH on [ FGristFiles BPlusTree.cpp ] SEARCH on [ FGristFiles BPlusTree.cpp ]
@@ -306,7 +306,7 @@ Stream::ReadAt(off_t pos, uint8* buffer, size_t* _length)
size_t length = *_length; size_t length = *_length;
if (pos + length > data.Size()) if (pos + (off_t)length > data.Size())
length = data.Size() - pos; length = data.Size() - pos;
block_run run; block_run run;
@@ -112,7 +112,8 @@ Volume::ValidateBlockRun(block_run run)
|| run.Start() > (1UL << AllocationGroupShift()) || run.Start() > (1UL << AllocationGroupShift())
|| run.length == 0 || run.length == 0
|| uint32(run.Length() + run.Start()) > (1UL << AllocationGroupShift())) { || uint32(run.Length() + run.Start()) > (1UL << AllocationGroupShift())) {
dprintf("bfs: invalid run(%ld,%d,%d)\n", run.AllocationGroup(), run.Start(), run.Length()); dprintf("bfs: invalid run(%" B_PRId32 ",%d,%d)\n",
run.AllocationGroup(), run.Start(), run.Length());
return B_BAD_DATA; return B_BAD_DATA;
} }
return B_OK; return B_OK;
@@ -1,5 +1,7 @@
SubDir HAIKU_TOP src system boot loader file_systems fat ; SubDir HAIKU_TOP src system boot loader file_systems fat ;
SetupFeatureObjectsDir $(TARGET_BOOT_PLATFORM) ;
#UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ; #UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ;
#UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; #UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
#UsePrivateHeaders [ FDirName storage ] ; #UsePrivateHeaders [ FDirName storage ] ;
@@ -20,5 +22,4 @@ BootStaticLibrary boot_fatfs :
Directory.cpp Directory.cpp
File.cpp File.cpp
Stream.cpp Stream.cpp
: -fno-pic
; ;
@@ -257,7 +257,7 @@ Stream::ReadAt(off_t pos, void *_buffer, size_t *_length, off_t *diskOffset)
size_t length = *_length; size_t length = *_length;
if (pos + length > fSize) if (pos + (off_t)length > fSize)
length = fSize - pos; length = fSize - pos;
off_t num; // block number off_t num; // block number
@@ -1,5 +1,7 @@
SubDir HAIKU_TOP src system boot loader file_systems hfs_plus ; SubDir HAIKU_TOP src system boot loader file_systems hfs_plus ;
SetupFeatureObjectsDir $(TARGET_BOOT_PLATFORM) ;
UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ; UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ;
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
UsePrivateHeaders kernel storage ; UsePrivateHeaders kernel storage ;
@@ -8,5 +10,4 @@ SubDirC++Flags -fno-rtti ;
BootStaticLibrary boot_hfs_plus : BootStaticLibrary boot_hfs_plus :
hfs_plus.cpp hfs_plus.cpp
: -fno-pic
; ;
@@ -1,5 +1,7 @@
SubDir HAIKU_TOP src system boot loader file_systems packagefs ; SubDir HAIKU_TOP src system boot loader file_systems packagefs ;
SetupFeatureObjectsDir $(TARGET_BOOT_PLATFORM) ;
UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ; UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ;
UsePrivateHeaders kernel shared storage support ; UsePrivateHeaders kernel shared storage support ;
UseBuildFeatureHeaders zlib ; UseBuildFeatureHeaders zlib ;
@@ -46,8 +48,6 @@ BootStaticLibrary boot_packagefs :
# support kit # support kit
CompressionAlgorithm.cpp CompressionAlgorithm.cpp
ZlibCompressionAlgorithm.cpp ZlibCompressionAlgorithm.cpp
: -fno-pic
; ;
Includes [ FGristFiles ZlibCompressionAlgorithm.cpp ] Includes [ FGristFiles ZlibCompressionAlgorithm.cpp ]
@@ -525,7 +525,7 @@ struct File : ::Node {
off_t size = fFile->Size(); off_t size = fFile->Size();
if (pos < 0 || pos > size) if (pos < 0 || pos > size)
return B_BAD_VALUE; return B_BAD_VALUE;
if (pos + bufferSize > size) if (pos + (off_t)bufferSize > size)
bufferSize = size - pos; bufferSize = size - pos;
if (bufferSize > 0) { if (bufferSize > 0) {
@@ -1,5 +1,7 @@
SubDir HAIKU_TOP src system boot loader file_systems tarfs ; SubDir HAIKU_TOP src system boot loader file_systems tarfs ;
SetupFeatureObjectsDir $(TARGET_BOOT_PLATFORM) ;
UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ; UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ;
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
UsePrivateHeaders kernel shared storage ; UsePrivateHeaders kernel shared storage ;
@@ -29,7 +31,6 @@ Depends [ FGristFiles $(zlibSources) ]
BootStaticLibrary boot_zlib : BootStaticLibrary boot_zlib :
$(zlibSources) $(zlibSources)
: -fno-pic
; ;
@@ -41,5 +42,4 @@ Includes [ FGristFiles tarfs.cpp ] : [ BuildFeatureAttribute zlib : sources ] ;
BootStaticLibrary boot_tarfs : BootStaticLibrary boot_tarfs :
tarfs.cpp tarfs.cpp
: -fno-pic
; ;
+12
View File
@@ -370,7 +370,13 @@ kernel_args_malloc(size_t size)
return NULL; return NULL;
} }
#ifdef _BOOT_PLATFORM_EFI
uint64 translated_block;
platform_bootloader_address_to_kernel_address(block, &translated_block);
if (add_kernel_args_range((void *)translated_block, size) != B_OK)
#else
if (add_kernel_args_range(block, size) != B_OK) if (add_kernel_args_range(block, size) != B_OK)
#endif
panic("kernel_args max range too low!\n"); panic("kernel_args max range too low!\n");
return block; return block;
} }
@@ -385,7 +391,13 @@ kernel_args_malloc(size_t size)
sFirstFree = (void*)((addr_t)block + size); sFirstFree = (void*)((addr_t)block + size);
sLast = block; sLast = block;
sFree = kChunkSize - size; sFree = kChunkSize - size;
#ifdef _BOOT_PLATFORM_EFI
uint64 translated_block;
platform_bootloader_address_to_kernel_address(block, &translated_block);
if (add_kernel_args_range((void *)translated_block, kChunkSize) != B_OK)
#else
if (add_kernel_args_range(block, kChunkSize) != B_OK) if (add_kernel_args_range(block, kChunkSize) != B_OK)
#endif
panic("kernel_args max range too low!\n"); panic("kernel_args max range too low!\n");
return block; return block;
@@ -101,7 +101,7 @@ load_driver_settings(stage2_args* /*args*/, Directory* volume)
status_t status = load_driver_settings_file(settings, name); status_t status = load_driver_settings_file(settings, name);
if (status != B_OK) if (status != B_OK)
dprintf("Could not load \"%s\" error %ld\n", name, status); dprintf("Could not load \"%s\" error %" B_PRIx32 "\n", name, status);
} }
settings->Close(cookie); settings->Close(cookie);
+3 -3
View File
@@ -123,7 +123,7 @@ load_kernel(stage2_args* args, BootVolume& volume)
close(fd); close(fd);
if (status < B_OK) { if (status < B_OK) {
dprintf("loading kernel failed: %lx!\n", status); dprintf("loading kernel failed: %" B_PRIx32 "!\n", status);
return status; return status;
} }
@@ -131,7 +131,7 @@ load_kernel(stage2_args* args, BootVolume& volume)
status = elf_relocate_image(gKernelArgs.kernel_image); status = elf_relocate_image(gKernelArgs.kernel_image);
if (status < B_OK) { if (status < B_OK) {
dprintf("relocating kernel failed: %lx!\n", status); dprintf("relocating kernel failed: %" B_PRIx32 "!\n", status);
return status; return status;
} }
@@ -163,7 +163,7 @@ load_modules_from(BootVolume& volume, const char* path)
status_t status = elf_load_image(modules, name); status_t status = elf_load_image(modules, name);
if (status != B_OK) if (status != B_OK)
dprintf("Could not load \"%s\" error %ld\n", name, status); dprintf("Could not load \"%s\" error %" B_PRIx32 "\n", name, status);
} }
modules->Close(cookie); modules->Close(cookie);
+2 -2
View File
@@ -1,5 +1,7 @@
SubDir HAIKU_TOP src system boot loader net ; SubDir HAIKU_TOP src system boot loader net ;
SetupFeatureObjectsDir $(TARGET_BOOT_PLATFORM) ;
UsePrivateHeaders kernel [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ; UsePrivateHeaders kernel [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ;
UsePrivateHeaders drivers ; UsePrivateHeaders drivers ;
@@ -23,6 +25,4 @@ BootStaticLibrary boot_net :
UDP.cpp UDP.cpp
$(tcp) $(tcp)
$(iscsi) $(iscsi)
: -fno-pic
; ;
+2 -1
View File
@@ -169,7 +169,8 @@ RemoteDisk::GetName(char *nameBuffer, size_t bufferSize) const
if (!nameBuffer) if (!nameBuffer)
return B_BAD_VALUE; return B_BAD_VALUE;
snprintf(nameBuffer, bufferSize, "RemoteDisk:%ld.%ld.%ld.%ld:%hd", snprintf(nameBuffer, bufferSize,
"RemoteDisk:%" B_PRIu32 ".%" B_PRIu32 ".%" B_PRIu32 ".%" B_PRIu32 ":%hd",
(fServerAddress >> 24) & 0xff, (fServerAddress >> 16) & 0xff, (fServerAddress >> 24) & 0xff, (fServerAddress >> 16) & 0xff,
(fServerAddress >> 8) & 0xff, fServerAddress & 0xff, fServerPort); (fServerAddress >> 8) & 0xff, fServerAddress & 0xff, fServerPort);
+56 -19
View File
@@ -99,6 +99,9 @@ private:
}; };
static int32 sIdCounter = 0;
// #pragma mark - // #pragma mark -
@@ -111,7 +114,8 @@ Partition::Partition(int fd)
TRACE(("%p Partition::Partition\n", this)); TRACE(("%p Partition::Partition\n", this));
memset((partition_data *)this, 0, sizeof(partition_data)); memset((partition_data *)this, 0, sizeof(partition_data));
id = (partition_id)this;
id = atomic_add(&sIdCounter, 1);
// it's safe to close the file // it's safe to close the file
fFD = dup(fd); fFD = dup(fd);
@@ -136,6 +140,29 @@ Partition::~Partition()
} }
Partition *
Partition::Lookup(partition_id id, NodeList *list)
{
Partition *p;
if (list == NULL)
list = &gPartitions;
NodeIterator iterator = list->GetIterator();
while ((p = (Partition *)iterator.Next()) != NULL) {
if (p->id == id)
return p;
if (!p->fChildren.IsEmpty()) {
Partition *c = Lookup(id, &p->fChildren);
if (c)
return c;
}
}
return NULL;
}
void void
Partition::SetParent(Partition *parent) Partition::SetParent(Partition *parent)
{ {
@@ -160,7 +187,7 @@ Partition::ReadAt(void *cookie, off_t position, void *buffer, size_t bufferSize)
if (position < 0) if (position < 0)
return B_BAD_VALUE; return B_BAD_VALUE;
if (position + bufferSize > this->size) if (position + (off_t)bufferSize > this->size)
bufferSize = this->size - position; bufferSize = this->size - position;
ssize_t result = read_pos(fFD, this->offset + position, buffer, bufferSize); ssize_t result = read_pos(fFD, this->offset + position, buffer, bufferSize);
@@ -177,7 +204,7 @@ Partition::WriteAt(void *cookie, off_t position, const void *buffer,
if (position < 0) if (position < 0)
return B_BAD_VALUE; return B_BAD_VALUE;
if (position + bufferSize > this->size) if (position + (off_t)bufferSize > this->size)
bufferSize = this->size - position; bufferSize = this->size - position;
ssize_t result = write_pos(fFD, this->offset + position, buffer, ssize_t result = write_pos(fFD, this->offset + position, buffer,
@@ -313,7 +340,7 @@ Partition::Scan(bool mountFileSystems, bool isBootDevice)
if (priority < 0.0) if (priority < 0.0)
continue; continue;
TRACE((" priority: %ld\n", (int32)(priority * 1000))); TRACE((" priority: %" B_PRId32 "\n", (int32)(priority * 1000)));
if (priority <= bestPriority) { if (priority <= bestPriority) {
// the disk system recognized the partition worse than the currently // the disk system recognized the partition worse than the currently
// best one // best one
@@ -371,9 +398,9 @@ Partition::Scan(bool mountFileSystems, bool isBootDevice)
Partition *child = NULL; Partition *child = NULL;
while ((child = (Partition *)iterator.Next()) != NULL) { while ((child = (Partition *)iterator.Next()) != NULL) {
TRACE(("%p Partition::Scan(): scan child %p (start = %Ld, size " TRACE(("%p Partition::Scan(): scan child %p (start = %" B_PRIdOFF
"= %Ld, parent = %p)!\n", this, child, child->offset, ", size = %" B_PRIdOFF ", parent = %p)!\n", this, child,
child->size, child->Parent())); child->offset, child->size, child->Parent()));
child->Scan(mountFileSystems); child->Scan(mountFileSystems);
@@ -431,16 +458,19 @@ add_partitions_for(int fd, bool mountFileSystems, bool isBootDevice)
partition->block_size = 512; partition->block_size = 512;
partition->size = partition->Size(); partition->size = partition->Size();
// add this partition to the list of partitions, if it contains // add this partition to the list of partitions
// or might contain a file system // temporarily for Lookup() to work
gPartitions.Add(partition);
// keep it, if it contains or might contain a file system
if ((partition->Scan(mountFileSystems, isBootDevice) == B_OK if ((partition->Scan(mountFileSystems, isBootDevice) == B_OK
&& partition->IsFileSystem()) && partition->IsFileSystem())
|| (!partition->IsPartitioningSystem() && !mountFileSystems)) { || (!partition->IsPartitioningSystem() && !mountFileSystems)) {
gPartitions.Add(partition);
return B_OK; return B_OK;
} }
// if not, we no longer need the partition // if not, we no longer need the partition
gPartitions.Remove(partition);
delete partition; delete partition;
return B_OK; return B_OK;
} }
@@ -458,7 +488,7 @@ add_partitions_for(Node *device, bool mountFileSystems, bool isBootDevice)
status_t status = add_partitions_for(fd, mountFileSystems, isBootDevice); status_t status = add_partitions_for(fd, mountFileSystems, isBootDevice);
if (status < B_OK) if (status < B_OK)
dprintf("add_partitions_for(%d) failed: %ld\n", fd, status); dprintf("add_partitions_for(%d) failed: %" B_PRIx32 "\n", fd, status);
close(fd); close(fd);
return B_OK; return B_OK;
@@ -469,8 +499,13 @@ partition_data *
create_child_partition(partition_id id, int32 index, off_t offset, off_t size, create_child_partition(partition_id id, int32 index, off_t offset, off_t size,
partition_id childID) partition_id childID)
{ {
Partition &partition = *(Partition *)id; Partition *partition = Partition::Lookup(id);
Partition *child = partition.AddChild(); if (partition == NULL) {
dprintf("creating partition failed: could not find partition.\n");
return NULL;
}
Partition *child = partition->AddChild();
if (child == NULL) { if (child == NULL) {
dprintf("creating partition failed: no memory\n"); dprintf("creating partition failed: no memory\n");
return NULL; return NULL;
@@ -490,11 +525,10 @@ create_child_partition(partition_id id, int32 index, off_t offset, off_t size,
partition_data * partition_data *
get_child_partition(partition_id id, int32 index) get_child_partition(partition_id id, int32 index)
{ {
//Partition &partition = *(Partition *)id;
// TODO: do we really have to implement this? // TODO: do we really have to implement this?
// The intel partition module doesn't really need this for our mission... // The intel partition module doesn't really need this for our mission...
TRACE(("get_child_partition(id = %lu, index = %ld)\n", id, index)); TRACE(("get_child_partition(id = %" B_PRId32 ", index = %" B_PRId32 ")\n",
id, index));
return NULL; return NULL;
} }
@@ -503,8 +537,11 @@ get_child_partition(partition_id id, int32 index)
partition_data * partition_data *
get_parent_partition(partition_id id) get_parent_partition(partition_id id)
{ {
Partition &partition = *(Partition *)id; Partition *partition = Partition::Lookup(id);
if (partition == NULL) {
return partition.Parent(); dprintf("could not find parent partition.\n");
return NULL;
}
return partition->Parent();
} }
+3 -1
View File
@@ -294,7 +294,9 @@ MemoryDisk::MemoryDisk(const uint8* data, size_t size, const char* name)
ssize_t ssize_t
MemoryDisk::ReadAt(void* cookie, off_t pos, void* buffer, size_t bufferSize) MemoryDisk::ReadAt(void* cookie, off_t pos, void* buffer, size_t bufferSize)
{ {
if (pos >= fSize) if (pos < 0)
return B_BAD_VALUE;
if ((size_t)pos >= fSize)
return 0; return 0;
if (pos + bufferSize > fSize) if (pos + bufferSize > fSize)
+1 -1
View File
@@ -49,7 +49,7 @@ BootMergeObject boot_platform_amiga_m68k_other.o :
#decode_edid.c #decode_edid.c
#dump_edid.c #dump_edid.c
: -fno-pic #-Wa,--pcrel : #-Wa,--pcrel
: boot_platform_generic.a : boot_platform_generic.a
; ;
+1 -1
View File
@@ -54,7 +54,7 @@ BootMergeObject boot_platform_atari_m68k_other.o :
#decode_edid.c #decode_edid.c
#dump_edid.c #dump_edid.c
: -fno-pic #-Wa,--pcrel : #-Wa,--pcrel
: boot_platform_generic.a : boot_platform_generic.a
; ;
+3 -1
View File
@@ -1,5 +1,7 @@
SubDir HAIKU_TOP src system boot platform bios_ia32 ; SubDir HAIKU_TOP src system boot platform bios_ia32 ;
SetupFeatureObjectsDir $(TARGET_BOOT_PLATFORM) ;
SubDirHdrs $(HAIKU_TOP) headers private kernel boot platform $(TARGET_BOOT_PLATFORM) ; SubDirHdrs $(HAIKU_TOP) headers private kernel boot platform $(TARGET_BOOT_PLATFORM) ;
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
@@ -47,7 +49,7 @@ BootMergeObject boot_platform_bios_ia32.o :
decode_edid.c decode_edid.c
dump_edid.c dump_edid.c
: -fno-pic :
: boot_platform_generic.a : boot_platform_generic.a
; ;
+59
View File
@@ -0,0 +1,59 @@
SubDir HAIKU_TOP src system boot platform efi ;
SetupFeatureObjectsDir $(TARGET_BOOT_PLATFORM) ;
UsePrivateHeaders [ FDirName kernel boot ] ;
UseBuildFeatureHeaders gnuefi ;
UseBuildFeatureHeaders gnuefi : headersProtocol ;
UseBuildFeatureHeaders gnuefi : headersArch ;
{
local defines = _BOOT_MODE GNU_EFI_USE_MS_ABI _BOOT_PLATFORM_EFI ;
defines = [ FDefines $(defines) ] ;
SubDirCcFlags $(defines) ;
SubDirC++Flags $(defines) -fno-rtti ;
}
local efi_glue_src =
crt0-efi-x86_64.S
;
local platform_src =
relocation_func.cpp
start.cpp
console.cpp
video.cpp
debug.cpp
entry.S
mmu.cpp
heap.cpp
acpi.cpp
menu.cpp
devices.cpp
hpet.cpp
cpu.cpp
smp.cpp
smp_trampoline.S
support.S
;
Includes [ FGristFiles $(efi_glue_src) $(platform_src) ]
:
[ BuildFeatureAttribute gnuefi : headers ]
[ BuildFeatureAttribute gnuefi : headersProtocol ]
[ BuildFeatureAttribute gnuefi : headersArch ]
;
BootMergeObject boot_platform_efi.o :
$(efi_glue_src)
$(platform_src)
:
: boot_platform_generic.a
;
SEARCH on [ FGristFiles relocation_func.cpp ]
= [ FDirName $(SUBDIR) arch $(TARGET_ARCH) ] ;
LOCATE on [ FGristFiles $(efi_glue_src) ]
= [ BuildFeatureAttribute gnuefi : libdir : path ] ;
Depends [ FGristFiles $(efi_glue_src) ]
: [ BuildFeatureAttribute gnuefi : libdir ] ;
+259
View File
@@ -0,0 +1,259 @@
/*
* Copyright 2014, Jessica Hamilton, jessica.l.hamilton@gmail.com.
* Copyright 2011, Rene Gollent, rene@gollent.com.
* Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved.
* Copyright 2007, Michael Lotz, mmlr@mlotz.ch
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#include <string.h>
#include <KernelExport.h>
#include <SupportDefs.h>
#include <arch/x86/arch_acpi.h>
#include <boot/stage2.h>
#include <boot/platform.h>
#include <boot/stdio.h>
#include "efi_platform.h"
#include "acpi.h"
#include "mmu.h"
#define TRACE_ACPI
#ifdef TRACE_ACPI
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
static acpi_descriptor_header* sAcpiRsdt; // System Description Table
static acpi_descriptor_header* sAcpiXsdt; // Extended System Description Table
static int32 sNumEntries = -1;
static status_t
acpi_validate_rsdp(acpi_rsdp* rsdp)
{
const char* data = (const char*)rsdp;
unsigned char checksum = 0;
for (uint32 i = 0; i < sizeof(acpi_rsdp_legacy); i++)
checksum += data[i];
if ((checksum & 0xff) != 0) {
TRACE(("acpi: rsdp failed basic checksum\n"));
return B_BAD_DATA;
}
// for ACPI 2.0+ we need to also validate the extended checksum
if (rsdp->revision > 0) {
for (uint32 i = sizeof(acpi_rsdp_legacy);
i < sizeof(acpi_rsdp_extended); i++) {
checksum += data[i];
}
if ((checksum & 0xff) != 0) {
TRACE(("acpi: rsdp failed extended checksum\n"));
return B_BAD_DATA;
}
}
return B_OK;
}
static status_t
acpi_validate_rsdt(acpi_descriptor_header* rsdt)
{
const char* data = (const char*)rsdt;
unsigned char checksum = 0;
for (uint32 i = 0; i < rsdt->length; i++)
checksum += data[i];
return checksum == 0 ? B_OK : B_BAD_DATA;
}
static status_t
acpi_check_rsdt(acpi_rsdp* rsdp)
{
if (acpi_validate_rsdp(rsdp) != B_OK)
return B_BAD_DATA;
bool usingXsdt = false;
TRACE(("acpi: found rsdp at %p oem id: %.6s, rev %d\n",
rsdp, rsdp->oem_id, rsdp->revision));
TRACE(("acpi: rsdp points to rsdt at 0x%x\n", rsdp->rsdt_address));
uint32 length = 0;
acpi_descriptor_header* rsdt = NULL;
if (rsdp->revision > 0) {
length = rsdp->xsdt_length;
rsdt = (acpi_descriptor_header*)mmu_map_physical_memory(
(uint32)rsdp->xsdt_address, rsdp->xsdt_length, kDefaultPageFlags);
if (rsdt != NULL
&& strncmp(rsdt->signature, ACPI_XSDT_SIGNATURE, 4) != 0) {
mmu_free(rsdt, rsdp->xsdt_length);
rsdt = NULL;
TRACE(("acpi: invalid extended system description table\n"));
} else
usingXsdt = true;
}
// if we're ACPI v1 or we fail to map the XSDT for some reason,
// attempt to use the RSDT instead.
if (rsdt == NULL) {
// map and validate the root system description table
rsdt = (acpi_descriptor_header*)mmu_map_physical_memory(
rsdp->rsdt_address, sizeof(acpi_descriptor_header),
kDefaultPageFlags);
if (rsdt == NULL) {
TRACE(("acpi: couldn't map rsdt header\n"));
return B_ERROR;
}
if (strncmp(rsdt->signature, ACPI_RSDT_SIGNATURE, 4) != 0) {
mmu_free(rsdt, sizeof(acpi_descriptor_header));
rsdt = NULL;
TRACE(("acpi: invalid root system description table\n"));
return B_ERROR;
}
length = rsdt->length;
// Map the whole table, not just the header
TRACE(("acpi: rsdt length: %u\n", length));
mmu_free(rsdt, sizeof(acpi_descriptor_header));
rsdt = (acpi_descriptor_header*)mmu_map_physical_memory(
rsdp->rsdt_address, length, kDefaultPageFlags);
}
if (rsdt != NULL) {
if (acpi_validate_rsdt(rsdt) != B_OK) {
TRACE(("acpi: rsdt failed checksum validation\n"));
mmu_free(rsdt, length);
return B_ERROR;
} else {
if (usingXsdt)
sAcpiXsdt = rsdt;
else
sAcpiRsdt = rsdt;
TRACE(("acpi: found valid %s at %p\n",
usingXsdt ? ACPI_XSDT_SIGNATURE : ACPI_RSDT_SIGNATURE,
rsdt));
}
} else
return B_ERROR;
return B_OK;
}
template<typename PointerType>
acpi_descriptor_header*
acpi_find_table_generic(const char* signature, acpi_descriptor_header* acpiSdt)
{
if (acpiSdt == NULL)
return NULL;
if (sNumEntries == -1) {
// if using the xsdt, our entries are 64 bits wide.
sNumEntries = (acpiSdt->length
- sizeof(acpi_descriptor_header))
/ sizeof(PointerType);
}
if (sNumEntries <= 0) {
TRACE(("acpi: root system description table is empty\n"));
return NULL;
}
TRACE(("acpi: searching %d entries for table '%.4s'\n", sNumEntries,
signature));
PointerType* pointer = (PointerType*)((uint8*)acpiSdt
+ sizeof(acpi_descriptor_header));
acpi_descriptor_header* header = NULL;
for (int32 j = 0; j < sNumEntries; j++, pointer++) {
header = (acpi_descriptor_header*)
mmu_map_physical_memory((uint32)*pointer,
sizeof(acpi_descriptor_header), kDefaultPageFlags);
if (header == NULL
|| strncmp(header->signature, signature, 4) != 0) {
// not interesting for us
TRACE(("acpi: Looking for '%.4s'. Skipping '%.4s'\n",
signature, header != NULL ? header->signature : "null"));
if (header != NULL) {
mmu_free(header, sizeof(acpi_descriptor_header));
header = NULL;
}
continue;
}
TRACE(("acpi: Found '%.4s' @ %p\n", signature, pointer));
break;
}
if (header == NULL)
return NULL;
// Map the whole table, not just the header
uint32 length = header->length;
mmu_free(header, sizeof(acpi_descriptor_header));
return (acpi_descriptor_header*)mmu_map_physical_memory(
(uint32)*pointer, length, kDefaultPageFlags);
}
acpi_descriptor_header*
acpi_find_table(const char* signature)
{
if (sAcpiRsdt != NULL)
return acpi_find_table_generic<uint32>(signature, sAcpiRsdt);
else if (sAcpiXsdt != NULL)
return acpi_find_table_generic<uint64>(signature, sAcpiXsdt);
return NULL;
}
void
acpi_init()
{
EFI_GUID acpi = ACPI_20_TABLE_GUID;
EFI_CONFIGURATION_TABLE *table = kSystemTable->ConfigurationTable;
UINTN entries = kSystemTable->NumberOfTableEntries;
// Try to find the ACPI RSDP.
for (uint32 i = 0; i < entries; i++) {
acpi_rsdp *rsdp = NULL;
EFI_GUID vendor = table[i].VendorGuid;
if (vendor.Data1 == acpi.Data1
&& vendor.Data2 == acpi.Data2
&& vendor.Data3 == acpi.Data3
&& strncmp((char *)vendor.Data4, (char *)acpi.Data4, 8) == 0) {
rsdp = (acpi_rsdp *)(table[i].VendorTable);
if (strncmp((char *)rsdp, ACPI_RSDP_SIGNATURE, 8) == 0)
TRACE(("acpi_init: found ACPI RSDP signature at %p\n", rsdp));
if (rsdp != NULL && acpi_check_rsdt(rsdp) == B_OK) {
gKernelArgs.arch_args.acpi_root = rsdp;
break;
}
}
}
}
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef ACPI_H
#define ACPI_H
#include <SupportDefs.h>
#include <arch/x86/arch_acpi.h>
#ifdef __cplusplus
extern "C" {
#endif
acpi_descriptor_header *acpi_find_table(const char *signature);
void acpi_init(void);
#ifdef __cplusplus
}
#endif
#endif /* ACPI_H */
@@ -0,0 +1,97 @@
/* reloc_x86_64.c - position independent x86_64 ELF shared object relocator
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
Copyright (C) 2005 Intel Co.
Contributed by Fenghua Yu <fenghua.yu@intel.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Hewlett-Packard Co. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, 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 <efi.h>
#include <elf.h>
extern "C" EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn,
EFI_HANDLE image __attribute__((__unused__)),
EFI_SYSTEM_TABLE *systab __attribute__((__unused__)))
{
long relsz = 0, relent = 0;
Elf64_Rel *rel = 0;
unsigned long *addr;
int i;
for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
switch (dyn[i].d_tag) {
case DT_RELA:
rel = (Elf64_Rel*)
((unsigned long)dyn[i].d_un.d_ptr
+ ldbase);
break;
case DT_RELASZ:
relsz = dyn[i].d_un.d_val;
break;
case DT_RELAENT:
relent = dyn[i].d_un.d_val;
break;
default:
break;
}
}
if (!rel && relent == 0)
return EFI_SUCCESS;
if (!rel || relent == 0)
return EFI_LOAD_ERROR;
while (relsz > 0) {
/* apply the relocs */
switch (ELF64_R_TYPE (rel->r_info)) {
case R_X86_64_NONE:
break;
case R_X86_64_RELATIVE:
addr = (unsigned long *)
(ldbase + rel->r_offset);
*addr += ldbase;
break;
default:
break;
}
rel = (Elf64_Rel*) ((char *) rel + relent);
relsz -= relent;
}
return EFI_SUCCESS;
}
+247
View File
@@ -0,0 +1,247 @@
/*
* Copyright 2014-2016 Haiku, Inc. All rights reserved.
* Copyright 2013 Fredrik Holmqvist, fredrik.holmqvist@gmail.com. All rights
* reserved.
* Distributed under the terms of the MIT License.
*/
#include "console.h"
#include <string.h>
#include <SupportDefs.h>
#include <boot/stage2.h>
#include <boot/platform.h>
#include <util/kernel_cpp.h>
#include "efi_platform.h"
class Console : public ConsoleNode {
public:
Console();
virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
size_t bufferSize);
virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer,
size_t bufferSize);
};
static uint32 sScreenWidth;
static uint32 sScreenHeight;
static uint32 sScreenMode;
static Console sInput, sOutput;
FILE *stdin, *stdout, *stderr;
// #pragma mark -
Console::Console()
: ConsoleNode()
{
}
ssize_t
Console::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
{
return B_ERROR;
}
ssize_t
Console::WriteAt(void *cookie, off_t /*pos*/, const void *buffer,
size_t bufferSize)
{
const char *string = (const char *)buffer;
CHAR16 ucsBuffer[bufferSize + 3];
uint32 j = 0;
for (uint32 i = 0; i < bufferSize; i++) {
switch (string[i]) {
case '\n': {
ucsBuffer[j++] = '\r';
ucsBuffer[j++] = '\n';
} //fallthrough
case 0 : {
//Not sure if we should keep going or abort for 0.
//Keep going was easy anyway.
ucsBuffer[j] = 0;
kSystemTable->ConOut->OutputString(kSystemTable->ConOut,
ucsBuffer);
j = 0;
continue;
}
default:
ucsBuffer[j++] = (CHAR16) string[i];
}
}
if (j > 0) {
ucsBuffer[j] = 0;
kSystemTable->ConOut->OutputString(kSystemTable->ConOut, ucsBuffer);
}
return bufferSize;
}
// #pragma mark -
void
console_clear_screen(void)
{
kSystemTable->ConOut->ClearScreen(kSystemTable->ConOut);
}
int32
console_width(void)
{
return sScreenWidth;
}
int32
console_height(void)
{
return sScreenHeight;
}
void
console_set_cursor(int32 x, int32 y)
{
kSystemTable->ConOut->SetCursorPosition(kSystemTable->ConOut, x, y);
}
void
console_show_cursor(void)
{
kSystemTable->ConOut->EnableCursor(kSystemTable->ConOut, true);
}
void
console_hide_cursor(void)
{
kSystemTable->ConOut->EnableCursor(kSystemTable->ConOut, false);
}
void
console_set_color(int32 foreground, int32 background)
{
kSystemTable->ConOut->SetAttribute(kSystemTable->ConOut,
EFI_TEXT_ATTR((foreground & 0xf), (background & 0xf)));
}
int
console_wait_for_key(void)
{
UINTN index;
EFI_STATUS status;
EFI_INPUT_KEY key;
EFI_EVENT event = kSystemTable->ConIn->WaitForKey;
do {
kBootServices->WaitForEvent(1, &event, &index);
status = kSystemTable->ConIn->ReadKeyStroke(kSystemTable->ConIn, &key);
} while (status == EFI_NOT_READY);
if (key.UnicodeChar > 0)
return (int) key.UnicodeChar;
switch (key.ScanCode) {
case SCAN_UP:
return TEXT_CONSOLE_KEY_UP;
case SCAN_DOWN:
return TEXT_CONSOLE_KEY_DOWN;
case SCAN_LEFT:
return TEXT_CONSOLE_KEY_LEFT;
case SCAN_RIGHT:
return TEXT_CONSOLE_KEY_RIGHT;
case SCAN_PAGE_UP:
return TEXT_CONSOLE_KEY_PAGE_UP;
case SCAN_PAGE_DOWN:
return TEXT_CONSOLE_KEY_PAGE_DOWN;
case SCAN_HOME:
return TEXT_CONSOLE_KEY_HOME;
case SCAN_END:
return TEXT_CONSOLE_KEY_END;
}
return 0;
}
static void update_screen_size(void)
{
UINTN width, height;
UINTN area = 0;
SIMPLE_TEXT_OUTPUT_INTERFACE *ConOut = kSystemTable->ConOut;
for (int mode = 0; mode < ConOut->Mode->MaxMode; ++mode) {
if (ConOut->QueryMode(ConOut, mode, &width, &height) == EFI_SUCCESS) {
if (width * height > area) {
sScreenWidth = width;
sScreenHeight = height;
sScreenMode = mode;
}
}
}
ConOut->SetMode(ConOut, sScreenMode);
}
status_t
console_init(void)
{
update_screen_size();
console_hide_cursor();
console_clear_screen();
// enable stdio functionality
stdin = (FILE *)&sInput;
stdout = stderr = (FILE *)&sOutput;
return B_OK;
}
uint32
console_check_boot_keys(void)
{
EFI_STATUS status;
EFI_INPUT_KEY key;
// give the user a chance to press a key
kBootServices->Stall(500000);
status = kSystemTable->ConIn->ReadKeyStroke(kSystemTable->ConIn, &key);
if (status != EFI_SUCCESS)
return 0;
if (key.UnicodeChar == 0 && key.ScanCode == SCAN_ESC)
return BOOT_OPTION_DEBUG_OUTPUT;
if (key.UnicodeChar == ' ')
return BOOT_OPTION_MENU;
return 0;
}
extern "C" void
platform_switch_to_text_mode(void)
{
kSystemTable->ConOut->Reset(kSystemTable->ConOut, false);
kSystemTable->ConOut->SetMode(kSystemTable->ConOut, sScreenMode);
gKernelArgs.frame_buffer.enabled = false;
}
+16
View File
@@ -0,0 +1,16 @@
/*
** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
** Distributed under the terms of the Haiku License.
*/
#ifndef CONSOLE_H
#define CONSOLE_H
#include <boot/platform/generic/text_console.h>
status_t console_init(void);
uint32 console_check_boot_keys(void);
#endif /* CONSOLE_H */
+349
View File
@@ -0,0 +1,349 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*
* calculate_cpu_conversion_factor() was written by Travis Geiselbrecht and
* licensed under the NewOS license.
*/
#include "cpu.h"
#include "efi_platform.h"
#include <OS.h>
#include <boot/platform.h>
#include <boot/stdio.h>
#include <boot/kernel_args.h>
#include <boot/stage2.h>
#include <arch/cpu.h>
#include <arch_kernel.h>
#include <arch_system_info.h>
#include <string.h>
//#define TRACE_CPU
#ifdef TRACE_CPU
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
extern "C" uint64 rdtsc();
uint32 gTimeConversionFactor;
// PIT definitions
#define TIMER_CLKNUM_HZ (14318180 / 12)
// PIT IO Ports
#define PIT_CHANNEL_PORT_BASE 0x40
#define PIT_CONTROL 0x43
// Channel selection
#define PIT_SELECT_CHANNEL_SHIFT 6
// Access mode
#define PIT_ACCESS_LATCH_COUNTER (0 << 4)
#define PIT_ACCESS_LOW_BYTE_ONLY (1 << 4)
#define PIT_ACCESS_HIGH_BYTE_ONLY (2 << 4)
#define PIT_ACCESS_LOW_THEN_HIGH_BYTE (3 << 4)
// Operating modes
#define PIT_MODE_INTERRUPT_ON_0 (0 << 1)
#define PIT_MODE_HARDWARE_COUNTDOWN (1 << 1)
#define PIT_MODE_RATE_GENERATOR (2 << 1)
#define PIT_MODE_SQUARE_WAVE_GENERATOR (3 << 1)
#define PIT_MODE_SOFTWARE_STROBE (4 << 1)
#define PIT_MODE_HARDWARE_STROBE (5 << 1)
// BCD/Binary mode
#define PIT_BINARY_MODE 0
#define PIT_BCD_MODE 1
// Channel 2 control (speaker)
#define PIT_CHANNEL_2_CONTROL 0x61
#define PIT_CHANNEL_2_GATE_HIGH 0x01
#define PIT_CHANNEL_2_SPEAKER_OFF_MASK ~0x02
// Maximum values
#define MAX_QUICK_SAMPLES 20
#define MAX_SLOW_SAMPLES 20
// TODO: These are arbitrary. They are here to avoid spinning indefinitely
// if the TSC just isn't stable and we can't get our desired error range.
#define CPUID_EFLAGS (1UL << 21)
#define RDTSC_FEATURE (1UL << 4)
struct uint128 {
uint128(uint64 low, uint64 high = 0)
:
low(low),
high(high)
{
}
bool operator<(const uint128& other) const
{
return high < other.high || (high == other.high && low < other.low);
}
bool operator<=(const uint128& other) const
{
return !(other < *this);
}
uint128 operator<<(int count) const
{
if (count == 0)
return *this;
if (count >= 128)
return 0;
if (count >= 64)
return uint128(0, low << (count - 64));
return uint128(low << count, (high << count) | (low >> (64 - count)));
}
uint128 operator>>(int count) const
{
if (count == 0)
return *this;
if (count >= 128)
return 0;
if (count >= 64)
return uint128(high >> (count - 64), 0);
return uint128((low >> count) | (high << (64 - count)), high >> count);
}
uint128 operator+(const uint128& other) const
{
uint64 resultLow = low + other.low;
return uint128(resultLow,
high + other.high + (resultLow < low ? 1 : 0));
}
uint128 operator-(const uint128& other) const
{
uint64 resultLow = low - other.low;
return uint128(resultLow,
high - other.high - (resultLow > low ? 1 : 0));
}
uint128 operator*(uint32 other) const
{
uint64 resultMid = (low >> 32) * other;
uint64 resultLow = (low & 0xffffffff) * other + (resultMid << 32);
return uint128(resultLow,
high * other + (resultMid >> 32)
+ (resultLow < resultMid << 32 ? 1 : 0));
}
uint128 operator/(const uint128& other) const
{
int shift = 0;
uint128 shiftedDivider = other;
while (shiftedDivider.high >> 63 == 0 && shiftedDivider < *this) {
shiftedDivider = shiftedDivider << 1;
shift++;
}
uint128 result = 0;
uint128 temp = *this;
for (; shift >= 0; shift--, shiftedDivider = shiftedDivider >> 1) {
if (shiftedDivider <= temp) {
result = result + (uint128(1) << shift);
temp = temp - shiftedDivider;
}
}
return result;
}
operator uint64() const
{
return low;
}
private:
uint64 low;
uint64 high;
};
static inline void
calibration_loop(uint8 desiredHighByte, uint8 channel, uint64& tscDelta,
double& conversionFactor, uint16& expired)
{
uint8 select = channel << PIT_SELECT_CHANNEL_SHIFT;
out8(select | PIT_ACCESS_LOW_THEN_HIGH_BYTE | PIT_MODE_INTERRUPT_ON_0
| PIT_BINARY_MODE, PIT_CONTROL);
// Fill in count of 0xffff, low then high byte
uint8 channelPort = PIT_CHANNEL_PORT_BASE + channel;
out8(0xff, channelPort);
out8(0xff, channelPort);
// Read the count back once to delay the start. This ensures that we've
// waited long enough for the counter to actually start counting down, as
// this only happens on the next clock cycle after reload.
in8(channelPort);
in8(channelPort);
// We're expecting the PIT to be at the starting position (high byte 0xff)
// as we just programmed it, but if it isn't we wait for it to wrap.
uint8 startLow;
uint8 startHigh;
do {
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
startLow = in8(channelPort);
startHigh = in8(channelPort);
} while (startHigh != 255);
// Read in the first TSC value
uint64 startTSC = rdtsc();
// Wait for the PIT to count down to our desired value
uint8 endLow;
uint8 endHigh;
do {
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
endLow = in8(channelPort);
endHigh = in8(channelPort);
} while (endHigh > desiredHighByte);
// And read the second TSC value
uint64 endTSC = rdtsc();
tscDelta = endTSC - startTSC;
expired = ((startHigh << 8) | startLow) - ((endHigh << 8) | endLow);
conversionFactor = (double)tscDelta / (double)expired;
}
static void
calculate_cpu_conversion_factor()
{
uint8 channel = 2;
// When using channel 2, enable the input and disable the speaker.
if (channel == 2) {
uint8 control = in8(PIT_CHANNEL_2_CONTROL);
control &= PIT_CHANNEL_2_SPEAKER_OFF_MASK;
control |= PIT_CHANNEL_2_GATE_HIGH;
out8(control, PIT_CHANNEL_2_CONTROL);
}
uint64 tscDeltaQuick, tscDeltaSlower, tscDeltaSlow;
double conversionFactorQuick, conversionFactorSlower, conversionFactorSlow;
uint16 expired;
uint32 quickSampleCount = 1;
uint32 slowSampleCount = 1;
quick_sample:
calibration_loop(224, channel, tscDeltaQuick, conversionFactorQuick,
expired);
slower_sample:
calibration_loop(192, channel, tscDeltaSlower, conversionFactorSlower,
expired);
double deviation = conversionFactorQuick / conversionFactorSlower;
if (deviation < 0.99 || deviation > 1.01) {
// We might have been hit by a SMI or were otherwise stalled
if (quickSampleCount++ < MAX_QUICK_SAMPLES)
goto quick_sample;
}
// Slow sample
calibration_loop(128, channel, tscDeltaSlow, conversionFactorSlow,
expired);
deviation = conversionFactorSlower / conversionFactorSlow;
if (deviation < 0.99 || deviation > 1.01) {
// We might have been hit by a SMI or were otherwise stalled
if (slowSampleCount++ < MAX_SLOW_SAMPLES)
goto slower_sample;
}
// Scale the TSC delta to timer units
tscDeltaSlow *= TIMER_CLKNUM_HZ;
uint64 clockSpeed = tscDeltaSlow / expired;
gTimeConversionFactor = ((uint128(expired) * uint32(1000000)) << 32)
/ uint128(tscDeltaSlow);
#ifdef TRACE_CPU
if (clockSpeed > 1000000000LL) {
dprintf("CPU at %Ld.%03Ld GHz\n", clockSpeed / 1000000000LL,
(clockSpeed % 1000000000LL) / 1000000LL);
} else {
dprintf("CPU at %Ld.%03Ld MHz\n", clockSpeed / 1000000LL,
(clockSpeed % 1000000LL) / 1000LL);
}
#endif
gKernelArgs.arch_args.system_time_cv_factor = gTimeConversionFactor;
gKernelArgs.arch_args.cpu_clock_speed = clockSpeed;
//dprintf("factors: %lu %llu\n", gTimeConversionFactor, clockSpeed);
if (quickSampleCount > 1) {
dprintf("needed %u quick samples for TSC calibration\n",
quickSampleCount);
}
if (slowSampleCount > 1) {
dprintf("needed %u slow samples for TSC calibration\n",
slowSampleCount);
}
if (channel == 2) {
// Set the gate low again
out8(in8(PIT_CHANNEL_2_CONTROL) & ~PIT_CHANNEL_2_GATE_HIGH,
PIT_CHANNEL_2_CONTROL);
}
}
// #pragma mark -
extern "C" bigtime_t
system_time()
{
uint64 lo, hi;
asm("rdtsc": "=a"(lo), "=d"(hi));
return ((lo * gTimeConversionFactor) >> 32) + hi * gTimeConversionFactor;
}
extern "C" void
spin(bigtime_t microseconds)
{
bigtime_t time = system_time();
while ((system_time() - time) < microseconds)
asm volatile ("pause;");
}
extern "C" void
cpu_init()
{
calculate_cpu_conversion_factor();
gKernelArgs.num_cpus = 1;
// this will eventually be corrected later on
}
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef CPU_H
#define CPU_H
#include <SupportDefs.h>
#ifdef __cplusplus
extern "C" {
#endif
extern void cpu_init(void);
#ifdef __cplusplus
}
#endif
#endif /* CPU_H */
+44
View File
@@ -0,0 +1,44 @@
/*
* Copyright 2016 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <string.h>
#include <boot/platform.h>
#include <boot/stage2.h>
#include <boot/stdio.h>
#include "efi_platform.h"
extern "C" void
dprintf(const char *format, ...)
{
}
extern "C" void
panic(const char *format, ...)
{
va_list args;
platform_switch_to_text_mode();
puts("*** PANIC ***");
va_start(args, format);
vprintf(format, args);
va_end(args);
while (true)
kBootServices->Stall(1000000);
}
char*
platform_debug_get_log_buffer(size_t *_size)
{
return NULL;
}
+242
View File
@@ -0,0 +1,242 @@
/*
* Copyright 2016 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <boot/partitions.h>
#include <boot/platform.h>
#include <boot/stage2.h>
#include "efi_platform.h"
class EfiDevice : public Node
{
public:
EfiDevice(EFI_BLOCK_IO *blockIo, EFI_DEVICE_PATH *devicePath);
virtual ~EfiDevice();
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) { return B_UNSUPPORTED; }
virtual off_t Size() const { return fSize; }
uint32 BlockSize() const { return fBlockSize; }
private:
EFI_BLOCK_IO* fBlockIo;
EFI_DEVICE_PATH* fDevicePath;
uint32 fBlockSize;
uint64 fSize;
};
EfiDevice::EfiDevice(EFI_BLOCK_IO *blockIo, EFI_DEVICE_PATH *devicePath)
:
fBlockIo(blockIo),
fDevicePath(devicePath)
{
fBlockSize = fBlockIo->Media->BlockSize;
fSize = (fBlockIo->Media->LastBlock + 1) * fBlockSize;
}
EfiDevice::~EfiDevice()
{
}
ssize_t
EfiDevice::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
{
uint32 offset = pos % fBlockSize;
pos /= fBlockSize;
uint32 numBlocks = (offset + bufferSize + fBlockSize) / fBlockSize;
char readBuffer[numBlocks * fBlockSize];
EFI_STATUS status = fBlockIo->ReadBlocks(fBlockIo, fBlockIo->Media->MediaId,
pos, sizeof(readBuffer), readBuffer);
if (status != EFI_SUCCESS)
return B_ERROR;
memcpy(buffer, readBuffer + offset, bufferSize);
return bufferSize;
}
static EFI_DEVICE_PATH*
find_device_path(EFI_DEVICE_PATH *devicePath, uint16 type, uint16 subType)
{
EFI_DEVICE_PATH *node = devicePath;
while (!IsDevicePathEnd(node)) {
if (DevicePathType(node) == type
&& (subType == 0xFFFF || DevicePathSubType(node) == subType))
return node;
node = NextDevicePathNode(node);
}
return NULL;
}
static status_t
add_boot_devices(NodeList *devicesList)
{
EFI_GUID blockIoGuid = BLOCK_IO_PROTOCOL;
EFI_GUID devicePathGuid = DEVICE_PATH_PROTOCOL;
EFI_BLOCK_IO *blockIo;
EFI_DEVICE_PATH *devicePath, *node, *targetDevicePath = NULL;
EFI_HANDLE *handles = NULL;
EFI_STATUS status;
UINTN size = 0;
status = kBootServices->LocateHandle(ByProtocol, &blockIoGuid, 0, &size, 0);
if (status != EFI_BUFFER_TOO_SMALL)
return B_ENTRY_NOT_FOUND;
handles = (EFI_HANDLE*)malloc(size);
status = kBootServices->LocateHandle(ByProtocol, &blockIoGuid, 0, &size,
handles);
if (status != EFI_SUCCESS) {
if (handles != NULL)
free(handles);
return B_ENTRY_NOT_FOUND;
}
for (int n = (size / sizeof(EFI_HANDLE)) - 1; n >= 0; --n) {
status = kBootServices->HandleProtocol(handles[n], &devicePathGuid,
(void**)&devicePath);
if (status != EFI_SUCCESS)
continue;
node = devicePath;
while (!IsDevicePathEnd(NextDevicePathNode(node)))
node = NextDevicePathNode(node);
if (DevicePathType(node) == MEDIA_DEVICE_PATH
&& DevicePathSubType(node) == MEDIA_CDROM_DP) {
targetDevicePath = find_device_path(devicePath,
MESSAGING_DEVICE_PATH, 0xFFFF);
continue;
}
if (DevicePathType(node) != MESSAGING_DEVICE_PATH)
continue;
status = kBootServices->HandleProtocol(handles[n], &blockIoGuid,
(void**)&blockIo);
if (status != EFI_SUCCESS || !blockIo->Media->MediaPresent)
continue;
EfiDevice *device = new(std::nothrow)EfiDevice(blockIo, devicePath);
if (device == NULL)
continue;
if (targetDevicePath != NULL
&& memcmp(targetDevicePath, node, DevicePathNodeLength(node)) == 0)
devicesList->InsertBefore(devicesList->Head(), device);
else
devicesList->Insert(device);
targetDevicePath = NULL;
}
return devicesList->Count() > 0 ? B_OK : B_ENTRY_NOT_FOUND;
}
static off_t
get_next_check_sum_offset(int32 index, off_t maxSize)
{
if (index < 2)
return index * 512;
if (index < 4)
return (maxSize >> 10) + index * 2048;
//return ((system_time() + index) % (maxSize >> 9)) * 512;
return 42 * 512;
}
static uint32
compute_check_sum(Node *device, off_t offset)
{
char buffer[512];
ssize_t bytesRead = device->ReadAt(NULL, offset, buffer, sizeof(buffer));
if (bytesRead < B_OK)
return 0;
if (bytesRead < (ssize_t)sizeof(buffer))
memset(buffer + bytesRead, 0, sizeof(buffer) - bytesRead);
uint32 *array = (uint32*)buffer;
uint32 sum = 0;
for (uint32 i = 0; i < (bytesRead + sizeof(uint32) - 1) / sizeof(uint32); i++)
sum += array[i];
return sum;
}
status_t
platform_add_boot_device(struct stage2_args *args, NodeList *devicesList)
{
// TODO: get GUID of partition to boot, and support for SATA/ATA devices
return add_boot_devices(devicesList);
}
status_t
platform_add_block_devices(struct stage2_args *args, NodeList *devicesList)
{
// add_boot_devices will add all available devices, so nothing to do here
return B_OK;
}
status_t
platform_get_boot_partition(struct stage2_args *args, Node *bootDevice,
NodeList *partitions, boot::Partition **_partition)
{
NodeIterator it = partitions->GetIterator();
while (it.HasNext()) {
boot::Partition *partition = (boot::Partition*)it.Next();
// we're only looking for CDs atm, so just return first found
*_partition = partition;
return B_OK;
}
return B_ERROR;
}
status_t
platform_register_boot_device(Node *device)
{
disk_identifier identifier;
identifier.bus_type = UNKNOWN_BUS;
identifier.device_type = UNKNOWN_DEVICE;
identifier.device.unknown.size = device->Size();
for (uint32 i = 0; i < NUM_DISK_CHECK_SUMS; ++i) {
off_t offset = get_next_check_sum_offset(i, device->Size());
identifier.device.unknown.check_sums[i].offset = offset;
identifier.device.unknown.check_sums[i].sum = compute_check_sum(device, offset);
}
gBootVolume.SetInt32(BOOT_METHOD, BOOT_METHOD_CD);
gBootVolume.SetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, true);
gBootVolume.SetData(BOOT_VOLUME_DISK_IDENTIFIER, B_RAW_TYPE,
&identifier, sizeof(disk_identifier));
return B_OK;
}
@@ -0,0 +1,23 @@
/*
* Copyright 2013, Fredrik Homlqvist, fredrik.holmqvist@gmail.com.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef EFI_PLATFORM_H
#define EFI_PLATFORM_H
#include "efibind.h"
#include "efidef.h"
#include "efidevp.h"
#include "efiprot.h"
#include "eficon.h"
#include "efierr.h"
#include "efiapi.h"
extern const EFI_SYSTEM_TABLE *kSystemTable;
extern const EFI_BOOT_SERVICES *kBootServices;
extern const EFI_RUNTIME_SERVICES *kRuntimeServices;
#endif /* EFI_PLATFORM_H */
+69
View File
@@ -0,0 +1,69 @@
/*
* Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
* Copyright 2014, Henry Harrington, henry.harrington@gmail.com.
* Distributed under the terms of the MIT License.
*/
#include <asm_defs.h>
#define __x86_64__
#include <arch/x86/descriptors.h>
#include "mmu.h"
#undef __x86_64__
#define GDT_LIMIT 0x800
.code64
/*! void efi_enter_kernel(uint64 pml4, uint64 entry_point, uint64 stackTop); */
FUNCTION(efi_enter_kernel):
// Point CR3 to the kernel's PML4.
movq %rdi, %cr3
// Load 64-bit enabled GDT
lgdtq gLongGDTR(%rip)
// Jump into the 64-bit code segment.
push $KERNEL_CODE_SELECTOR
lea .Llmode(%rip), %rax
push %rax
lretq
.align 8
.code64
.Llmode:
// Set data segments.
mov $KERNEL_DATA_SELECTOR, %ax
mov %ax, %ss
xor %ax, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
// Set the stack pointer.
movq %rdx, %rsp
// Clear the stack frame/RFLAGS.
xorq %rbp, %rbp
push $2
popf
// Get arguments and call the kernel entry point.
mov %rsi, %rax // entry point
leaq gKernelArgs(%rip), %rdi
xorl %esi, %esi // current cpu
call *%rax
.data
SYMBOL(gLongGDTR):
.word BOOT_GDT_SEGMENT_COUNT * 8 - 1
SYMBOL(gLongGDT):
.quad 0
+40
View File
@@ -0,0 +1,40 @@
/*
* Copyright 2016 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <boot/platform.h>
#include <boot/stage2.h>
#include "efi_platform.h"
#define STAGE_PAGES 0x2000 /* 32 MB */
static EFI_PHYSICAL_ADDRESS staging;
extern "C" void
platform_release_heap(struct stage2_args *args, void *base)
{
if ((void*)staging != base)
panic("Attempt to release heap with wrong base address!");
kBootServices->FreePages(staging, STAGE_PAGES);
}
extern "C" status_t
platform_init_heap(struct stage2_args *args, void **_base, void **_top)
{
if (kBootServices->AllocatePages(AllocateAnyPages, EfiLoaderData,
STAGE_PAGES, &staging) != EFI_SUCCESS)
return B_NO_MEMORY;
*_base = (void*)staging;
*_top = (void*)((int8*)staging + STAGE_PAGES * PAGE_SIZE);
return B_OK;
}
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#include "mmu.h"
#include "acpi.h"
#include "hpet.h"
#include <KernelExport.h>
#include <kernel.h>
#include <safemode.h>
#include <boot/stage2.h>
#include <boot/menu.h>
#include <arch/x86/arch_acpi.h>
#include <arch/x86/arch_hpet.h>
#include <arch/x86/arch_system_info.h>
#include <string.h>
//#define TRACE_HPET
#ifdef TRACE_HPET
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
void
hpet_init(void)
{
// Try to find the HPET ACPI table.
TRACE(("hpet_init: Looking for HPET...\n"));
acpi_hpet *hpet = (acpi_hpet *)acpi_find_table(ACPI_HPET_SIGNATURE);
if (hpet == NULL) {
// No HPET table in the RSDT.
// Since there are no other methods for finding it,
// assume we don't have one.
TRACE(("hpet_init: HPET not found.\n"));
gKernelArgs.arch_args.hpet_phys = 0;
gKernelArgs.arch_args.hpet = NULL;
return;
}
TRACE(("hpet_init: found HPET at %x.\n", hpet->hpet_address.address));
gKernelArgs.arch_args.hpet_phys = hpet->hpet_address.address;
gKernelArgs.arch_args.hpet = (void *)mmu_map_physical_memory(
gKernelArgs.arch_args.hpet_phys, B_PAGE_SIZE, EfiACPIReclaimMemory);
}
+21
View File
@@ -0,0 +1,21 @@
/*
* Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef HPET_H
#define HPET_H
#include <SupportDefs.h>
#include <arch/x86/arch_hpet.h>
#ifdef __cplusplus
extern "C" {
#endif
void hpet_init(void);
#ifdef __cplusplus
}
#endif
#endif /* HPET_H */
+40
View File
@@ -0,0 +1,40 @@
/*
* Copyright 2016 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <boot/menu.h>
#include <boot/platform/generic/text_menu.h>
#include "efi_platform.h"
void
platform_add_menus(Menu *menu)
{
// No platform specific menus
}
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);
}
+381
View File
@@ -0,0 +1,381 @@
/*
* Copyright 2016 Haiku, Inc. All rights reserved.
* Copyright 2014, Jessica Hamilton, jessica.l.hamilton@gmail.com.
* Copyright 2014, Henry Harrington, henry.harrington@gmail.com.
* Distributed under the terms of the MIT License.
*/
#include <algorithm>
#include <boot/platform.h>
#include <boot/stage2.h>
#include <kernel/arch/x86/arch_kernel.h>
#include <kernel/kernel.h>
#include "efi_platform.h"
#include "mmu.h"
struct allocated_memory_region {
allocated_memory_region *next;
uint64_t vaddr;
uint64_t paddr;
size_t size;
bool released;
};
static uint64_t next_virtual_address = KERNEL_LOAD_BASE_64_BIT + 32 * 1024 * 1024;
static allocated_memory_region *allocated_memory_regions = NULL;
static uint64_t mmu_allocate_page()
{
EFI_PHYSICAL_ADDRESS addr;
EFI_STATUS s = kBootServices->AllocatePages(AllocateAnyPages, EfiLoaderData, 1, &addr);
if (s != EFI_SUCCESS)
panic("Unabled to allocate memory: %li", s);
return addr;
}
uint64_t
mmu_generate_post_efi_page_tables(UINTN memory_map_size,
EFI_MEMORY_DESCRIPTOR *memory_map, UINTN descriptor_size,
UINTN descriptor_version)
{
// Generate page tables, matching bios_ia32/long.cpp.
uint64_t *pml4;
uint64_t *pdpt;
uint64_t *pageDir;
uint64_t *pageTable;
// Allocate the top level PML4.
pml4 = NULL;
if (platform_allocate_region((void**)&pml4, B_PAGE_SIZE, 0, false) != B_OK)
panic("Failed to allocate PML4.");
gKernelArgs.arch_args.phys_pgdir = (uint32_t)(addr_t)pml4;
memset(pml4, 0, B_PAGE_SIZE);
platform_bootloader_address_to_kernel_address(pml4, &gKernelArgs.arch_args.vir_pgdir);
// Store the virtual memory usage information.
gKernelArgs.virtual_allocated_range[0].start = KERNEL_LOAD_BASE_64_BIT;
gKernelArgs.virtual_allocated_range[0].size = next_virtual_address - KERNEL_LOAD_BASE_64_BIT;
gKernelArgs.num_virtual_allocated_ranges = 1;
gKernelArgs.arch_args.virtual_end = ROUNDUP(KERNEL_LOAD_BASE_64_BIT
+ gKernelArgs.virtual_allocated_range[0].size, 0x200000);
// Find the highest physical memory address. We map all physical memory
// into the kernel address space, so we want to make sure we map everything
// we have available.
uint64 maxAddress = 0;
for (UINTN i = 0; i < memory_map_size / descriptor_size; ++i) {
EFI_MEMORY_DESCRIPTOR *entry = (EFI_MEMORY_DESCRIPTOR *)((addr_t)memory_map + i * descriptor_size);
maxAddress = std::max(maxAddress,
entry->PhysicalStart + entry->NumberOfPages * 4096);
}
// Want to map at least 4GB, there may be stuff other than usable RAM that
// could be in the first 4GB of physical address space.
maxAddress = std::max(maxAddress, (uint64)0x100000000ll);
maxAddress = ROUNDUP(maxAddress, 0x40000000);
// Currently only use 1 PDPT (512GB). This will need to change if someone
// wants to use Haiku on a box with more than 512GB of RAM but that's
// probably not going to happen any time soon.
if (maxAddress / 0x40000000 > 512)
panic("Can't currently support more than 512GB of RAM!");
// Create page tables for the physical map area. Also map this PDPT
// temporarily at the bottom of the address space so that we are identity
// mapped.
pdpt = (uint64*)mmu_allocate_page();
memset(pdpt, 0, B_PAGE_SIZE);
pml4[510] = (addr_t)pdpt | kTableMappingFlags;
pml4[0] = (addr_t)pdpt | kTableMappingFlags;
for (uint64 i = 0; i < maxAddress; i += 0x40000000) {
pageDir = (uint64*)mmu_allocate_page();
memset(pageDir, 0, B_PAGE_SIZE);
pdpt[i / 0x40000000] = (addr_t)pageDir | kTableMappingFlags;
for (uint64 j = 0; j < 0x40000000; j += 0x200000) {
pageDir[j / 0x200000] = (i + j) | kLargePageMappingFlags;
}
}
// Allocate tables for the kernel mappings.
pdpt = (uint64*)mmu_allocate_page();
memset(pdpt, 0, B_PAGE_SIZE);
pml4[511] = (addr_t)pdpt | kTableMappingFlags;
pageDir = (uint64*)mmu_allocate_page();
memset(pageDir, 0, B_PAGE_SIZE);
pdpt[510] = (addr_t)pageDir | kTableMappingFlags;
// We can now allocate page tables and duplicate the mappings across from
// the 32-bit address space to them.
pageTable = NULL; // shush, compiler.
for (uint32 i = 0; i < gKernelArgs.virtual_allocated_range[0].size
/ B_PAGE_SIZE; i++) {
if ((i % 512) == 0) {
pageTable = (uint64*)mmu_allocate_page();
memset(pageTable, 0, B_PAGE_SIZE);
pageDir[i / 512] = (addr_t)pageTable | kTableMappingFlags;
}
// Get the physical address to map.
void *phys;
if (platform_kernel_address_to_bootloader_address(KERNEL_LOAD_BASE_64_BIT + (i * B_PAGE_SIZE),
&phys) != B_OK)
continue;
pageTable[i % 512] = (addr_t)phys | kPageMappingFlags;
}
return (uint64)pml4;
}
// Called after EFI boot services exit.
// Currently assumes that the memory map is sane... Sorted and no overlapping
// regions.
void
mmu_post_efi_setup(UINTN memory_map_size, EFI_MEMORY_DESCRIPTOR *memory_map, UINTN descriptor_size, UINTN descriptor_version)
{
// Add physical memory to the kernel args and update virtual addresses for EFI regions..
addr_t addr = (addr_t)memory_map;
gKernelArgs.num_physical_memory_ranges = 0;
for (UINTN i = 0; i < memory_map_size / descriptor_size; ++i) {
EFI_MEMORY_DESCRIPTOR *entry = (EFI_MEMORY_DESCRIPTOR *)(addr + i * descriptor_size);
switch (entry->Type) {
case EfiLoaderCode:
case EfiLoaderData:
case EfiBootServicesCode:
case EfiBootServicesData:
case EfiConventionalMemory: {
// Usable memory.
// Ignore memory below 1MB and above 512GB.
uint64_t base = entry->PhysicalStart;
uint64_t end = entry->PhysicalStart + entry->NumberOfPages * 4096;
if (base < 0x100000)
base = 0x100000;
if (end > (512ull * 1024 * 1024 * 1024))
end = 512ull * 1024 * 1024 * 1024;
if (base >= end)
break;
uint64_t size = end - base;
insert_physical_memory_range(base, size);
// LoaderData memory is bootloader allocated memory, possibly
// containing the kernel or loaded drivers.
if (entry->Type == EfiLoaderData)
insert_physical_allocated_range(base, size);
break;
}
case EfiACPIReclaimMemory:
// ACPI reclaim -- physical memory we could actually use later
gKernelArgs.ignored_physical_memory += entry->NumberOfPages * 4096;
break;
case EfiRuntimeServicesCode:
case EfiRuntimeServicesData:
entry->VirtualStart = entry->PhysicalStart + 0xFFFFFF0000000000ull;
break;
}
}
// Sort the address ranges.
sort_address_ranges(gKernelArgs.physical_memory_range,
gKernelArgs.num_physical_memory_ranges);
sort_address_ranges(gKernelArgs.physical_allocated_range,
gKernelArgs.num_physical_allocated_ranges);
sort_address_ranges(gKernelArgs.virtual_allocated_range,
gKernelArgs.num_virtual_allocated_ranges);
// Switch EFI to virtual mode, using the kernel pmap.
// Something involving ConvertPointer might need to be done after this?
// http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#SetVirtualAddressMap.28.29
kRuntimeServices->SetVirtualAddressMap(memory_map_size, descriptor_size, descriptor_version, memory_map);
}
// Platform allocator.
// The bootloader assumes that bootloader address space == kernel address space.
// This is not true until just before the kernel is booted, so an ugly hack is
// used to cover the difference. platform_allocate_region allocates addresses
// in bootloader space, but can convert them to kernel space. The ELF loader
// accesses kernel memory via Mao(), and much later in the boot process,
// addresses in the kernel argument struct are converted from bootloader
// addresses to kernel addresses.
extern "C" status_t
platform_allocate_region(void **_address, size_t size, uint8 /* protection */, bool exactAddress)
{
// We don't have any control over the page tables, give up right away if an
// exactAddress is wanted.
if (exactAddress)
return B_NO_MEMORY;
EFI_PHYSICAL_ADDRESS addr;
size_t aligned_size = ROUNDUP(size, B_PAGE_SIZE);
allocated_memory_region *region = new(std::nothrow) allocated_memory_region;
if (region == NULL)
return B_NO_MEMORY;
EFI_STATUS status = kBootServices->AllocatePages(AllocateAnyPages,
EfiLoaderData, aligned_size / B_PAGE_SIZE, &addr);
if (status != EFI_SUCCESS) {
delete region;
return B_NO_MEMORY;
}
// Addresses above 512GB not supported.
// Memory map regions above 512GB can be ignored, but if EFI returns pages
// above that there's nothing that can be done to fix it.
if (addr + size > (512ull * 1024 * 1024 * 1024))
panic("Can't currently support more than 512GB of RAM!");
region->next = allocated_memory_regions;
allocated_memory_regions = region;
region->vaddr = 0;
region->paddr = addr;
region->size = size;
region->released = false;
if (*_address != NULL) {
region->vaddr = (uint64_t)*_address;
}
//dprintf("Allocated region %#lx (requested %p) %#lx %lu\n", region->vaddr, *_address, region->paddr, region->size);
*_address = (void *)region->paddr;
return B_OK;
}
/*!
Neither \a virtualAddress nor \a size need to be aligned, but the function
will map all pages the range intersects with.
If physicalAddress is not page-aligned, the returned virtual address will
have the same "misalignment".
*/
extern "C" addr_t
mmu_map_physical_memory(addr_t physicalAddress, size_t size, uint32 flags)
{
addr_t pageOffset = physicalAddress & (B_PAGE_SIZE - 1);
physicalAddress -= pageOffset;
size += pageOffset;
size_t aligned_size = ROUNDUP(size, B_PAGE_SIZE);
allocated_memory_region *region = new(std::nothrow) allocated_memory_region;
if (!region)
return B_NO_MEMORY;
// Addresses above 512GB not supported.
// Memory map regions above 512GB can be ignored, but if EFI returns pages above
// that there's nothing that can be done to fix it.
if (physicalAddress + size > (512ull * 1024 * 1024 * 1024))
panic("Can't currently support more than 512GB of RAM!");
region->next = allocated_memory_regions;
allocated_memory_regions = region;
region->vaddr = 0;
region->paddr = physicalAddress;
region->size = aligned_size;
region->released = false;
return physicalAddress + pageOffset;
}
extern "C" void
mmu_free(void *virtualAddress, size_t size)
{
addr_t physicalAddress = (addr_t)virtualAddress;
addr_t pageOffset = physicalAddress & (B_PAGE_SIZE - 1);
physicalAddress -= pageOffset;
size += pageOffset;
size_t aligned_size = ROUNDUP(size, B_PAGE_SIZE);
for (allocated_memory_region *region = allocated_memory_regions; region; region = region->next) {
if (region->paddr == physicalAddress && region->size == aligned_size) {
region->released = true;
return;
}
}
}
static allocated_memory_region *
get_region(void *address, size_t size)
{
for (allocated_memory_region *region = allocated_memory_regions; region; region = region->next) {
if (region->paddr == (uint64_t)address && region->size == size) {
return region;
}
}
return 0;
}
extern "C" status_t
platform_bootloader_address_to_kernel_address(void *address, uint64_t *_result)
{
uint64_t addr = (uint64_t)address;
for (allocated_memory_region *region = allocated_memory_regions; region; region = region->next) {
if (region->paddr <= addr && addr < region->paddr + region->size) {
// Lazily allocate virtual memory.
if (region->vaddr == 0) {
region->vaddr = next_virtual_address;
next_virtual_address += ROUNDUP(region->size, B_PAGE_SIZE);
}
*_result = region->vaddr + (addr - region->paddr);
//dprintf("Converted bootloader address %p in region %#lx-%#lx to %#lx\n",
// address, region->paddr, region->paddr + region->size, *_result);
return B_OK;
}
}
return B_ERROR;
}
extern "C" status_t
platform_kernel_address_to_bootloader_address(uint64_t address, void **_result)
{
for (allocated_memory_region *region = allocated_memory_regions; region; region = region->next) {
if (region->vaddr != 0 && region->vaddr <= address && address < region->vaddr + region->size) {
*_result = (void *)(region->paddr + (address - region->vaddr));
//dprintf("Converted kernel address %#lx in region %#lx-%#lx to %p\n",
// address, region->vaddr, region->vaddr + region->size, *_result);
return B_OK;
}
}
return B_ERROR;
}
extern "C" status_t
platform_free_region(void *address, size_t size)
{
//dprintf("Release region %p %lu\n", address, size);
allocated_memory_region *region = get_region(address, size);
if (!region)
panic("Unknown region??");
kBootServices->FreePages((EFI_PHYSICAL_ADDRESS)address, ROUNDUP(size, B_PAGE_SIZE) / B_PAGE_SIZE);
return B_OK;
}
+73
View File
@@ -0,0 +1,73 @@
/*
* Copyright 2014, Henry Harrington, henry.harrington@gmail.com.
* Distributed under the terms of the MIT License.
*/
#ifndef MMU_H
#define MMU_H
#include <arch/x86/descriptors.h>
#undef BOOT_GDT_SEGMENT_COUNT
#define BOOT_GDT_SEGMENT_COUNT (USER_DATA_SEGMENT + 1)
#ifndef _ASSEMBLER
#include "efi_platform.h"
#include <util/FixedWidthPointer.h>
extern segment_descriptor gBootGDT[BOOT_GDT_SEGMENT_COUNT];
static const uint32 kDefaultPageFlags = 0x3; // present, R/W
static const uint64 kTableMappingFlags = 0x7; // present, R/W, user
static const uint64 kLargePageMappingFlags = 0x183; // present, R/W, user, global, large
static const uint64 kPageMappingFlags = 0x103; // present, R/W, user, global
#ifdef __cplusplus
extern "C" {
#endif
extern addr_t mmu_map_physical_memory(addr_t physicalAddress, size_t size, uint32 flags);
extern void mmu_free(void *virtualAddress, size_t size);
extern void
mmu_post_efi_setup(UINTN memory_map_size, EFI_MEMORY_DESCRIPTOR *memory_map, UINTN descriptor_size, UINTN descriptor_version);
extern uint64_t
mmu_generate_post_efi_page_tables(UINTN memory_map_size, EFI_MEMORY_DESCRIPTOR *memory_map, UINTN descriptor_size, UINTN descriptor_version);
extern status_t
platform_kernel_address_to_bootloader_address(uint64_t address, void **_result);
extern status_t
platform_bootloader_address_to_kernel_address(void *address, uint64_t *_result);
#ifdef __cplusplus
}
#endif
/*! Convert a 32-bit address to a 64-bit address. */
inline uint64
fix_address(uint64 address)
{
uint64 result;
if (platform_bootloader_address_to_kernel_address((void *)address, &result) != B_OK)
return address;
else
return result;
}
template<typename Type>
inline void
fix_address(FixedWidthPointer<Type>& p)
{
if (p != NULL)
p.SetTo(fix_address(p.Get()));
}
#endif // !_ASSEMBLER
#endif /* MMU_H */
+457
View File
@@ -0,0 +1,457 @@
/*
* Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved.
* Copyright 2004-2010, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#include "smp.h"
#include <string.h>
#include <KernelExport.h>
#include <kernel.h>
#include <safemode.h>
#include <boot/platform.h>
#include <boot/stage2.h>
#include <boot/menu.h>
#include <arch/x86/apic.h>
#include <arch/x86/arch_acpi.h>
#include <arch/x86/arch_cpu.h>
#include <arch/x86/arch_smp.h>
#include <arch/x86/arch_system_info.h>
#include <arch/x86/descriptors.h>
#include "mmu.h"
#include "acpi.h"
#define NO_SMP 0
//#define TRACE_SMP
#ifdef TRACE_SMP
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
extern "C" void execute_n_instructions(int count);
extern "C" void smp_trampoline(void);
extern "C" void smp_trampoline_args(void);
extern "C" void smp_trampoline_end(void);
struct gdtr {
uint16 limit;
uint32 base;
unsigned char null[8];
unsigned char code[8];
unsigned char data[8];
} __attribute__((packed));
// Arguments passed to the SMP trampoline.
struct trampoline_args {
uint32 trampoline; // Trampoline address
uint32 gdt32; // 32-bit GDTR
uint32 pml4; // 64-bit PML4
uint32 gdt64; // 64-bit GDTR
uint64 kernel_entry; // Kernel entry point
uint64 kernel_args; // Kernel arguments
uint64 current_cpu; // CPU number
uint64 stack_top; // Kernel stack
volatile uint64 sentinel; // Sentinel, AP sets to 0 when finished
// smp_boot_other_cpus puts the GDTR here.
struct gdtr gdtr;
};
static uint32
apic_read(uint32 offset)
{
return *(volatile uint32 *)((addr_t)gKernelArgs.arch_args.apic_phys + offset);
}
static void
apic_write(uint32 offset, uint32 data)
{
*(volatile uint32 *)((addr_t)gKernelArgs.arch_args.apic_phys + offset) = data;
}
static status_t
smp_do_acpi_config(void)
{
TRACE(("smp: using ACPI to detect MP configuration\n"));
// reset CPU count
gKernelArgs.num_cpus = 0;
acpi_madt *madt = (acpi_madt *)acpi_find_table(ACPI_MADT_SIGNATURE);
if (madt == NULL) {
TRACE(("smp: Failed to find MADT!\n"));
return B_ERROR;
}
gKernelArgs.arch_args.apic_phys = madt->local_apic_address;
TRACE(("smp: local apic address is 0x%" B_PRIx32 "\n", madt->local_apic_address));
acpi_apic *apic = (acpi_apic *)((uint8 *)madt + sizeof(acpi_madt));
acpi_apic *end = (acpi_apic *)((uint8 *)madt + madt->header.length);
while (apic < end) {
switch (apic->type) {
case ACPI_MADT_LOCAL_APIC:
{
if (gKernelArgs.num_cpus == SMP_MAX_CPUS) {
TRACE(("smp: already reached maximum CPUs (%d)\n",
SMP_MAX_CPUS));
break;
}
acpi_local_apic *localApic = (acpi_local_apic *)apic;
TRACE(("smp: found local APIC with id %u\n",
localApic->apic_id));
if ((localApic->flags & ACPI_LOCAL_APIC_ENABLED) == 0) {
TRACE(("smp: APIC is disabled and will not be used\n"));
break;
}
gKernelArgs.arch_args.cpu_apic_id[gKernelArgs.num_cpus]
= localApic->apic_id;
// TODO: how to find out? putting 0x10 in to indicate a local apic
gKernelArgs.arch_args.cpu_apic_version[gKernelArgs.num_cpus]
= 0x10;
gKernelArgs.num_cpus++;
break;
}
case ACPI_MADT_IO_APIC: {
acpi_io_apic *ioApic = (acpi_io_apic *)apic;
TRACE(("smp: found io APIC with id %" B_PRIu32 " and address 0x%" B_PRIx32 "\n",
ioApic->io_apic_id, ioApic->io_apic_address));
if (gKernelArgs.arch_args.ioapic_phys == 0)
gKernelArgs.arch_args.ioapic_phys = ioApic->io_apic_address;
break;
}
default:
break;
}
apic = (acpi_apic *)((uint8 *)apic + apic->length);
}
return gKernelArgs.num_cpus > 0 ? B_OK : B_ERROR;
}
static void
calculate_apic_timer_conversion_factor(void)
{
int64 t1, t2;
uint32 config;
uint32 count;
TRACE(("calculating apic timer conversion factor\n"));
// setup the timer
config = apic_read(APIC_LVT_TIMER);
config = (config & APIC_LVT_TIMER_MASK) + APIC_LVT_MASKED;
// timer masked, vector 0
apic_write(APIC_LVT_TIMER, config);
config = (apic_read(APIC_TIMER_DIVIDE_CONFIG) & ~0x0000000f);
apic_write(APIC_TIMER_DIVIDE_CONFIG, config | APIC_TIMER_DIVIDE_CONFIG_1);
// divide clock by one
t1 = system_time();
apic_write(APIC_INITIAL_TIMER_COUNT, 0xffffffff); // start the counter
execute_n_instructions(128 * 20000);
count = apic_read(APIC_CURRENT_TIMER_COUNT);
t2 = system_time();
count = 0xffffffff - count;
gKernelArgs.arch_args.apic_time_cv_factor
= (uint32)((1000000.0/(t2 - t1)) * count);
TRACE(("APIC ticks/sec = %" B_PRId32 "\n",
gKernelArgs.arch_args.apic_time_cv_factor));
}
// #pragma mark -
int
smp_get_current_cpu(void)
{
if (gKernelArgs.arch_args.apic == NULL)
return 0;
uint8 apicID = apic_read(APIC_ID) >> 24;
for (uint32 i = 0; i < gKernelArgs.num_cpus; i++) {
if (gKernelArgs.arch_args.cpu_apic_id[i] == apicID)
return i;
}
return 0;
}
void
smp_init_other_cpus(void)
{
if (get_safemode_boolean(B_SAFEMODE_DISABLE_SMP, false)) {
// SMP has been disabled!
TRACE(("smp disabled per safemode setting\n"));
gKernelArgs.num_cpus = 1;
}
if (get_safemode_boolean(B_SAFEMODE_DISABLE_APIC, false)) {
TRACE(("local apic disabled per safemode setting, disabling smp\n"));
gKernelArgs.arch_args.apic_phys = 0;
gKernelArgs.num_cpus = 1;
}
if (gKernelArgs.arch_args.apic_phys == 0)
return;
TRACE(("smp: found %" B_PRId32 " cpu%s\n", gKernelArgs.num_cpus,
gKernelArgs.num_cpus != 1 ? "s" : ""));
TRACE(("smp: apic_phys = %lx\n", (addr_t)gKernelArgs.arch_args.apic_phys));
TRACE(("smp: ioapic_phys = %lx\n",
(addr_t)gKernelArgs.arch_args.ioapic_phys));
// map in the apic
gKernelArgs.arch_args.apic = (void *)mmu_map_physical_memory(
gKernelArgs.arch_args.apic_phys, B_PAGE_SIZE, kDefaultPageFlags);
TRACE(("smp: apic (mapped) = %lx\n", (addr_t)gKernelArgs.arch_args.apic.Pointer()));
// calculate how fast the apic timer is
calculate_apic_timer_conversion_factor();
if (gKernelArgs.num_cpus < 2)
return;
for (uint32 i = 1; i < gKernelArgs.num_cpus; i++) {
// create a final stack the trampoline code will put the ap processor on
void * stack = NULL;
const size_t size = KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
if (platform_allocate_region(&stack, size, 0, false) != B_OK) {
panic("Unable to allocate AP stack");
}
memset(stack, 0, size);
gKernelArgs.cpu_kstack[i].start = fix_address((uint64_t)stack);
gKernelArgs.cpu_kstack[i].size = size;
}
}
void
smp_boot_other_cpus(uint32 pml4, uint32 gdtr64, uint64 kernel_entry)
{
if (gKernelArgs.num_cpus < 2)
return;
TRACE(("trampolining other cpus\n"));
// allocate a stack and a code area for the smp trampoline
// (these have to be < 1M physical, 0xa0000-0xfffff is reserved by the BIOS)
uint64 trampolineCode = 0x9000;
uint64 trampolineStack = 0x8000;
// copy the trampoline code over
TRACE(("copying the trampoline code to %p from %p\n", (char*)trampolineCode, (const void*)&smp_trampoline));
TRACE(("size of trampoline code = %lu bytes\n", (uint64)&smp_trampoline_end - (uint64)&smp_trampoline));
memcpy((char *)trampolineCode, (const void*)&smp_trampoline,
(uint64)&smp_trampoline_end - (uint64)&smp_trampoline);
// boot the cpus
TRACE(("we have %d CPUs to boot...\n", gKernelArgs.num_cpus - 1));
for (uint32 i = 1; i < gKernelArgs.num_cpus; i++) {
TRACE(("trampolining CPU %d\n", i));
uint32 config;
uint64 numStartups;
uint32 j;
trampoline_args * args = (trampoline_args *)trampolineStack;
args->trampoline = trampolineCode;
args->gdt32 = (uint64) &args->gdtr;
args->gdtr.limit = 23;
args->gdtr.base = (uint32)(uint64)args->gdtr.null;
#define COPY_ARRAY(A, X0, X1, X2, X3, X4, X5, X6, X7) \
{ A[0] = X0; A[1] = X1; A[2] = X2; A[3] = X3; A[4] = X4; A[5] = X5; A[6] = X6; A[7] = X7; }
COPY_ARRAY(args->gdtr.null, 0, 0, 0, 0, 0, 0, 0, 0);
COPY_ARRAY(args->gdtr.code, 0xff, 0xff, 0, 0, 0, 0x9a, 0xcf, 0);
COPY_ARRAY(args->gdtr.data, 0xff, 0xff, 0, 0, 0, 0x92, 0xcf, 0);
#undef COPY_ARRAY
args->pml4 = pml4;
args->gdt64 = gdtr64;
args->kernel_entry = kernel_entry;
args->kernel_args = (uint64)&gKernelArgs;
args->current_cpu = i;
args->stack_top = gKernelArgs.cpu_kstack[i].start + gKernelArgs.cpu_kstack[i].size;
args->sentinel = 1;
// put the args in the right place
uint32 * args_ptr =
(uint32 *)(trampolineCode + (uint64)smp_trampoline_args - (uint64)smp_trampoline);
*args_ptr = (uint32)(uint64)args;
/* clear apic errors */
if (gKernelArgs.arch_args.cpu_apic_version[i] & 0xf0) {
apic_write(APIC_ERROR_STATUS, 0);
apic_read(APIC_ERROR_STATUS);
}
/* send (aka assert) INIT IPI */
config = (apic_read(APIC_INTR_COMMAND_2) & APIC_INTR_COMMAND_2_MASK)
| (gKernelArgs.arch_args.cpu_apic_id[i] << 24);
apic_write(APIC_INTR_COMMAND_2, config); /* set target pe */
config = (apic_read(APIC_INTR_COMMAND_1) & 0xfff00000)
| APIC_TRIGGER_MODE_LEVEL | APIC_INTR_COMMAND_1_ASSERT
| APIC_DELIVERY_MODE_INIT;
apic_write(APIC_INTR_COMMAND_1, config);
// wait for pending to end
while ((apic_read(APIC_INTR_COMMAND_1) & APIC_DELIVERY_STATUS) != 0)
asm volatile ("pause;");
/* deassert INIT */
config = (apic_read(APIC_INTR_COMMAND_2) & APIC_INTR_COMMAND_2_MASK)
| (gKernelArgs.arch_args.cpu_apic_id[i] << 24);
apic_write(APIC_INTR_COMMAND_2, config);
config = (apic_read(APIC_INTR_COMMAND_1) & 0xfff00000)
| APIC_TRIGGER_MODE_LEVEL | APIC_DELIVERY_MODE_INIT;
apic_write(APIC_INTR_COMMAND_1, config);
// wait for pending to end
while ((apic_read(APIC_INTR_COMMAND_1) & APIC_DELIVERY_STATUS) != 0)
asm volatile ("pause;");
/* wait 10ms */
spin(10000);
/* is this a local apic or an 82489dx ? */
numStartups = (gKernelArgs.arch_args.cpu_apic_version[i] & 0xf0)
? 2 : 0;
for (j = 0; j < numStartups; j++) {
/* it's a local apic, so send STARTUP IPIs */
apic_write(APIC_ERROR_STATUS, 0);
/* set target pe */
config = (apic_read(APIC_INTR_COMMAND_2) & APIC_INTR_COMMAND_2_MASK)
| (gKernelArgs.arch_args.cpu_apic_id[i] << 24);
apic_write(APIC_INTR_COMMAND_2, config);
/* send the IPI */
config = (apic_read(APIC_INTR_COMMAND_1) & 0xfff0f800)
| APIC_DELIVERY_MODE_STARTUP | (trampolineCode >> 12);
apic_write(APIC_INTR_COMMAND_1, config);
/* wait */
spin(200);
while ((apic_read(APIC_INTR_COMMAND_1) & APIC_DELIVERY_STATUS) != 0)
asm volatile ("pause;");
}
// Wait for the trampoline code to clear the final stack location.
// This serves as a notification for us that it has loaded the address
// and it is safe for us to overwrite it to trampoline the next CPU.
while (args->sentinel != 0)
spin(1000);
}
TRACE(("done trampolining\n"));
}
void
smp_add_safemode_menus(Menu *menu)
{
MenuItem *item;
if (gKernelArgs.arch_args.ioapic_phys != 0) {
menu->AddItem(item = new(nothrow) MenuItem("Disable IO-APIC"));
item->SetType(MENU_ITEM_MARKABLE);
item->SetData(B_SAFEMODE_DISABLE_IOAPIC);
item->SetHelpText("Disables using the IO APIC for interrupt routing, "
"forcing the use of the legacy PIC instead.");
}
if (gKernelArgs.arch_args.apic_phys != 0) {
menu->AddItem(item = new(nothrow) MenuItem("Disable local APIC"));
item->SetType(MENU_ITEM_MARKABLE);
item->SetData(B_SAFEMODE_DISABLE_APIC);
item->SetHelpText("Disables using the local APIC, also disables SMP.");
cpuid_info info;
if (get_current_cpuid(&info, 1, 0) == B_OK
&& (info.regs.ecx & IA32_FEATURE_EXT_X2APIC) != 0) {
#if 0
menu->AddItem(item = new(nothrow) MenuItem("Disable X2APIC"));
item->SetType(MENU_ITEM_MARKABLE);
item->SetData(B_SAFEMODE_DISABLE_X2APIC);
item->SetHelpText("Disables using X2APIC.");
#else
menu->AddItem(item = new(nothrow) MenuItem("Enable X2APIC"));
item->SetType(MENU_ITEM_MARKABLE);
item->SetData(B_SAFEMODE_ENABLE_X2APIC);
item->SetHelpText("Enables using X2APIC.");
#endif
}
}
if (gKernelArgs.num_cpus < 2)
return;
item = new(nothrow) MenuItem("Disable SMP");
menu->AddItem(item);
item->SetData(B_SAFEMODE_DISABLE_SMP);
item->SetType(MENU_ITEM_MARKABLE);
item->SetHelpText("Disables all but one CPU core.");
}
void
smp_init(void)
{
#if NO_SMP
gKernelArgs.num_cpus = 1;
return;
#endif
cpuid_info info;
if (get_current_cpuid(&info, 1, 0) != B_OK)
return;
if ((info.eax_1.features & IA32_FEATURE_APIC) == 0) {
// Local APICs aren't present; As they form the basis for all inter CPU
// communication and therefore SMP, we don't need to go any further.
TRACE(("no local APIC present, not attempting SMP init\n"));
return;
}
// first try to find ACPI tables to get MP configuration as it handles
// physical as well as logical MP configurations as in multiple cpus,
// multiple cores or hyper threading.
if (smp_do_acpi_config() == B_OK) {
TRACE(("smp init success\n"));
return;
}
// Everything failed or we are not running an SMP system, reset anything
// that might have been set through an incomplete configuration attempt.
gKernelArgs.arch_args.apic_phys = 0;
gKernelArgs.arch_args.ioapic_phys = 0;
gKernelArgs.num_cpus = 1;
}
+30
View File
@@ -0,0 +1,30 @@
/*
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef SMP_H
#define SMP_H
#include <SupportDefs.h>
#ifdef __cplusplus
// this is only available in C++
# include <boot/menu.h>
extern void smp_add_safemode_menus(Menu *menu);
extern "C" {
#endif
extern void smp_init(void);
extern void smp_init_other_cpus(void);
extern void smp_boot_other_cpus(uint32 pml4, uint32 gdt64, uint64 kernel_entry);
extern int smp_get_current_cpu(void);
#ifdef __cplusplus
}
#endif
#endif /* SMP_H */
@@ -0,0 +1,129 @@
/*
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
** Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
** Distributed under the terms of the NewOS License.
*/
// Relocatable. Before calling, smp_trampoline_args should point
// to a struct trampoline_args (see smp.cpp). This pointer should
// be 16-byte aligned, below 1MB and identity-mapped.
.globl smp_trampoline
.globl smp_trampoline_end
.globl smp_trampoline_args
#include <asm_defs.h>
#include <arch/x86/descriptors.h>
#include "mmu.h"
.code16
smp_trampoline:
cli
// movl 0xdeadbeef, esi
.byte 0x66
.byte 0xbe
smp_trampoline_args:
.long 0xdeadbeef
// Load the trampoline args into ss.
movl %esi, %eax
shrl $4, %eax
movw %ax, %ss
xorw %sp, %sp
// Switch to protected mode.
popl %ebx
popl %edx
lgdt (%edx)
movl %cr0,%eax
orl $0x01,%eax
movl %eax,%cr0
pushl $8
leal (trampoline_32 - smp_trampoline)(%ebx), %eax
pushl %eax
.byte 0x66
.code32
retf
trampoline_32:
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
// Put the trampoline args on the stack.
movl %esi, %esp
addl $8, %esp
// Enable PAE and PGE
movl %cr4, %eax
orl $(1 << 5) | (1 << 7), %eax
movl %eax, %cr4
// Point CR3 to the kernel's PML4.
popl %eax
movl %eax, %cr3
// Enable long mode by setting EFER.LME.
movl $0xc0000080, %ecx
rdmsr
orl $(1 << 8), %eax
wrmsr
// Re-enable paging, which will put us in compatibility mode as we are
// currently in a 32-bit code segment.
movl %cr0, %ecx
orl $(1 << 31), %ecx
movl %ecx, %cr0
// Load 64-bit enabled GDT
popl %eax
lgdtl (%eax)
// Jump into the 64-bit code segment.
pushl $KERNEL_CODE_SELECTOR
leal (.Llmode - smp_trampoline)(%ebx), %eax
pushl %eax
retf
.align 8
.code64
.Llmode:
// Set data segments.
mov $KERNEL_DATA_SELECTOR, %ax
mov %ax, %ss
xor %ax, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
// Initialisation that comes from long_smp_start_kernel.
movq %cr0, %rax
orq $0x10000, %rax
andq $(~6), %rax
movq %rax, %cr0
fninit
movq %cr4, %rax
orq $0x600, %rax
movq %rax, %cr4
// Get kernel arguments.
popq %rax
popq %rdi
popq %rsi
// Set the stack pointer, write to the sentinel and clear the stack frame/RFLAGS.
popq %rbp
movq $0, (%rsp)
movq %rbp, %rsp
xorq %rbp, %rbp
push $0
popf
// Call the entry point.
call *%rax
smp_trampoline_end:
+295
View File
@@ -0,0 +1,295 @@
/*
* Copyright 2014-2016 Haiku, Inc. All rights reserved.
* Copyright 2013-2014, Fredrik Holmqvist, fredrik.holmqvist@gmail.com.
* Copyright 2014, Henry Harrington, henry.harrington@gmail.com.
* All rights reserved.
* Distributed under the terms of the Haiku License.
*/
#include <string.h>
#include <KernelExport.h>
#include <arch/cpu.h>
#include <arch/x86/descriptors.h>
#include <boot/kernel_args.h>
#include <boot/platform.h>
#include <boot/stage2.h>
#include <boot/stdio.h>
#include <kernel.h>
#include "acpi.h"
#include "console.h"
#include "efi_platform.h"
#include "hpet.h"
#include "cpu.h"
#include "mmu.h"
#include "smp.h"
extern void (*__ctor_list)(void);
extern void (*__ctor_end)(void);
const EFI_SYSTEM_TABLE *kSystemTable;
const EFI_BOOT_SERVICES *kBootServices;
const EFI_RUNTIME_SERVICES *kRuntimeServices;
EFI_HANDLE kImage;
static uint32 sBootOptions;
static uint64 gLongKernelEntry;
extern uint64 gLongGDT;
extern uint64 gLongGDTR;
segment_descriptor gBootGDT[BOOT_GDT_SEGMENT_COUNT];
extern "C" int main(stage2_args *args);
extern "C" void _start(void);
extern "C" void efi_enter_kernel(uint64 pml4, uint64 entry_point, uint64 stack);
static void
call_ctors(void)
{
void (**f)(void);
for (f = &__ctor_list; f < &__ctor_end; f++)
(**f)();
}
extern "C" uint32
platform_boot_options()
{
return sBootOptions;
}
static void
long_gdt_init()
{
clear_segment_descriptor(&gBootGDT[0]);
// Set up code/data segments (TSS segments set up later in the kernel).
set_segment_descriptor(&gBootGDT[KERNEL_CODE_SEGMENT], DT_CODE_EXECUTE_ONLY,
DPL_KERNEL);
set_segment_descriptor(&gBootGDT[KERNEL_DATA_SEGMENT], DT_DATA_WRITEABLE,
DPL_KERNEL);
set_segment_descriptor(&gBootGDT[USER_CODE_SEGMENT], DT_CODE_EXECUTE_ONLY,
DPL_USER);
set_segment_descriptor(&gBootGDT[USER_DATA_SEGMENT], DT_DATA_WRITEABLE,
DPL_USER);
// Used by long_enter_kernel().
gLongGDT = (addr_t)gBootGDT + 0xFFFFFF0000000000;
dprintf("GDT at 0x%lx\n", gLongGDT);
}
static void
convert_preloaded_image(preloaded_elf64_image* image)
{
fix_address(image->next);
fix_address(image->name);
fix_address(image->debug_string_table);
fix_address(image->syms);
fix_address(image->rel);
fix_address(image->rela);
fix_address(image->pltrel);
fix_address(image->debug_symbols);
}
/*! Convert all addresses in kernel_args to 64-bit addresses. */
static void
convert_kernel_args()
{
fix_address(gKernelArgs.boot_volume);
fix_address(gKernelArgs.vesa_modes);
fix_address(gKernelArgs.edid_info);
fix_address(gKernelArgs.debug_output);
fix_address(gKernelArgs.boot_splash);
fix_address(gKernelArgs.arch_args.apic);
fix_address(gKernelArgs.arch_args.hpet);
convert_preloaded_image(static_cast<preloaded_elf64_image*>(
gKernelArgs.kernel_image.Pointer()));
fix_address(gKernelArgs.kernel_image);
// Iterate over the preloaded images. Must save the next address before
// converting, as the next pointer will be converted.
preloaded_image* image = gKernelArgs.preloaded_images;
fix_address(gKernelArgs.preloaded_images);
while (image != NULL) {
preloaded_image* next = image->next;
convert_preloaded_image(static_cast<preloaded_elf64_image*>(image));
image = next;
}
// Fix driver settings files.
driver_settings_file* file = gKernelArgs.driver_settings;
fix_address(gKernelArgs.driver_settings);
while (file != NULL) {
driver_settings_file* next = file->next;
fix_address(file->next);
fix_address(file->buffer);
file = next;
}
}
extern "C" void
platform_start_kernel(void)
{
if (gKernelArgs.kernel_image->elf_class != ELFCLASS64)
panic("32-bit kernels not supported with EFI");
cpu_init();
acpi_init();
hpet_init();
smp_init();
smp_init_other_cpus();
preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
gKernelArgs.kernel_image.Pointer());
long_gdt_init();
convert_kernel_args();
// Save the kernel entry point address.
gLongKernelEntry = image->elf_header.e_entry;
dprintf("kernel entry at %#lx\n", gLongKernelEntry);
// map in a kernel stack
void *stack_address = NULL;
if (platform_allocate_region(&stack_address, KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false) != B_OK) {
panic("Unabled to allocate a stack");
}
gKernelArgs.cpu_kstack[0].start = fix_address((uint64_t)stack_address);
gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
dprintf("Kernel stack at %#lx\n", gKernelArgs.cpu_kstack[0].start);
// Prepare to exit EFI boot services.
// Read the memory map.
// First call is to determine the buffer size.
UINTN memory_map_size = 0;
EFI_MEMORY_DESCRIPTOR dummy;
EFI_MEMORY_DESCRIPTOR *memory_map;
UINTN map_key;
UINTN descriptor_size;
UINT32 descriptor_version;
if (kBootServices->GetMemoryMap(&memory_map_size, &dummy, &map_key, &descriptor_size, &descriptor_version) != EFI_BUFFER_TOO_SMALL) {
panic("Unable to determine size of system memory map");
}
// Allocate a buffer twice as large as needed just in case it gets bigger between
// calls to ExitBootServices.
UINTN actual_memory_map_size = memory_map_size * 2;
memory_map = (EFI_MEMORY_DESCRIPTOR *)kernel_args_malloc(actual_memory_map_size);
if (memory_map == NULL)
panic("Unable to allocate memory map.");
// Read (and print) the memory map.
memory_map_size = actual_memory_map_size;
if (kBootServices->GetMemoryMap(&memory_map_size, memory_map, &map_key, &descriptor_size, &descriptor_version) != EFI_SUCCESS) {
panic("Unable to fetch system memory map.");
}
addr_t addr = (addr_t)memory_map;
dprintf("System provided memory map:\n");
for (UINTN i = 0; i < memory_map_size / descriptor_size; ++i) {
EFI_MEMORY_DESCRIPTOR *entry = (EFI_MEMORY_DESCRIPTOR *)(addr + i * descriptor_size);
dprintf(" %#lx-%#lx %#lx %#x %#lx\n",
entry->PhysicalStart, entry->PhysicalStart + entry->NumberOfPages * 4096,
entry->VirtualStart, entry->Type, entry->Attribute);
}
// Generate page tables for use after ExitBootServices.
uint64_t final_pml4 = mmu_generate_post_efi_page_tables(memory_map_size, memory_map, descriptor_size, descriptor_version);
dprintf("Final PML4 at %#lx\n", final_pml4);
// Attempt to fetch the memory map and exit boot services.
// This needs to be done in a loop, as ExitBootServices can change the
// memory map.
// Even better: Only GetMemoryMap and ExitBootServices can be called after
// the first call to ExitBootServices, as the firmware is permitted to
// partially exit. This is why twice as much space was allocated for the
// memory map, as it's impossible to allocate more now.
// A changing memory map shouldn't affect the generated page tables, as
// they only needed to know about the maximum address, not any specific
// entry.
dprintf("Calling ExitBootServices. So long, EFI!\n");
while (true) {
if (kBootServices->ExitBootServices(kImage, map_key) == EFI_SUCCESS) {
break;
}
memory_map_size = actual_memory_map_size;
if (kBootServices->GetMemoryMap(&memory_map_size, memory_map, &map_key, &descriptor_size, &descriptor_version) != EFI_SUCCESS) {
panic("Unable to fetch system memory map.");
}
}
// We're on our own now...
// The console was provided by boot services, disable it.
stdout = NULL;
// Update EFI, generate final kernel physical memory map, etc.
mmu_post_efi_setup(memory_map_size, memory_map, descriptor_size, descriptor_version);
smp_boot_other_cpus(final_pml4, (uint32_t)(uint64_t)&gLongGDTR, gLongKernelEntry);
// Enter the kernel!
efi_enter_kernel(final_pml4,
gLongKernelEntry,
gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size);
panic("Shouldn't get here");
}
extern "C" void
platform_exit(void)
{
return;
}
/**
* efi_main - The entry point for the EFI application
* @image: firmware-allocated handle that identifies the image
* @systemTable: EFI system table
*/
extern "C" EFI_STATUS
efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systemTable)
{
stage2_args args;
memset(&args, 0, sizeof(stage2_args));
kImage = image;
kSystemTable = systemTable;
kBootServices = systemTable->BootServices;
kRuntimeServices = systemTable->RuntimeServices;
memset(&args, 0, sizeof(stage2_args));
call_ctors();
console_init();
sBootOptions = console_check_boot_keys();
// disable apm in case we ever load a 32-bit kernel...
gKernelArgs.platform_args.apm.version = 0;
gKernelArgs.num_cpus = 1;
gKernelArgs.arch_args.hpet_phys = 0;
gKernelArgs.arch_args.hpet = NULL;
main(&args);
return EFI_SUCCESS;
}
+39
View File
@@ -0,0 +1,39 @@
/*
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#define FUNCTION(x) .global x; .type x,@function; x
/* uint64 rdtsc() */
FUNCTION(rdtsc):
rdtsc
/* Convert to 64-bit result in rax. */
shlq $32, %rdx
orq %rdx, %rax
ret
FUNCTION(execute_n_instructions):
movl %edi, %ecx
shrl $4, %ecx
.again:
xorl %eax, %eax
xorl %eax, %eax
xorl %eax, %eax
xorl %eax, %eax
xorl %eax, %eax
xorl %eax, %eax
xorl %eax, %eax
xorl %eax, %eax
xorl %eax, %eax
xorl %eax, %eax
xorl %eax, %eax
xorl %eax, %eax
xorl %eax, %eax
xorl %eax, %eax
xorl %eax, %eax
xorl %eax, %eax
loop .again
ret
+108
View File
@@ -0,0 +1,108 @@
/*
* Copyright 2016, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <boot/kernel_args.h>
#include <boot/platform.h>
#include <boot/platform/generic/video.h>
#include <boot/stage2.h>
#include "efi_platform.h"
static EFI_GUID sGraphicsOutputGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
static EFI_GRAPHICS_OUTPUT_PROTOCOL *sGraphicsOutput;
static UINTN sGraphicsMode;
extern "C" status_t
platform_init_video(void)
{
EFI_STATUS status = kBootServices->LocateProtocol(&sGraphicsOutputGuid,
NULL, (void **)&sGraphicsOutput);
if (sGraphicsOutput == NULL || status != EFI_SUCCESS) {
gKernelArgs.frame_buffer.enabled = false;
sGraphicsOutput = NULL;
return B_ERROR;
}
UINTN bestArea = 0;
UINTN bestDepth = 0;
for (UINTN mode = 0; mode < sGraphicsOutput->Mode->MaxMode; ++mode) {
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
UINTN size, depth;
sGraphicsOutput->QueryMode(sGraphicsOutput, mode, &size, &info);
UINTN area = info->HorizontalResolution * info->VerticalResolution;
if (info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor)
depth = 32;
else if (info->PixelFormat == PixelBitMask
&& info->PixelInformation.RedMask == 0xFF0000
&& info->PixelInformation.GreenMask == 0x00FF00
&& info->PixelInformation.BlueMask == 0x0000FF
&& info->PixelInformation.ReservedMask == 0)
depth = 24;
else
continue;
area *= depth;
if (area >= bestArea) {
bestArea = area;
bestDepth = depth;
sGraphicsMode = mode;
}
}
if (bestArea == 0 || bestDepth == 0) {
sGraphicsOutput = NULL;
return B_ERROR;
}
return B_OK;
}
extern "C" void
platform_switch_to_logo(void)
{
if (sGraphicsOutput == NULL || gKernelArgs.frame_buffer.enabled)
return;
sGraphicsOutput->SetMode(sGraphicsOutput, sGraphicsMode);
gKernelArgs.frame_buffer.enabled = true;
gKernelArgs.frame_buffer.physical_buffer.start =
sGraphicsOutput->Mode->FrameBufferBase;
gKernelArgs.frame_buffer.physical_buffer.size =
sGraphicsOutput->Mode->FrameBufferSize;
gKernelArgs.frame_buffer.width =
sGraphicsOutput->Mode->Info->HorizontalResolution;
gKernelArgs.frame_buffer.height =
sGraphicsOutput->Mode->Info->VerticalResolution;
gKernelArgs.frame_buffer.depth =
sGraphicsOutput->Mode->Info->PixelFormat == PixelBitMask ? 24 : 32;
gKernelArgs.frame_buffer.bytes_per_row =
sGraphicsOutput->Mode->Info->PixelsPerScanLine
* gKernelArgs.frame_buffer.depth / 8;
video_display_splash(gKernelArgs.frame_buffer.physical_buffer.start);
}
extern "C" void
platform_blit4(addr_t frameBuffer, const uint8 *data,
uint16 width, uint16 height, uint16 imageWidth,
uint16 left, uint16 top)
{
panic("platform_blit4 unsupported");
return;
}
extern "C" void
platform_set_palette(const uint8 *palette)
{
panic("platform_set_palette unsupported");
return;
}
+2 -1
View File
@@ -1,5 +1,7 @@
SubDir HAIKU_TOP src system boot platform generic ; SubDir HAIKU_TOP src system boot platform generic ;
SetupFeatureObjectsDir $(TARGET_BOOT_PLATFORM) ;
UseBuildFeatureHeaders zlib ; UseBuildFeatureHeaders zlib ;
UsePrivateKernelHeaders ; UsePrivateKernelHeaders ;
@@ -9,7 +11,6 @@ BootStaticLibrary boot_platform_generic :
text_menu.cpp text_menu.cpp
video_blit.cpp video_blit.cpp
video_splash.cpp video_splash.cpp
: -fno-pic
; ;
Includes [ FGristFiles video_splash.cpp ] Includes [ FGristFiles video_splash.cpp ]
+1 -1
View File
@@ -57,7 +57,7 @@ BootMergeObject boot_platform_pxe_ia32.o :
$(bios_ia32_src) $(bios_ia32_src)
$(bios_ia32_edid_src) $(bios_ia32_edid_src)
: -fno-pic :
: boot_platform_generic.a : boot_platform_generic.a
; ;
@@ -40,7 +40,7 @@ BootMergeObject boot_platform_raspberrypi_arm.o :
arch_framebuffer_bcm2835.cpp arch_framebuffer_bcm2835.cpp
$(genericPlatformSources) $(genericPlatformSources)
: -fno-pic :
: boot_platform_generic.a : boot_platform_generic.a
; ;
+1 -1
View File
@@ -59,7 +59,7 @@ BootMergeObject boot_platform_u-boot_common.o :
$(libFDTSources) $(libFDTSources)
: -fno-pic :
: boot_platform_generic.a : boot_platform_generic.a
; ;
@@ -16,7 +16,6 @@ BootMergeObject boot_platform_u-boot_arm.o :
shell.S shell.S
arch_mailbox.cpp arch_mailbox.cpp
: -fno-pic
; ;
#SEARCH on [ FGristFiles arch_cpu_asm.S ] #SEARCH on [ FGristFiles arch_cpu_asm.S ]
@@ -12,7 +12,7 @@ SubDirC++Flags -fno-rtti ;
BootMergeObject boot_platform_u-boot_ppc_amcc440.o : BootMergeObject boot_platform_u-boot_ppc_amcc440.o :
arch_mmu_amcc440.cpp arch_mmu_amcc440.cpp
: -fno-pic -mcpu=440 : -mcpu=440
; ;
BootMergeObject boot_platform_u-boot_ppc.o : BootMergeObject boot_platform_u-boot_ppc.o :
@@ -24,7 +24,7 @@ BootMergeObject boot_platform_u-boot_ppc.o :
arch_start_kernel.S arch_start_kernel.S
arch_cpu.cpp arch_cpu.cpp
#mmu.cpp #mmu.cpp
: -fno-pic :
: boot_platform_u-boot_ppc_amcc440.o : boot_platform_u-boot_ppc_amcc440.o
; ;
+2 -2
View File
@@ -37,7 +37,7 @@ is_in_image(struct elf_image_info *image, addr_t address)
#endif // !_BOOT_MODE #endif // !_BOOT_MODE
#if !defined(__x86_64__) || defined(_BOOT_MODE) #if !defined(__x86_64__) || (defined(_BOOT_MODE) && _BOOT_PLATFORM != efi)
#ifdef TRACE_ARCH_ELF #ifdef TRACE_ARCH_ELF
@@ -183,7 +183,7 @@ arch_elf_relocate_rela(struct elf_image_info *image,
} }
#endif // !__x86_64__ || _BOOT_MODE #endif // !__x86_64__ || (_BOOT_MODE && _BOOT_PLATFORM != efi)
#if defined(__x86_64__) || defined(_BOOT_MODE) #if defined(__x86_64__) || defined(_BOOT_MODE)
@@ -10,6 +10,8 @@
#include <arch/platform.h> #include <arch/platform.h>
#include <apm.h> #include <apm.h>
#include <boot_item.h>
#include <boot/stage2.h>
status_t status_t
@@ -22,6 +24,10 @@ arch_platform_init(struct kernel_args *args)
status_t status_t
arch_platform_init_post_vm(struct kernel_args *args) arch_platform_init_post_vm(struct kernel_args *args)
{ {
// Now we can add boot items; pass on the ACPI root pointer
add_boot_item("ACPI_ROOT_POINTER",
args->arch_args.acpi_root.Pointer(), sizeof(void*));
return B_OK; return B_OK;
} }
+20
View File
@@ -3916,6 +3916,26 @@ vm_allocate_early_physical_page(kernel_args* args)
} }
} }
// Expanding upwards didn't work, try going downwards.
for (uint32 i = 0; i < args->num_physical_allocated_ranges; i++) {
phys_addr_t nextPage;
nextPage = args->physical_allocated_range[i].start - B_PAGE_SIZE;
// see if the page after the prev allocated paddr run can be allocated
if (i > 0 && args->physical_allocated_range[i - 1].size != 0) {
// see if the next page will collide with the next allocated range
if (nextPage < args->physical_allocated_range[i-1].start + args->physical_allocated_range[i-1].size)
continue;
}
// see if the next physical page fits in the memory block
if (is_page_in_physical_memory_range(args, nextPage)) {
// we got one!
args->physical_allocated_range[i].start -= B_PAGE_SIZE;
args->physical_allocated_range[i].size += B_PAGE_SIZE;
return nextPage / B_PAGE_SIZE;
}
}
return 0; return 0;
// could not allocate a block // could not allocate a block
} }
@@ -0,0 +1,79 @@
/* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below & ctor support - KEEP IN SYNC */
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SECTIONS
{
. = 0;
ImageBase = .;
.hash : { *(.hash) } /* this MUST come first! */
. = ALIGN(4096);
.eh_frame :
{
*(.eh_frame)
}
. = ALIGN(4096);
.text :
{
_text = .;
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
. = ALIGN(16);
}
_etext = .;
_text_size = . - _text;
. = ALIGN(4096);
.reloc :
{
*(.reloc)
}
. = ALIGN(4096);
.data :
{
. = ALIGN(0x4);
__ctor_list = .;
*(.ctors)
__ctor_end = .;
_data = .;
*(.rodata*)
*(.got.plt)
*(.got)
*(.data*)
*(.sdata)
/* the EFI loader doesn't seem to like a .bss section, so we stick
it all into .data: */
*(.sbss)
*(.scommon)
*(.dynbss)
*(.bss)
*(COMMON)
*(.rel.local)
}
.note.gnu.build-id : { *(.note.gnu.build-id) }
_edata = .;
_data_size = . - _etext;
. = ALIGN(4096);
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
.rela :
{
*(.rela.data*)
*(.rela.ctors)
*(.rela.got)
*(.rela.stab)
}
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
. = ALIGN(4096);
.ignored.reloc :
{
*(.rela.reloc)
*(.eh_frame)
*(.note.GNU-stack)
}
.comment 0 : { *(.comment) }
}