Merge branch 'uefi-support'
This commit is contained in:
+30
-12
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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 ;
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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 ;
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o :
|
|||||||
$(kernelDebugSources)
|
$(kernelDebugSources)
|
||||||
|
|
||||||
$(librootArchObjects)
|
$(librootArchObjects)
|
||||||
: -fno-pic
|
:
|
||||||
:
|
:
|
||||||
$(kernelLibArchObjects)
|
$(kernelLibArchObjects)
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -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 ]
|
||||||
|
|||||||
@@ -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 ] ;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -152,7 +174,7 @@ ELFLoader<Class>::Create(int fd, preloaded_image** _image)
|
|||||||
ImageType* image = (ImageType*)kernel_args_malloc(sizeof(ImageType));
|
ImageType* image = (ImageType*)kernel_args_malloc(sizeof(ImageType));
|
||||||
if (image == NULL)
|
if (image == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
ssize_t length = read_pos(fd, 0, &image->elf_header, sizeof(EhdrType));
|
ssize_t length = read_pos(fd, 0, &image->elf_header, sizeof(EhdrType));
|
||||||
if (length < (ssize_t)sizeof(EhdrType)) {
|
if (length < (ssize_t)sizeof(EhdrType)) {
|
||||||
kernel_args_free(image);
|
kernel_args_free(image);
|
||||||
@@ -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
|
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -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 ] ;
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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:
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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,8 +11,7 @@ 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 ]
|
||||||
: [ BuildFeatureAttribute zlib : headers ] ;
|
: [ BuildFeatureAttribute zlib : headers ] ;
|
||||||
|
|||||||
@@ -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
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -1,38 +1,44 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Ingo Weinhold <bonefish@cs.tu-berlin.de>
|
* Ingo Weinhold <bonefish@cs.tu-berlin.de>
|
||||||
* Axel Dörfler, axeld@pinc-software.de
|
* Axel Dörfler, axeld@pinc-software.de
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <arch/platform.h>
|
#include <arch/platform.h>
|
||||||
#include <apm.h>
|
#include <apm.h>
|
||||||
|
#include <boot_item.h>
|
||||||
|
#include <boot/stage2.h>
|
||||||
status_t
|
|
||||||
arch_platform_init(struct kernel_args *args)
|
|
||||||
{
|
status_t
|
||||||
return B_OK;
|
arch_platform_init(struct kernel_args *args)
|
||||||
}
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
status_t
|
|
||||||
arch_platform_init_post_vm(struct kernel_args *args)
|
|
||||||
{
|
status_t
|
||||||
return B_OK;
|
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",
|
||||||
status_t
|
args->arch_args.acpi_root.Pointer(), sizeof(void*));
|
||||||
arch_platform_init_post_thread(struct kernel_args *args)
|
|
||||||
{
|
return B_OK;
|
||||||
// APM is not supported on x86_64.
|
}
|
||||||
#ifndef __x86_64__
|
|
||||||
apm_init(args);
|
|
||||||
#endif
|
status_t
|
||||||
return B_OK;
|
arch_platform_init_post_thread(struct kernel_args *args)
|
||||||
}
|
{
|
||||||
|
// APM is not supported on x86_64.
|
||||||
|
#ifndef __x86_64__
|
||||||
|
apm_init(args);
|
||||||
|
#endif
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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) }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user