diff options
84 files changed, 1341 insertions, 577 deletions
diff --git a/Documentation/boards/efi.rst b/Documentation/boards/efi.rst index b7ad40e472..ecadb3ebba 100644 --- a/Documentation/boards/efi.rst +++ b/Documentation/boards/efi.rst @@ -25,7 +25,7 @@ Use the following to build barebox for EFI: .. code-block:: sh - export ARCH=efi + export ARCH=x86 make efi_defconfig make diff --git a/arch/efi/Kconfig b/arch/efi/Kconfig deleted file mode 100644 index d8d0592e51..0000000000 --- a/arch/efi/Kconfig +++ /dev/null @@ -1,51 +0,0 @@ -config ARCH_EFI - bool - default y - select HAS_DEBUG_LL - select HAS_KALLSYMS - select EFI_GUID - select EFI_DEVICEPATH - select PRINTF_UUID - select GENERIC_FIND_NEXT_BIT - -config ARCH_TEXT_BASE - hex - default 0x0 - -menu "EFI specific settings" - -config 64BIT - def_bool y - help - Say yes to build a 64-bit binary - formerly known as x86_64 - Say no to build a 32-bit binary - formerly known as i386. - - 32-bit support currently does not compile and is not tested - due to the lack of hardware. - -config X86_32 - def_bool y - depends on !64BIT - -config X86_64 - def_bool y - depends on 64BIT - -config ARCH_EFI_REGISTER_COM1 - bool "Register first serial port" - help - Say yes here to register the first serial port on ioport 0x3f8. - This is useful to control barebox over a serial port if the board - has one. Enabling this option may not work on boards which do not - have a serial port. Also enable DRIVER_SERIAL_NS16550 to enable - the NS16550 driver. - -endmenu - -source common/Kconfig -source commands/Kconfig -source net/Kconfig -source drivers/Kconfig -source fs/Kconfig -source lib/Kconfig -source crypto/Kconfig diff --git a/arch/efi/Makefile b/arch/efi/Makefile deleted file mode 100644 index 32a1c152b7..0000000000 --- a/arch/efi/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -KBUILD_DEFCONFIG := efi_defconfig - -CFLAGS += -fpic -fshort-wchar -mno-sse -mno-mmx - -ifeq ($(CONFIG_X86_32),y) - UTS_MACHINE := i386 - biarch := $(call cc-option,-m32) - AFLAGS += $(biarch) - CFLAGS += $(biarch) - TARGET = efi-app-ia32 -else - UTS_MACHINE := x86_64 - AFLAGS += -m64 - CFLAGS += -m64 -mno-red-zone - TARGET = efi-app-x86_64 -endif - -lds-$(CONFIG_X86_32) := arch/efi/lib/elf_ia32_efi.lds -lds-$(CONFIG_X86_64) := arch/efi/lib/elf_x86_64_efi.lds - -cmd_barebox__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_barebox) -o $@ \ - -T $(lds-y) \ - -shared -Bsymbolic -nostdlib -znocombreloc \ - --start-group $(barebox-common) \ - --end-group \ - $(filter-out $(barebox-lds) $(barebox-common) FORCE ,$^) - -quiet_cmd_efi_image = EFI-IMG $@ - cmd_efi_image = $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic \ - -j .dynsym -j .rel -j .rela -j .reloc -j __barebox_initcalls \ - -j __barebox_exitcalls -j __barebox_cmd -j .barebox_magicvar \ - -j .bbenv.* --target=$(TARGET) $< $@ - -KBUILD_BINARY := barebox - -LDFLAGS := -m elf_$(UTS_MACHINE) --no-undefined - -barebox.efi: $(KBUILD_BINARY) FORCE - $(call if_changed,efi_image) - -KBUILD_IMAGE := barebox.efi - -common-y += arch/efi/efi/ arch/efi/lib/ diff --git a/arch/efi/efi/Makefile b/arch/efi/efi/Makefile deleted file mode 100644 index a856e5907c..0000000000 --- a/arch/efi/efi/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-y += efi.o clocksource.o efi-block-io.o efi-device.o efi-image.o -bbenv-y += env-efi diff --git a/arch/efi/efi/clocksource.c b/arch/efi/efi/clocksource.c deleted file mode 100644 index c92c35b112..0000000000 --- a/arch/efi/efi/clocksource.c +++ /dev/null @@ -1,58 +0,0 @@ -#include <common.h> -#include <efi.h> -#include <mach/efi.h> -#include <clock.h> - -#ifdef __x86_64__ -uint64_t ticks_read(void) -{ - uint64_t a, d; - - __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d)); - - return (d << 32) | a; -} -#else -uint64_t ticks_read(void) -{ - uint64_t val; - - __asm__ volatile ("rdtsc" : "=A" (val)); - - return val; -} -#endif - -static uint64_t freq; - -/* count TSC ticks during a millisecond delay */ -static uint64_t ticks_freq(void) -{ - uint64_t ticks_start, ticks_end; - - ticks_start = ticks_read(); - BS->stall(1000); - ticks_end = ticks_read(); - - return (ticks_end - ticks_start) * 1000; -} - -static uint64_t efi_clocksource_read(void) -{ - return 1000 * 1000 * ticks_read() / freq; -} - -static struct clocksource cs = { - .read = efi_clocksource_read, - .mask = CLOCKSOURCE_MASK(64), - .shift = 0, -}; - -int efi_clocksource_init(void) -{ - cs.mult = clocksource_hz2mult(1000 * 1000, cs.shift); - - freq = ticks_freq(); - - return init_clock(&cs); -} diff --git a/arch/efi/include/asm/barebox.h b/arch/efi/include/asm/barebox.h deleted file mode 100644 index 2997587d82..0000000000 --- a/arch/efi/include/asm/barebox.h +++ /dev/null @@ -1 +0,0 @@ -/* dummy */ diff --git a/arch/efi/include/asm/bitops.h b/arch/efi/include/asm/bitops.h deleted file mode 100644 index 447023da63..0000000000 --- a/arch/efi/include/asm/bitops.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _SANDBOX_BITOPS_H -#define _SANDBOX_BITOPS_H - -/* nothing but the defaults.. */ -#include <asm-generic/bitops/__ffs.h> -#include <asm-generic/bitops/__fls.h> -#include <asm-generic/bitops/ffs.h> -#include <asm-generic/bitops/fls.h> -#include <asm-generic/bitops/ffz.h> -#include <asm-generic/bitops/find.h> -#include <asm-generic/bitops/fls64.h> -#include <asm-generic/bitops/hweight.h> -#include <asm-generic/bitops/ops.h> - -#define set_bit(x, y) __set_bit(x, y) -#define clear_bit(x, y) __clear_bit(x, y) -#define change_bit(x, y) __change_bit(x, y) -#define test_and_set_bit(x, y) __test_and_set_bit(x, y) -#define test_and_clear_bit(x, y) __test_and_clear_bit(x, y) -#define test_and_change_bit(x, y) __test_and_change_bit(x, y) - -#endif diff --git a/arch/efi/include/asm/bitsperlong.h b/arch/efi/include/asm/bitsperlong.h deleted file mode 100644 index 00c1fc2625..0000000000 --- a/arch/efi/include/asm/bitsperlong.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __ASM_BITSPERLONG_H -#define __ASM_BITSPERLONG_H - -#ifdef __x86_64__ -#define BITS_PER_LONG 64 -#else -#define BITS_PER_LONG 32 -#endif - -#endif /* __ASM_BITSPERLONG_H */ diff --git a/arch/efi/include/asm/byteorder.h b/arch/efi/include/asm/byteorder.h deleted file mode 100644 index 37316f2371..0000000000 --- a/arch/efi/include/asm/byteorder.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _I386_BYTEORDER_H -#define _I386_BYTEORDER_H - -#include <asm/types.h> - -#include <linux/byteorder/little_endian.h> - -#endif /* _I386_BYTEORDER_H */ diff --git a/arch/efi/include/asm/common.h b/arch/efi/include/asm/common.h deleted file mode 100644 index b0e6b7fb18..0000000000 --- a/arch/efi/include/asm/common.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef ASM_COMMON_H -#define ASM_COMMON_H - -#endif /* ASM_COMMON_H */ diff --git a/arch/efi/include/asm/dma.h b/arch/efi/include/asm/dma.h deleted file mode 100644 index 459536779e..0000000000 --- a/arch/efi/include/asm/dma.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de> - * - * This file is released under the GPLv2 - * - */ - -#ifndef __ASM_DMA_H -#define __ASM_DMA_H - -/* empty*/ - -#endif /* __ASM_DMA_H */ diff --git a/arch/efi/include/asm/elf.h b/arch/efi/include/asm/elf.h deleted file mode 100644 index ddde035188..0000000000 --- a/arch/efi/include/asm/elf.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __ASM_SANDBOX_ELF_H__ -#define __ASM_SANDBOX_ELF_H__ - -#ifdef __i386__ - -typedef struct user_fxsr_struct elf_fpxregset_t; - -#define R_386_NONE 0 -#define R_386_32 1 -#define R_386_PC32 2 -#define R_386_GOT32 3 -#define R_386_PLT32 4 -#define R_386_COPY 5 -#define R_386_GLOB_DAT 6 -#define R_386_JMP_SLOT 7 -#define R_386_RELATIVE 8 -#define R_386_GOTOFF 9 -#define R_386_GOTPC 10 -#define R_386_NUM 11 - -/* - * These are used to set parameters in the core dumps. - */ -#define ELF_CLASS ELFCLASS32 -#define ELF_DATA ELFDATA2LSB -#define ELF_ARCH EM_386 - -#else - -/* x86-64 relocation types */ -#define R_X86_64_NONE 0 /* No reloc */ -#define R_X86_64_64 1 /* Direct 64 bit */ -#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ -#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ -#define R_X86_64_PLT32 4 /* 32 bit PLT address */ -#define R_X86_64_COPY 5 /* Copy symbol at runtime */ -#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ -#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ -#define R_X86_64_RELATIVE 8 /* Adjust by program base */ -#define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative - offset to GOT */ -#define R_X86_64_32 10 /* Direct 32 bit zero extended */ -#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ -#define R_X86_64_16 12 /* Direct 16 bit zero extended */ -#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ -#define R_X86_64_8 14 /* Direct 8 bit sign extended */ -#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ - -#define R_X86_64_NUM 16 - -/* - * These are used to set parameters in the core dumps. - */ -#define ELF_CLASS ELFCLASS64 -#define ELF_DATA ELFDATA2LSB -#define ELF_ARCH EM_X86_64 - -#endif - -#endif /* __ASM_SANDBOX_ELF_H__ */ diff --git a/arch/efi/include/asm/io.h b/arch/efi/include/asm/io.h deleted file mode 100644 index ac8a9c1b35..0000000000 --- a/arch/efi/include/asm/io.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef __ASM_SANDBOX_IO_H -#define __ASM_SANDBOX_IO_H - -#define build_mmio_read(name, size, type, reg, barrier) \ - static inline type name(const volatile void *addr) \ - { type ret; asm volatile("mov" size " %1,%0":reg (ret) \ - :"m" (*(volatile type*)addr) barrier); return ret; } - -build_mmio_read(readb, "b", unsigned char, "=q", :"memory") -build_mmio_read(readw, "w", unsigned short, "=r", :"memory") -build_mmio_read(readl, "l", unsigned int, "=r", :"memory") - -#define build_mmio_write(name, size, type, reg, barrier) \ - static inline void name(type val, volatile void *addr) \ - { asm volatile("mov" size " %0,%1": :reg (val), \ - "m" (*(volatile type*)addr) barrier); } - -build_mmio_write(writeb, "b", unsigned char, "q", :"memory") -build_mmio_write(writew, "w", unsigned short, "r", :"memory") -build_mmio_write(writel, "l", unsigned int, "r", :"memory") - -#define BUILDIO(bwl, bw, type) \ -static inline void out##bwl(unsigned type value, int port) \ -{ \ - asm volatile("out" #bwl " %" #bw "0, %w1" \ - : : "a"(value), "Nd"(port)); \ -} \ - \ -static inline unsigned type in##bwl(int port) \ -{ \ - unsigned type value; \ - asm volatile("in" #bwl " %w1, %" #bw "0" \ - : "=a"(value) : "Nd"(port)); \ - return value; \ -} \ - \ -static inline void outs##bwl(int port, const void *addr, unsigned long count) \ -{ \ - asm volatile("rep; outs" #bwl \ - : "+S"(addr), "+c"(count) : "d"(port)); \ -} \ - \ -static inline void ins##bwl(int port, void *addr, unsigned long count) \ -{ \ - asm volatile("rep; ins" #bwl \ - : "+D"(addr), "+c"(count) : "d"(port)); \ -} - -BUILDIO(b, b, char) -BUILDIO(w, w, short) -BUILDIO(l, , int) - -#define IO_SPACE_LIMIT 0xffff - -#endif /* __ASM_SANDBOX_IO_H */ diff --git a/arch/efi/include/asm/posix_types.h b/arch/efi/include/asm/posix_types.h deleted file mode 100644 index 22cae6230c..0000000000 --- a/arch/efi/include/asm/posix_types.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/posix_types.h> diff --git a/arch/efi/include/asm/sections.h b/arch/efi/include/asm/sections.h deleted file mode 100644 index 2b8c516038..0000000000 --- a/arch/efi/include/asm/sections.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/sections.h> diff --git a/arch/efi/include/asm/string.h b/arch/efi/include/asm/string.h deleted file mode 100644 index 2997587d82..0000000000 --- a/arch/efi/include/asm/string.h +++ /dev/null @@ -1 +0,0 @@ -/* dummy */ diff --git a/arch/efi/include/asm/swab.h b/arch/efi/include/asm/swab.h deleted file mode 100644 index 60a90120b6..0000000000 --- a/arch/efi/include/asm/swab.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_SWAB_H -#define _ASM_SWAB_H - -/* nothing. use generic functions */ - -#endif /* _ASM_SWAB_H */ diff --git a/arch/efi/include/asm/types.h b/arch/efi/include/asm/types.h deleted file mode 100644 index 3caac398d8..0000000000 --- a/arch/efi/include/asm/types.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef __ASM_I386_TYPES_H -#define __ASM_I386_TYPES_H - -#ifndef __ASSEMBLY__ - -#ifdef __x86_64__ -/* - * This is used in dlmalloc. On X86_64 we need it to be - * 64 bit - */ -#define INTERNAL_SIZE_T unsigned long - -/* - * This is a Kconfig variable in the Kernel, but we want to detect - * this during compile time, so we set it here. - */ -#define CONFIG_PHYS_ADDR_T_64BIT - -#endif - -typedef unsigned short umode_t; - -/* - * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the - * header files exported to user space - */ - -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; - -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) -typedef __signed__ long long __s64; -typedef unsigned long long __u64; -#endif - -/* - * These aren't exported outside the kernel to avoid name space clashes - */ -#ifdef __KERNEL__ - -typedef signed char s8; -typedef unsigned char u8; - -typedef signed short s16; -typedef unsigned short u16; - -typedef signed int s32; -typedef unsigned int u32; - -typedef signed long long s64; -typedef unsigned long long u64; - -#include <asm/bitsperlong.h> - -#endif /* __KERNEL__ */ - -#endif - -#endif diff --git a/arch/efi/include/asm/unaligned.h b/arch/efi/include/asm/unaligned.h deleted file mode 100644 index d02da6e60d..0000000000 --- a/arch/efi/include/asm/unaligned.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _ASM_SANDBOX_UNALIGNED_H -#define _ASM_SANDBOX_UNALIGNED_H - -/* - * The architecture sandbox is compiled on can do unaligned accesses itself. - */ - -#include <linux/unaligned/access_ok.h> -#include <linux/unaligned/generic.h> - -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define get_unaligned __get_unaligned_le -#define put_unaligned __put_unaligned_le -#else -#define get_unaligned __get_unaligned_be -#define put_unaligned __put_unaligned_be -#endif - -#endif /* _ASM_SANDBOX_UNALIGNED_H */ diff --git a/arch/efi/lib/asm-offsets.c b/arch/efi/lib/asm-offsets.c deleted file mode 100644 index 22f382b71e..0000000000 --- a/arch/efi/lib/asm-offsets.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Generate definitions needed by assembly language modules. - * This code generates raw asm output which is post-processed to extract - * and format the required data. - */ - -#include <linux/kbuild.h> - -int main(void) -{ - return 0; -} diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 346640dcda..52ccf4894f 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1,9 +1,16 @@ # # # +config X86 + bool + select HAS_KALLSYMS + select GENERIC_FIND_NEXT_BIT + default y + config ARCH_TEXT_BASE hex default 0x00007c00 if MACH_X86_GENERIC + default 0x0 if MACH_EFI_GENERIC config BOARD_LINKER_SCRIPT bool @@ -14,17 +21,33 @@ config GENERIC_LINKER_SCRIPT default y depends on !BOARD_LINKER_SCRIPT -config X86 +menu "ARCH specific settings" + +config 64BIT + def_bool y if X86_EFI + help + Say yes to build a 64-bit binary - formerly known as x86_64 + Say no to build a 32-bit binary - formerly known as i386. + + 32-bit support currently does not compile and is not tested + due to the lack of hardware. + +config X86_32 + def_bool y + depends on !64BIT + +config X86_64 + def_bool y + depends on 64BIT + +endmenu + +config X86_BOOTLOADER bool - select HAS_KALLSYMS + select X86_32 select HAS_MODULES select HAVE_CONFIGURABLE_MEMORY_LAYOUT select HAVE_CONFIGURABLE_TEXT_BASE - select GENERIC_FIND_NEXT_BIT - default y - -config X86_BOOTLOADER - bool choice prompt "Select your board" @@ -32,14 +55,30 @@ choice config MACH_X86_GENERIC bool "Generic x86" select X86_BOOTLOADER + depends on !X86_EFI help Say Y here if you want barebox to be your BIOS based bootloader +config MACH_EFI_GENERIC + bool "Generic EFI" + depends on X86_EFI + select HAS_DEBUG_LL + help + Say Y here if you want barebox to be your EFI based bootloader + endchoice choice prompt "Bring up type" + config X86_EFI + bool "EFI" + select EFI_BOOTUP + select EFI_GUID + select EFI_DEVICEPATH + select PRINTF_UUID + select CLOCKSOURCE_EFI_X86 + config X86_BIOS_BRINGUP bool "16 bit BIOS" help diff --git a/arch/x86/Makefile b/arch/x86/Makefile index da17d70bdc..0751e63649 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -1,20 +1,47 @@ KBUILD_DEFCONFIG := generic_defconfig -CPPFLAGS += -D__X86__ -fno-strict-aliasing +CPPFLAGS += -D__X86__ -board-y := x86_generic -machine-y := i386 +board-$(CONFIG_MACH_X86_GENERIC) := x86_generic TEXT_BASE = $(CONFIG_TEXT_BASE) -CPPFLAGS += -march=i386 -m32 -DTEXT_BASE=$(TEXT_BASE) \ +ifeq ($(CONFIG_X86_EFI),y) +machine-y := efi +CFLAGS += -fpic -fshort-wchar -mno-sse -mno-mmx +ifeq ($(CONFIG_X86_32),y) + TARGET = efi-app-ia32 +else + TARGET = efi-app-x86_64 +endif +else +CPPFLAGS += -fno-strict-aliasing +CPPFLAGS += -march=i386 -DTEXT_BASE=$(TEXT_BASE) \ -fno-unwind-tables -fno-asynchronous-unwind-tables -LDFLAGS += -m elf_i386 + +machine-y := i386 +endif + +ifeq ($(CONFIG_X86_32),y) + UTS_MACHINE := i386 + biarch := $(call cc-option,-m32) + AFLAGS += $(biarch) + CFLAGS += $(biarch) + CPPFLAGS += $(biarch) +else + UTS_MACHINE := x86_64 + AFLAGS += -m64 + CFLAGS += -m64 -mno-red-zone + CPPFLAGS += -m64 +endif + ifndef CONFIG_MODULES # Add cleanup flags +ifneq ($(CONFIG_X86_EFI),y) CPPFLAGS += -fdata-sections -ffunction-sections -LDFLAGS_uboot += -static --gc-sections +LDFLAGS_barebox += -static --gc-sections +endif endif machdirs := $(patsubst %,arch/x86/mach-%/,$(machine-y)) @@ -39,12 +66,46 @@ endif common-y += $(BOARD) $(MACH) common-y += arch/x86/lib/ -common-y += arch/x86/boot/ +common-$(CONFIG_X86_BIOS_BRINGUP) += arch/x86/bios/ # arch/x86/cpu/ +ifeq ($(CONFIG_X86_EFI),y) +lds-$(CONFIG_X86_32) := arch/x86/mach-efi/elf_ia32_efi.lds +lds-$(CONFIG_X86_64) := arch/x86/mach-efi/elf_x86_64_efi.lds + +cmd_barebox__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_barebox) -o $@ \ + -T $(lds-y) \ + -shared -Bsymbolic -nostdlib -znocombreloc \ + --start-group $(barebox-common) \ + --end-group \ + $(filter-out $(barebox-lds) $(barebox-common) FORCE ,$^) + +quiet_cmd_efi_image = EFI-IMG $@ + cmd_efi_image = $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic \ + -j .dynsym -j .rel -j .rela -j .reloc -j __barebox_initcalls \ + -j __barebox_exitcalls -j __barebox_cmd -j .barebox_magicvar \ + -j .bbenv.* -j .bblogo.* --target=$(TARGET) $< $@ + +KBUILD_BINARY := barebox + +LDFLAGS := --no-undefined + +barebox.efi: $(KBUILD_BINARY) FORCE + $(call if_changed,efi_image) + +KBUILD_IMAGE := barebox.efi + +else +common-y += arch/x86/boot/ + lds-$(CONFIG_GENERIC_LINKER_SCRIPT) := arch/x86/lib/barebox.lds lds-$(CONFIG_BOARD_LINKER_SCRIPT) := $(BOARD)/barebox.lds +endif + +LDFLAGS += -m elf_$(UTS_MACHINE) + +CLEAN_FILES += $(lds-y) CLEAN_FILES += arch/x86/lib/barebox.lds barebox.map barebox.S diff --git a/arch/x86/bios/Makefile b/arch/x86/bios/Makefile new file mode 100644 index 0000000000..414ee42a4a --- /dev/null +++ b/arch/x86/bios/Makefile @@ -0,0 +1,3 @@ +obj-y += memory16.o +obj-y += traveler.o +obj-y += bios_disk.o diff --git a/arch/x86/lib/bios_disk.S b/arch/x86/bios/bios_disk.S index cce33e67af..cce33e67af 100644 --- a/arch/x86/lib/bios_disk.S +++ b/arch/x86/bios/bios_disk.S diff --git a/arch/x86/lib/memory16.S b/arch/x86/bios/memory16.S index 76ee72b56c..76ee72b56c 100644 --- a/arch/x86/lib/memory16.S +++ b/arch/x86/bios/memory16.S diff --git a/arch/x86/lib/traveler.S b/arch/x86/bios/traveler.S index 113b19802e..113b19802e 100644 --- a/arch/x86/lib/traveler.S +++ b/arch/x86/bios/traveler.S diff --git a/arch/efi/configs/efi_defconfig b/arch/x86/configs/efi_defconfig index f24148d3bc..0d9a44a4d2 100644 --- a/arch/efi/configs/efi_defconfig +++ b/arch/x86/configs/efi_defconfig @@ -1,7 +1,6 @@ CONFIG_MMU=y CONFIG_MALLOC_SIZE=0x0 CONFIG_MALLOC_TLSF=y -CONFIG_PROMPT="barebox> " CONFIG_HUSH_FANCY_PROMPT=y CONFIG_CMDLINE_EDITING=y CONFIG_AUTO_COMPLETE=y @@ -21,6 +20,7 @@ CONFIG_DEBUG_LL=y CONFIG_LONGHELP=y CONFIG_CMD_IOMEM=y CONFIG_CMD_MEMINFO=y +# CONFIG_CMD_LINUX16 is not set CONFIG_CMD_GO=y CONFIG_CMD_LOADB=y CONFIG_CMD_RESET=y diff --git a/arch/x86/configs/generic_defconfig b/arch/x86/configs/generic_defconfig index 5ff7f531eb..3b94e02a7e 100644 --- a/arch/x86/configs/generic_defconfig +++ b/arch/x86/configs/generic_defconfig @@ -1,3 +1,4 @@ +CONFIG_X86_BIOS_BRINGUP=y CONFIG_X86_HDBOOT=y CONFIG_STACK_SIZE=0x7000 CONFIG_EXPERIMENTAL=y diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 94a40c6243..ddde035188 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -1,26 +1,60 @@ +#ifndef __ASM_SANDBOX_ELF_H__ +#define __ASM_SANDBOX_ELF_H__ + +#ifdef __i386__ + +typedef struct user_fxsr_struct elf_fpxregset_t; + +#define R_386_NONE 0 +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GOT32 3 +#define R_386_PLT32 4 +#define R_386_COPY 5 +#define R_386_GLOB_DAT 6 +#define R_386_JMP_SLOT 7 +#define R_386_RELATIVE 8 +#define R_386_GOTOFF 9 +#define R_386_GOTPC 10 +#define R_386_NUM 11 + /* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * + * These are used to set parameters in the core dumps. */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_386 -/** - * @file - * @brief x86 specific elf information - * - */ +#else -#ifndef _ASM_X86_ELF_H -#define _ASM_X86_ELF_H +/* x86-64 relocation types */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative + offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ + +#define R_X86_64_NUM 16 + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS64 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_X86_64 -#define ELF_CLASS ELFCLASS32 +#endif -#endif /* _ASM_X86_ELF_H */ +#endif /* __ASM_SANDBOX_ELF_H__ */ diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index f020510569..df4bc99ec8 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -12,44 +12,6 @@ #include <asm/byteorder.h> -#define IO_SPACE_LIMIT 0xffff - -static inline void outb(unsigned char value, int port) -{ - asm volatile("outb %b0, %w1" : : "a"(value), "Nd"(port)); -} - -static inline void outw(unsigned short value, int port) -{ - asm volatile("outw %w0, %w1" : : "a"(value), "Nd"(port)); -} - -static inline void outl(unsigned long value, int port) -{ - asm volatile("outl %0, %w1" : : "a"(value), "Nd"(port)); -} - -static inline unsigned char inb(int port) -{ - unsigned char value; - asm volatile("inb %w1, %b0" : "=a"(value) : "Nd"(port)); - return value; -} - -static inline unsigned short inw(int port) -{ - unsigned short value; - asm volatile("inw %w1, %w0" : "=a"(value) : "Nd"(port)); - return value; -} - -static inline unsigned long inl(int port) -{ - unsigned long value; - asm volatile("inl %w1, %0" : "=a"(value) : "Nd"(port)); - return value; -} - #define build_mmio_read(name, size, type, reg, barrier) \ static inline type name(const volatile void *addr) \ { type ret; asm volatile("mov" size " %1,%0":reg (ret) \ @@ -68,6 +30,39 @@ build_mmio_write(writeb, "b", unsigned char, "q", :"memory") build_mmio_write(writew, "w", unsigned short, "r", :"memory") build_mmio_write(writel, "l", unsigned int, "r", :"memory") +#define BUILDIO(bwl, bw, type) \ +static inline void out##bwl(unsigned type value, int port) \ +{ \ + asm volatile("out" #bwl " %" #bw "0, %w1" \ + : : "a"(value), "Nd"(port)); \ +} \ + \ +static inline unsigned type in##bwl(int port) \ +{ \ + unsigned type value; \ + asm volatile("in" #bwl " %w1, %" #bw "0" \ + : "=a"(value) : "Nd"(port)); \ + return value; \ +} \ + \ +static inline void outs##bwl(int port, const void *addr, unsigned long count) \ +{ \ + asm volatile("rep; outs" #bwl \ + : "+S"(addr), "+c"(count) : "d"(port)); \ +} \ + \ +static inline void ins##bwl(int port, void *addr, unsigned long count) \ +{ \ + asm volatile("rep; ins" #bwl \ + : "+D"(addr), "+c"(count) : "d"(port)); \ +} + +BUILDIO(b, b, char) +BUILDIO(w, w, short) +BUILDIO(l, , int) + +#define IO_SPACE_LIMIT 0xffff + /* do a tiny io delay */ static inline void io_delay(void) { diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h index 7349ba03c2..3caac398d8 100644 --- a/arch/x86/include/asm/types.h +++ b/arch/x86/include/asm/types.h @@ -1,21 +1,29 @@ +#ifndef __ASM_I386_TYPES_H +#define __ASM_I386_TYPES_H + +#ifndef __ASSEMBLY__ + +#ifdef __x86_64__ +/* + * This is used in dlmalloc. On X86_64 we need it to be + * 64 bit + */ +#define INTERNAL_SIZE_T unsigned long + /* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * + * This is a Kconfig variable in the Kernel, but we want to detect + * this during compile time, so we set it here. */ +#define CONFIG_PHYS_ADDR_T_64BIT -#ifndef __ASM_X86_TYPES_H -#define __ASM_X86_TYPES_H +#endif -#ifndef __ASSEMBLY__ +typedef unsigned short umode_t; + +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ typedef __signed__ char __s8; typedef unsigned char __u8; @@ -26,8 +34,15 @@ typedef unsigned short __u16; typedef __signed__ int __s32; typedef unsigned int __u32; +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) typedef __signed__ long long __s64; typedef unsigned long long __u64; +#endif + +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +#ifdef __KERNEL__ typedef signed char s8; typedef unsigned char u8; @@ -41,10 +56,10 @@ typedef unsigned int u32; typedef signed long long s64; typedef unsigned long long u64; -typedef unsigned short umode_t; +#include <asm/bitsperlong.h> -#include <asm-generic/bitsperlong.h> +#endif /* __KERNEL__ */ -#endif /* __ASSEMBLY__ */ +#endif -#endif /* __ASM_X86_TYPES_H */ +#endif diff --git a/arch/x86/include/asm/unaligned.h b/arch/x86/include/asm/unaligned.h index a7bd416b47..7e38706c5d 100644 --- a/arch/x86/include/asm/unaligned.h +++ b/arch/x86/include/asm/unaligned.h @@ -8,7 +8,12 @@ #include <linux/unaligned/access_ok.h> #include <linux/unaligned/generic.h> +#if __BYTE_ORDER == __LITTLE_ENDIAN #define get_unaligned __get_unaligned_le #define put_unaligned __put_unaligned_le +#else +#define get_unaligned __get_unaligned_be +#define put_unaligned __put_unaligned_be +#endif #endif /* _ASM_X86_UNALIGNED_H */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index b67629f115..05e43f0f2b 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -1,9 +1,8 @@ extra-$(CONFIG_GENERIC_LINKER_SCRIPT) += barebox.lds +ifneq ($(CONFIG_X86_EFI),y) obj-y += memory.o obj-y += gdt.o +endif # needed, when running via a 16 bit BIOS -obj-$(CONFIG_X86_BIOS_BRINGUP) += memory16.o -obj-$(CONFIG_X86_BIOS_BRINGUP) += traveler.o -obj-$(CONFIG_X86_BIOS_BRINGUP) += bios_disk.o obj-$(CONFIG_CMD_LINUX16) += linux_start.o diff --git a/arch/x86/lib/asm-offsets.c b/arch/x86/lib/asm-offsets.c index b1be3e5390..0f9c47eaa9 100644 --- a/arch/x86/lib/asm-offsets.c +++ b/arch/x86/lib/asm-offsets.c @@ -6,6 +6,13 @@ #include <linux/kbuild.h> +#ifdef CONFIG_EFI_BOOTUP +int main(void) +{ + return 0; +} +#else void common(void) { } +#endif diff --git a/arch/efi/lib/.gitignore b/arch/x86/mach-efi/.gitignore index 847e317701..847e317701 100644 --- a/arch/efi/lib/.gitignore +++ b/arch/x86/mach-efi/.gitignore diff --git a/arch/efi/lib/Makefile b/arch/x86/mach-efi/Makefile index c8a97bae07..f633e7c7ed 100644 --- a/arch/efi/lib/Makefile +++ b/arch/x86/mach-efi/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_X86_64) += reloc_x86_64.o crt0-efi-x86_64.o obj-$(CONFIG_X86_32) += reloc_ia32.o crt0-efi-ia32.o +obj-y += clocksource.o extra-$(CONFIG_X86_32) += elf_ia32_efi.lds extra-$(CONFIG_X86_64) += elf_x86_64_efi.lds diff --git a/arch/x86/mach-efi/clocksource.c b/arch/x86/mach-efi/clocksource.c new file mode 100644 index 0000000000..2023fa19ac --- /dev/null +++ b/arch/x86/mach-efi/clocksource.c @@ -0,0 +1,11 @@ +#include <common.h> +#include <init.h> +#include <driver.h> + +static int efi_x86_pure_init(void) +{ + struct device_d *dev = device_alloc("efi-cs-x86", DEVICE_ID_SINGLE); + + return platform_device_register(dev); +} +core_initcall(efi_x86_pure_init); diff --git a/arch/efi/lib/crt0-efi-ia32.S b/arch/x86/mach-efi/crt0-efi-ia32.S index 6f0f2e872e..6f0f2e872e 100644 --- a/arch/efi/lib/crt0-efi-ia32.S +++ b/arch/x86/mach-efi/crt0-efi-ia32.S diff --git a/arch/efi/lib/crt0-efi-x86_64.S b/arch/x86/mach-efi/crt0-efi-x86_64.S index aa03106e9c..aa03106e9c 100644 --- a/arch/efi/lib/crt0-efi-x86_64.S +++ b/arch/x86/mach-efi/crt0-efi-x86_64.S diff --git a/arch/efi/lib/elf_ia32_efi.lds.S b/arch/x86/mach-efi/elf_ia32_efi.lds.S index 69f43f5547..69f43f5547 100644 --- a/arch/efi/lib/elf_ia32_efi.lds.S +++ b/arch/x86/mach-efi/elf_ia32_efi.lds.S diff --git a/arch/efi/lib/elf_x86_64_efi.lds.S b/arch/x86/mach-efi/elf_x86_64_efi.lds.S index 93d34d17ab..93d34d17ab 100644 --- a/arch/efi/lib/elf_x86_64_efi.lds.S +++ b/arch/x86/mach-efi/elf_x86_64_efi.lds.S diff --git a/arch/x86/mach-efi/include/mach/barebox.lds.h b/arch/x86/mach-efi/include/mach/barebox.lds.h new file mode 100644 index 0000000000..40a8c178f1 --- /dev/null +++ b/arch/x86/mach-efi/include/mach/barebox.lds.h @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/x86/mach-efi/include/mach/debug_ll.h b/arch/x86/mach-efi/include/mach/debug_ll.h new file mode 100644 index 0000000000..e144d86e00 --- /dev/null +++ b/arch/x86/mach-efi/include/mach/debug_ll.h @@ -0,0 +1 @@ +#include <efi/debug_ll.h> diff --git a/arch/efi/lib/reloc_ia32.c b/arch/x86/mach-efi/reloc_ia32.c index 46929631ec..46929631ec 100644 --- a/arch/efi/lib/reloc_ia32.c +++ b/arch/x86/mach-efi/reloc_ia32.c diff --git a/arch/efi/lib/reloc_x86_64.c b/arch/x86/mach-efi/reloc_x86_64.c index 1db72f5dbc..1db72f5dbc 100644 --- a/arch/efi/lib/reloc_x86_64.c +++ b/arch/x86/mach-efi/reloc_x86_64.c diff --git a/commands/Kconfig b/commands/Kconfig index 21d921268f..bc0885c69d 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -370,7 +370,7 @@ config CMD_BOOTZ config CMD_LINUX16 tristate - depends on X86 + depends on X86 && !X86_EFI default y if X86 prompt "linux16" help diff --git a/commands/edit.c b/commands/edit.c index a5415a6e5b..696a818d9d 100644 --- a/commands/edit.c +++ b/commands/edit.c @@ -396,7 +396,7 @@ static int do_edit(int argc, char *argv[]) * down when we write to the right bottom screen position. Reduce the number * of rows by one to work around this. */ - if (IS_ENABLED(CONFIG_ARCH_EFI)) + if (IS_ENABLED(CONFIG_EFI_BOOTUP)) screenheight = 24; else screenheight = 25; diff --git a/common/Makefile b/common/Makefile index 869b15a92a..5f58c81d22 100644 --- a/common/Makefile +++ b/common/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_BOOTCHOOSER) += bootchooser.o obj-$(CONFIG_UIMAGE) += image.o uimage.o obj-$(CONFIG_FITIMAGE) += image-fit.o obj-$(CONFIG_MENUTREE) += menutree.o +obj-$(CONFIG_EFI_BOOTUP) += efi/ obj-$(CONFIG_EFI_GUID) += efi-guid.o obj-$(CONFIG_EFI_DEVICEPATH) += efi-devicepath.o lwl-$(CONFIG_IMD) += imd-barebox.o diff --git a/common/clock.c b/common/clock.c index 2c5dd91ccd..0d581c2c7e 100644 --- a/common/clock.c +++ b/common/clock.c @@ -36,9 +36,32 @@ static uint64_t time_ns; */ uint64_t time_beginning; +static uint64_t dummy_read(void) +{ + static uint64_t dummy_counter; + + dummy_counter += CONFIG_CLOCKSOURCE_DUMMY_RATE; + + return dummy_counter; +} + +static struct clocksource dummy_cs = { + .shift = 0, + .mult = 1, + .read = dummy_read, + .mask = CLOCKSOURCE_MASK(64), + .priority = -1, +}; + +static int dummy_csrc_init(void) +{ + return init_clock(&dummy_cs); +} +pure_initcall(dummy_csrc_init); + static int dummy_csrc_warn(void) { - if (!current_clock) { + if (current_clock == &dummy_cs) { pr_warn("Warning: Using dummy clocksource\n"); } @@ -55,14 +78,6 @@ uint64_t get_time_ns(void) uint64_t cycle_now, cycle_delta; uint64_t ns_offset; - if (!cs) { - static uint64_t dummy_counter; - - dummy_counter += CONFIG_CLOCKSOURCE_DUMMY_RATE; - - return dummy_counter; - } - /* read clocksource: */ cycle_now = cs->read() & cs->mask; @@ -213,6 +228,17 @@ EXPORT_SYMBOL(mdelay_non_interruptible); int init_clock(struct clocksource *cs) { + if (current_clock && cs->priority <= current_clock->priority) + return 0; + + if (cs->init) { + int ret; + + ret = cs->init(cs); + if (ret) + return ret; + } + current_clock = cs; time_beginning = get_time_ns(); diff --git a/common/efi-guid.c b/common/efi-guid.c index 64f3b1f65f..71aa21ddda 100644 --- a/common/efi-guid.c +++ b/common/efi-guid.c @@ -75,6 +75,12 @@ const char *efi_guid_string(efi_guid_t *g) EFI_GUID_STRING(EFI_COMPONENT_NAME2_PROTOCOL_GUID, "Component Name2 Protocol", "UEFI 2.0 Component Name2 Protocol"); EFI_GUID_STRING(EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID_31, "Network Interface Identifier Protocol_31", "EFI1.1 Network Interface Identifier Protocol"); EFI_GUID_STRING(EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID, "Network Interface Identifier Protocol", "EFI Network Interface Identifier Protocol"); + EFI_GUID_STRING(EFI_TIMESTAMP_PROTOCOL_GUID, "Timestamp", "Timestamp"); + + /* TPM 1.2 */ + EFI_GUID_STRING( EFI_TCG_PROTOCOL_GUID, "TcgService", "TCGServices Protocol"); + /* TPM 2.0 */ + EFI_GUID_STRING( EFI_TCG2_PROTOCOL_GUID, "Tcg2Service", "TCG2Services Protocol"); /* File */ EFI_GUID_STRING(EFI_IDEBUSDXE_INF_GUID, "IdeBusDxe.inf", "EFI IdeBusDxe.inf File GUID"); diff --git a/common/efi/Makefile b/common/efi/Makefile new file mode 100644 index 0000000000..ef19969f93 --- /dev/null +++ b/common/efi/Makefile @@ -0,0 +1,3 @@ +obj-y += efi.o +obj-y += efi-image.o +bbenv-y += env-efi diff --git a/arch/efi/efi/efi-image.c b/common/efi/efi-image.c index 27f3c1b39c..885348da45 100644 --- a/arch/efi/efi/efi-image.c +++ b/common/efi/efi-image.c @@ -36,8 +36,8 @@ #include <libfile.h> #include <binfmt.h> #include <wchar.h> -#include <mach/efi.h> -#include <mach/efi-device.h> +#include <efi/efi.h> +#include <efi/efi-device.h> struct linux_kernel_header { /* first sector of the image */ diff --git a/arch/efi/efi/efi.c b/common/efi/efi.c index 36ac016a91..05c58250f4 100644 --- a/arch/efi/efi/efi.c +++ b/common/efi/efi.c @@ -38,8 +38,8 @@ #include <wchar.h> #include <envfs.h> #include <efi.h> -#include <mach/efi.h> -#include <mach/efi-device.h> +#include <efi/efi.h> +#include <efi/efi-device.h> efi_runtime_services_t *RT; efi_boot_services_t *BS; @@ -119,7 +119,7 @@ struct efi_boot { void *binary; }; -struct efi_boot *efi_get_boot(int num) +static struct efi_boot *efi_get_boot(int num) { struct efi_boot *boot = xzalloc(sizeof(*boot)); void *buf, *ptr; @@ -314,7 +314,6 @@ efi_status_t efi_main(efi_handle_t image, efi_system_table_t *sys_table) efi_physical_addr_t mem; size_t memsize; efi_status_t efiret; - char *uuid; #ifdef DEBUG sys_table->con_out->output_string(sys_table->con_out, L"barebox\n"); @@ -349,7 +348,23 @@ efi_status_t efi_main(efi_handle_t image, efi_system_table_t *sys_table) efi_strerror(efiret)); mem_malloc_init((void *)mem, (void *)mem + memsize); - efi_clocksource_init(); + start_barebox(); + + return EFI_SUCCESS; +} + +static int efi_core_init(void) +{ + struct device_d *dev = device_alloc("efi-cs", DEVICE_ID_SINGLE); + + return platform_device_register(dev); +} +core_initcall(efi_core_init); + +static int efi_postcore_init(void) +{ + char *uuid; + efi_set_variable_usec("LoaderTimeInitUSec", &efi_systemd_vendor_guid, get_time_ns()/1000); @@ -366,10 +381,9 @@ efi_status_t efi_main(efi_handle_t image, efi_system_table_t *sys_table) free(uuid16); } - start_barebox(); - - return EFI_SUCCESS; + return 0; } +postcore_initcall(efi_postcore_init); static int do_efiexit(int argc, char *argv[]) { diff --git a/arch/efi/efi/env-efi/network/eth0-discover b/common/efi/env-efi/network/eth0-discover index 62c31a553c..62c31a553c 100644 --- a/arch/efi/efi/env-efi/network/eth0-discover +++ b/common/efi/env-efi/network/eth0-discover diff --git a/common/memory.c b/common/memory.c index 4725f6e382..ad38b00ecb 100644 --- a/common/memory.c +++ b/common/memory.c @@ -67,7 +67,7 @@ void mem_malloc_init(void *start, void *end) mem_malloc_initialized = 1; } -#if !defined __SANDBOX__ && !defined CONFIG_ARCH_EFI +#if !defined __SANDBOX__ && !defined CONFIG_EFI_BOOTUP static int mem_malloc_resource(void) { /* diff --git a/drivers/Kconfig b/drivers/Kconfig index cc086ac2df..bf31115fa0 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -1,5 +1,6 @@ menu "Drivers" +source "drivers/efi/Kconfig" source "drivers/of/Kconfig" source "drivers/aiodev/Kconfig" source "drivers/amba/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 6a70f6ee19..0fadf4e44b 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -1,5 +1,7 @@ obj-y += base/ +obj-y += block/ obj-$(CONFIG_ARM_AMBA) += amba/ +obj-$(CONFIG_EFI_BOOTUP) += efi/ obj-y += net/ obj-y += serial/ obj-y += mtd/ diff --git a/drivers/block/Makefile b/drivers/block/Makefile new file mode 100644 index 0000000000..8812c0faec --- /dev/null +++ b/drivers/block/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_EFI_BOOTUP) += efi-block-io.o diff --git a/arch/efi/efi/efi-block-io.c b/drivers/block/efi-block-io.c index e02d3b49cc..a4d9d3a95d 100644 --- a/arch/efi/efi/efi-block-io.c +++ b/drivers/block/efi-block-io.c @@ -12,8 +12,8 @@ #include <efi.h> #include <block.h> #include <disks.h> -#include <mach/efi.h> -#include <mach/efi-device.h> +#include <efi/efi.h> +#include <efi/efi-device.h> #define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001 #define EFI_BLOCK_IO_PROTOCOL_REVISION3 ((2<<16) | (31)) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index f3c3255ffc..23ad20afcf 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -34,6 +34,14 @@ config CLOCKSOURCE_DUMMY_RATE The option CONFIG_CLOCKSOURCE_DUMMY_RATE is used to adjust this clocksource. The bigger rate valuest makes clocksource "faster". +config CLOCKSOURCE_EFI + bool "Generic EFI Driver" + depends on EFI_BOOTUP + +config CLOCKSOURCE_EFI_X86 + bool "EFI X86 HW driver" + depends on EFI_BOOTUP && X86 + config CLOCKSOURCE_MVEBU bool depends on ARCH_MVEBU diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 0564d8f5a9..f774edee46 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -3,6 +3,8 @@ obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o obj-$(CONFIG_CLOCKSOURCE_BCM283X) += bcm2835.o obj-$(CONFIG_CLOCKSOURCE_CLPS711X) += clps711x.o obj-$(CONFIG_CLOCKSOURCE_DIGIC) += digic.o +obj-$(CONFIG_CLOCKSOURCE_EFI) += efi.o +obj-$(CONFIG_CLOCKSOURCE_EFI_X86) += efi_x86.o obj-$(CONFIG_CLOCKSOURCE_MVEBU) += mvebu.o obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o obj-$(CONFIG_CLOCKSOURCE_ORION) += orion.o diff --git a/drivers/clocksource/efi.c b/drivers/clocksource/efi.c new file mode 100644 index 0000000000..89906c452e --- /dev/null +++ b/drivers/clocksource/efi.c @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2017 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com> + * + * Under GPL v2 + */ +#include <common.h> +#include <init.h> +#include <driver.h> +#include <clock.h> +#include <efi.h> +#include <efi/efi.h> +#include <efi/efi-device.h> +#include <linux/err.h> + +static uint64_t ticks = 1; +static void *efi_cs_evt; + +static uint64_t efi_cs_read(void) +{ + return ticks; +} + +static void efi_cs_inc(void *event, void *ctx) +{ + ticks++; +} + +/* count ticks during a 1dms */ +static uint64_t ticks_freq(void) +{ + uint64_t ticks_start, ticks_end; + + ticks_start = ticks; + BS->stall(1000); + ticks_end = ticks; + + return (ticks_end - ticks_start) * 1000; +} + +/* count ticks during a 20ms delay as on qemu x86_64 the max is 100Hz */ +static uint64_t ticks_freq_x86(void) +{ + uint64_t ticks_start, ticks_end; + + ticks_start = ticks; + BS->stall(20 * 1000); + ticks_end = ticks; + + return (ticks_end - ticks_start) * 50; +} + +static int efi_cs_init(struct clocksource *cs) +{ + efi_status_t efiret; + uint64_t freq; + + efiret = BS->create_event(EFI_EVT_TIMER | EFI_EVT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, efi_cs_inc, NULL, &efi_cs_evt); + + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + efiret = BS->set_timer(efi_cs_evt, EFI_TIMER_PERIODIC, 10); + if (EFI_ERROR(efiret)) { + BS->close_event(efi_cs_evt); + return -efi_errno(efiret); + } + + freq = 1000 * 1000; + if (ticks_freq() < 800 * 1000) { + uint64_t nb_100ns; + + freq = ticks_freq_x86(); + nb_100ns = 10 * 1000 * 1000 / freq; + pr_warn("EFI Event timer too slow freq = %llu Hz\n", freq); + efiret = BS->set_timer(efi_cs_evt, EFI_TIMER_PERIODIC, nb_100ns); + if (EFI_ERROR(efiret)) { + BS->close_event(efi_cs_evt); + return -efi_errno(efiret); + } + } + + cs->mult = clocksource_hz2mult(freq, cs->shift); + + return 0; +} + +static struct clocksource efi_cs = { + .read = efi_cs_read, + .mask = CLOCKSOURCE_MASK(64), + .shift = 0, + .init = efi_cs_init, +}; + +static int efi_cs_probe(struct device_d *dev) +{ + return init_clock(&efi_cs); +} + +static struct driver_d efi_cs_driver = { + .name = "efi-cs", + .probe = efi_cs_probe, +}; + +static int efi_cs_initcall(void) +{ + return platform_driver_register(&efi_cs_driver); +} +/* for efi the time must be init at core initcall level */ +core_initcall(efi_cs_initcall); diff --git a/drivers/clocksource/efi_x86.c b/drivers/clocksource/efi_x86.c new file mode 100644 index 0000000000..4d2657ea1d --- /dev/null +++ b/drivers/clocksource/efi_x86.c @@ -0,0 +1,79 @@ +#include <common.h> +#include <init.h> +#include <driver.h> +#include <efi.h> +#include <efi/efi.h> +#include <clock.h> + +#ifdef __x86_64__ +uint64_t ticks_read(void) +{ + uint64_t a, d; + + __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d)); + + return (d << 32) | a; +} +#else +uint64_t ticks_read(void) +{ + uint64_t val; + + __asm__ volatile ("rdtsc" : "=A" (val)); + + return val; +} +#endif + +static uint64_t freq; + +/* count TSC ticks during a millisecond delay */ +static uint64_t ticks_freq(void) +{ + uint64_t ticks_start, ticks_end; + + ticks_start = ticks_read(); + BS->stall(1000); + ticks_end = ticks_read(); + + return (ticks_end - ticks_start) * 1000; +} + +static uint64_t efi_x86_cs_read(void) +{ + return 1000 * 1000 * ticks_read() / freq; +} + +static int efi_x86_cs_init(struct clocksource *cs) +{ + cs->mult = clocksource_hz2mult(1000 * 1000, cs->shift); + + freq = ticks_freq(); + + return 0; +} + +static struct clocksource efi_x86_cs = { + .read = efi_x86_cs_read, + .mask = CLOCKSOURCE_MASK(64), + .shift = 0, + .priority = 100, + .init = efi_x86_cs_init, +}; + +static int efi_x86_cs_probe(struct device_d *dev) +{ + return init_clock(&efi_x86_cs); +} + +static struct driver_d efi_x86_cs_driver = { + .name = "efi-cs-x86", + .probe = efi_x86_cs_probe, +}; + +static int efi_x86_cs_initcall(void) +{ + return platform_driver_register(&efi_x86_cs_driver); +} +/* for efi the time must be init at core initcall level */ +core_initcall(efi_x86_cs_initcall); diff --git a/drivers/efi/Kconfig b/drivers/efi/Kconfig new file mode 100644 index 0000000000..2cd9dd504f --- /dev/null +++ b/drivers/efi/Kconfig @@ -0,0 +1,2 @@ +config EFI_BOOTUP + bool diff --git a/drivers/efi/Makefile b/drivers/efi/Makefile new file mode 100644 index 0000000000..de31212f25 --- /dev/null +++ b/drivers/efi/Makefile @@ -0,0 +1 @@ +obj-y += efi-device.o diff --git a/arch/efi/efi/efi-device.c b/drivers/efi/efi-device.c index 678a28399d..6ed7f12b37 100644 --- a/arch/efi/efi/efi-device.c +++ b/drivers/efi/efi-device.c @@ -27,8 +27,8 @@ #include <wchar.h> #include <init.h> #include <efi.h> -#include <mach/efi.h> -#include <mach/efi-device.h> +#include <efi/efi.h> +#include <efi/efi-device.h> #include <linux/err.h> int efi_locate_handle(enum efi_locate_search_type search_type, @@ -341,12 +341,246 @@ struct bus_type efi_bus = { .remove = efi_bus_remove, }; +static void efi_businfo(struct device_d *dev) +{ + int i; + + printf("Tables:\n"); + for (i = 0; i < efi_sys_table->nr_tables; i++) { + efi_config_table_t *t = &efi_sys_table->tables[i]; + + printf(" %d: %pUl: %s\n", i, &t->guid, + efi_guid_string(&t->guid)); + } +} + +static int efi_is_secure_boot(void) +{ + uint8_t *val; + int ret = 0; + + val = efi_get_variable("SecureBoot", &efi_global_variable_guid, NULL); + if (!IS_ERR(val)) { + ret = *val; + free(val); + } + + return ret != 1; +} + +static int efi_is_setup_mode(void) +{ + uint8_t *val; + int ret = 0; + + val = efi_get_variable("SetupMode", &efi_global_variable_guid, NULL); + if (!IS_ERR(val)) { + ret = *val; + free(val); + } + + return ret != 1; +} + static int efi_init_devices(void) { + char *fw_vendor = NULL; + u16 sys_major = efi_sys_table->hdr.revision >> 16; + u16 sys_minor = efi_sys_table->hdr.revision & 0xffff; + int secure_boot = efi_is_secure_boot(); + int setup_mode = efi_is_setup_mode(); + + fw_vendor = strdup_wchar_to_char((const wchar_t *)efi_sys_table->fw_vendor); + + pr_info("EFI v%u.%.02u by %s v%u\n", + sys_major, sys_minor, + fw_vendor, efi_sys_table->fw_revision); + bus_register(&efi_bus); + dev_add_param_fixed(efi_bus.dev, "fw_vendor", fw_vendor); + free(fw_vendor); + + dev_add_param_int_ro(efi_bus.dev, "major", sys_major, "%u"); + dev_add_param_int_ro(efi_bus.dev, "minor", sys_minor, "%u"); + dev_add_param_int_ro(efi_bus.dev, "fw_revision", efi_sys_table->fw_revision, "%u"); + dev_add_param_int_ro(efi_bus.dev, "secure_boot", secure_boot, "%d"); + dev_add_param_int_ro(efi_bus.dev, "secure_mode", + secure_boot & setup_mode, "%u"); + + efi_bus.dev->info = efi_businfo; + efi_register_devices(); return 0; } core_initcall(efi_init_devices); + +static void efi_devpath(efi_handle_t handle) +{ + efi_status_t efiret; + void *devpath; + char *dev_path_str; + + efiret = BS->open_protocol(handle, &efi_device_path_protocol_guid, + &devpath, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(efiret)) + return; + + dev_path_str = device_path_to_str(devpath); + if (dev_path_str) { + printf(" Devpath: \n %s\n", dev_path_str); + free(dev_path_str); + } +} + +static void efi_dump(efi_handle_t *handles, unsigned long handle_count) +{ + int i, j; + unsigned long num_guids; + efi_guid_t **guids; + + if (!handles || !handle_count) + return; + + for (i = 0; i < handle_count; i++) { + printf("handle-%p\n", handles[i]); + + BS->protocols_per_handle(handles[i], &guids, &num_guids); + printf(" Protocols:\n"); + for (j = 0; j < num_guids; j++) + printf(" %d: %pUl: %s\n", j, guids[j], + efi_guid_string(guids[j])); + efi_devpath(handles[i]); + } + printf("\n"); +} + +static unsigned char to_digit(unsigned char c) +{ + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else + c -= 'a' - 10; + + return c; +} + +#define read_xbit(src, dest, bit) \ + do { \ + int __i; \ + for (__i = (bit - 4); __i >= 0; __i -= 4, src++) \ + dest |= to_digit(*src) << __i; \ + } while (0) + +static int do_efi_protocol_dump(int argc, char **argv) +{ + unsigned long handle_count = 0; + efi_handle_t *handles = NULL; + int ret; + efi_guid_t guid; + u32 a = 0; + u16 b = 0; + u16 c = 0; + u8 d0 = 0; + u8 d1 = 0; + u8 d2 = 0; + u8 d3 = 0; + u8 d4 = 0; + u8 d5 = 0; + u8 d6 = 0; + u8 d7 = 0; + + /* Format 220e73b6-6bdb-4413-8405-b974b108619a */ + if (argc == 1) { + char *s = argv[0]; + int len = strlen(s); + + if (len != 36) + return -EINVAL; + + read_xbit(s, a, 32); + if (*s != '-') + return -EINVAL; + s++; + read_xbit(s, b, 16); + if (*s != '-') + return -EINVAL; + s++; + read_xbit(s, c, 16); + if (*s != '-') + return -EINVAL; + s++; + read_xbit(s, d0, 8); + read_xbit(s, d1, 8); + if (*s != '-') + return -EINVAL; + s++; + read_xbit(s, d2, 8); + read_xbit(s, d3, 8); + read_xbit(s, d4, 8); + read_xbit(s, d5, 8); + read_xbit(s, d6, 8); + read_xbit(s, d7, 8); + } else if (argc == 11) { + /* Format : + * 220e73b6 6bdb 4413 84 05 b9 74 b1 08 61 9a + * or + * 0x220e73b6 0x6bdb 0x14413 0x84 0x05 0xb9 0x74 0xb1 0x08 0x61 0x9a + */ + a = simple_strtoul(argv[0], NULL, 16); + b = simple_strtoul(argv[1], NULL, 16); + c = simple_strtoul(argv[2], NULL, 16); + d0 = simple_strtoul(argv[3], NULL, 16); + d1 = simple_strtoul(argv[4], NULL, 16); + d2 = simple_strtoul(argv[5], NULL, 16); + d3 = simple_strtoul(argv[6], NULL, 16); + d4 = simple_strtoul(argv[7], NULL, 16); + d5 = simple_strtoul(argv[8], NULL, 16); + d6 = simple_strtoul(argv[9], NULL, 16); + d7 = simple_strtoul(argv[10], NULL, 16); + } else { + return -EINVAL; + } + + guid = EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7); + + printf("Searching for:\n"); + printf(" %pUl: %s\n", &guid, efi_guid_string(&guid)); + + ret = efi_locate_handle(by_protocol, &guid, NULL, &handle_count, &handles); + if (!ret) + efi_dump(handles, handle_count); + + return 0; +} + +static int do_efi_handle_dump(int argc, char *argv[]) +{ + unsigned long handle_count = 0; + efi_handle_t *handles = NULL; + int ret; + + if (argc > 1) + return do_efi_protocol_dump(--argc, ++argv); + + ret = efi_locate_handle(all_handles, NULL, NULL, &handle_count, &handles); + if (!ret) + efi_dump(handles, handle_count); + + return 0; +} + +BAREBOX_CMD_HELP_START(efi_handle_dump) +BAREBOX_CMD_HELP_TEXT("Dump all the efi handle with protocol and devpath\n") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(efi_handle_dump) + .cmd = do_efi_handle_dump, + BAREBOX_CMD_DESC("Usage: efi_handle_dump") + BAREBOX_CMD_OPTS("[a-b-c-d0d1-d3d4d5d6d7] or [a b c d0 d1 d2 d3 d4 d5 d6 d7]") + BAREBOX_CMD_GROUP(CMD_GRP_MISC) + BAREBOX_CMD_HELP(cmd_efi_handle_dump_help) +BAREBOX_CMD_END diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index b723a127f2..c3980e78f5 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -202,7 +202,7 @@ config DRIVER_NET_TAP config DRIVER_NET_EFI_SNP bool "EFI SNP ethernet driver" - depends on ARCH_EFI + depends on EFI_BOOTUP config DRIVER_NET_TSE depends on NIOS2 diff --git a/drivers/net/efi-snp.c b/drivers/net/efi-snp.c index 963d539db3..23edc9f04f 100644 --- a/drivers/net/efi-snp.c +++ b/drivers/net/efi-snp.c @@ -23,8 +23,8 @@ #include <net.h> #include <init.h> #include <efi.h> -#include <mach/efi.h> -#include <mach/efi-device.h> +#include <efi/efi.h> +#include <efi/efi-device.h> struct efi_network_statistics { uint64_t RxTotalFrames; diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index d0a62bda91..a1fac0e613 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -4,7 +4,7 @@ config OFTREE config OFTREE_MEM_GENERIC depends on OFTREE - depends on PPC || ARM || ARCH_EFI || OPENRISC || SANDBOX + depends on PPC || ARM || EFI_BOOTUP || OPENRISC || SANDBOX def_bool y config DTC diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 4eab437ea5..cfddc2ee96 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -21,6 +21,10 @@ config DRIVER_SERIAL_AR933X If you have an Atheros AR933X SOC based board and want to use the built-in UART of the SoC, say Y to this option. +config DRIVER_SERIAL_EFI + bool "EFI serial" + depends on EFI_BOOTUP + config DRIVER_SERIAL_IMX depends on ARCH_IMX default y @@ -46,7 +50,7 @@ config DRIVER_SERIAL_LINUX_CONSOLE bool "linux console driver" config DRIVER_SERIAL_EFI_STDIO - depends on ARCH_EFI + depends on EFI_BOOTUP bool "EFI stdio driver" config DRIVER_SERIAL_MPC5XXX diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 7d1bae195f..3d9f735ed2 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_DRIVER_SERIAL_ARM_DCC) += arm_dcc.o obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o obj-$(CONFIG_DRIVER_SERIAL_AR933X) += serial_ar933x.o +obj-$(CONFIG_DRIVER_SERIAL_EFI) += serial_efi.o obj-$(CONFIG_DRIVER_SERIAL_IMX) += serial_imx.o obj-$(CONFIG_DRIVER_SERIAL_STM378X) += stm-serial.o obj-$(CONFIG_DRIVER_SERIAL_ATMEL) += atmel.o diff --git a/drivers/serial/efi-stdio.c b/drivers/serial/efi-stdio.c index 5ab917386e..0703f727e7 100644 --- a/drivers/serial/efi-stdio.c +++ b/drivers/serial/efi-stdio.c @@ -25,7 +25,7 @@ #include <efi.h> #include <readkey.h> #include <linux/ctype.h> -#include <mach/efi.h> +#include <efi/efi.h> #define EFI_SHIFT_STATE_VALID 0x80000000 #define EFI_RIGHT_CONTROL_PRESSED 0x00000004 diff --git a/drivers/serial/serial_efi.c b/drivers/serial/serial_efi.c new file mode 100644 index 0000000000..f0a2b22c2b --- /dev/null +++ b/drivers/serial/serial_efi.c @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2017 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * + * Under GPLv2 Only + */ + +#include <common.h> +#include <driver.h> +#include <init.h> +#include <malloc.h> +#include <efi.h> +#include <efi/efi.h> +#include <efi/efi-device.h> + +/* + * define for Control bits, grouped by read only, write only, and read write + * + * Read Only + */ +#define EFI_SERIAL_CLEAR_TO_SEND 0x00000010 +#define EFI_SERIAL_DATA_SET_READY 0x00000020 +#define EFI_SERIAL_RING_INDICATE 0x00000040 +#define EFI_SERIAL_CARRIER_DETECT 0x00000080 +#define EFI_SERIAL_INPUT_BUFFER_EMPTY 0x00000100 +#define EFI_SERIAL_OUTPUT_BUFFER_EMPTY 0x00000200 + +/* + * Write Only + */ +#define EFI_SERIAL_REQUEST_TO_SEND 0x00000002 +#define EFI_SERIAL_DATA_TERMINAL_READY 0x00000001 + +/* + * Read Write + */ +#define EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE 0x00001000 +#define EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE 0x00002000 +#define EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE 0x00004000 + +typedef enum { + DefaultParity, + NoParity, + EvenParity, + OddParity, + MarkParity, + SpaceParity +} efi_parity_type; + +typedef enum { + DefaultStopBits, + OneStopBit, + OneFiveStopBits, + TwoStopBits +} efi_stop_bits_type; + +struct efi_serial_io_mode { + uint32_t controlmask; + uint32_t timeout; + uint64_t baudrate; + uint32_t receivefifodepth; + uint32_t databits; + uint32_t parity; + uint32_t stopbits; +}; + +struct efi_serial_io_protocol { + uint32_t revision; + + efi_status_t (EFIAPI *reset) (struct efi_serial_io_protocol *This); + efi_status_t (EFIAPI *set_attributes) (struct efi_serial_io_protocol *This, + uint64_t baudrate, uint32_t receivefifodepth, + uint32_t timeout, efi_parity_type parity, + uint8_t databits, efi_stop_bits_type stopbits); + efi_status_t (EFIAPI *setcontrol) (struct efi_serial_io_protocol *This, + uint32_t control); + efi_status_t (EFIAPI *getcontrol) (struct efi_serial_io_protocol *This, + uint32_t *control); + efi_status_t (EFIAPI *write) (struct efi_serial_io_protocol *This, + unsigned long *buffersize, void *buffer); + efi_status_t (EFIAPI *read) (struct efi_serial_io_protocol *This, + unsigned long *buffersize, void *buffer); + + struct efi_serial_io_mode *mode; +}; + +/* + * We wrap our port structure around the generic console_device. + */ +struct efi_serial_port { + struct efi_serial_io_protocol *serial; + struct console_device uart; /* uart */ + struct efi_device *efidev; +}; + +static inline struct efi_serial_port * +to_efi_serial_port(struct console_device *uart) +{ + return container_of(uart, struct efi_serial_port, uart); +} + +static int efi_serial_setbaudrate(struct console_device *cdev, int baudrate) +{ + struct efi_serial_port *uart = to_efi_serial_port(cdev); + struct efi_serial_io_protocol *serial = uart->serial; + efi_status_t efiret; + + efiret = serial->set_attributes(serial, baudrate, 0, 0, NoParity, 8, + OneStopBit); + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + return 0; +} + +static void efi_serial_putc(struct console_device *cdev, char c) +{ + struct efi_serial_port *uart = to_efi_serial_port(cdev); + struct efi_serial_io_protocol *serial = uart->serial; + uint32_t control; + efi_status_t efiret; + unsigned long buffersize = sizeof(char); + + do { + efiret = serial->getcontrol(serial, &control); + if (EFI_ERROR(efiret)) + return; + + } while(!(control & EFI_SERIAL_CLEAR_TO_SEND)); + + serial->write(serial, &buffersize, &c); +} + +static int efi_serial_puts(struct console_device *cdev, const char *s) +{ + struct efi_serial_port *uart = to_efi_serial_port(cdev); + struct efi_serial_io_protocol *serial = uart->serial; + uint32_t control; + efi_status_t efiret; + unsigned long buffersize = strlen(s) * sizeof(char); + + do { + efiret = serial->getcontrol(serial, &control); + if (EFI_ERROR(efiret)) + return 0; + + } while(!(control & EFI_SERIAL_CLEAR_TO_SEND)); + + serial->write(serial, &buffersize, (void*)s); + + return strlen(s); +} + +static int efi_serial_getc(struct console_device *cdev) +{ + struct efi_serial_port *uart = to_efi_serial_port(cdev); + struct efi_serial_io_protocol *serial = uart->serial; + uint32_t control; + efi_status_t efiret; + unsigned long buffersize = sizeof(char); + char c; + + do { + efiret = serial->getcontrol(serial, &control); + if (EFI_ERROR(efiret)) + return (int)-1; + + } while(!(control & EFI_SERIAL_DATA_SET_READY)); + + serial->read(serial, &buffersize, &c); + + return (int)c; +} + +static int efi_serial_tstc(struct console_device *cdev) +{ + struct efi_serial_port *uart = to_efi_serial_port(cdev); + struct efi_serial_io_protocol *serial = uart->serial; + uint32_t control; + efi_status_t efiret; + + efiret = serial->getcontrol(serial, &control); + if (EFI_ERROR(efiret)) + return 0; + + return !(control & EFI_SERIAL_INPUT_BUFFER_EMPTY); +} + +static int efi_serial_probe(struct efi_device *efidev) +{ + struct efi_serial_port *uart; + struct console_device *cdev; + + uart = xzalloc(sizeof(struct efi_serial_port)); + + cdev = &uart->uart; + cdev->dev = &efidev->dev; + cdev->tstc = efi_serial_tstc; + cdev->putc = efi_serial_putc; + cdev->puts = efi_serial_puts; + cdev->getc = efi_serial_getc; + cdev->setbrg = efi_serial_setbaudrate; + + uart->serial = efidev->protocol; + + uart->serial->reset(uart->serial); + + /* Enable UART */ + + console_register(cdev); + + return 0; +} + +static struct efi_driver efi_serial_driver = { + .driver = { + .name = "efi-serial", + }, + .probe = efi_serial_probe, + .guid = EFI_SERIAL_IO_PROTOCOL_GUID, +}; +device_efi_driver(efi_serial_driver); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 8f31f5af74..8d50db6f61 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -24,6 +24,10 @@ config DRIVER_VIDEO_ATMEL_HLCD bool "Atmel HLCDC framebuffer driver" depends on ARCH_AT91 +config DRIVER_VIDEO_EFI_GOP + bool "EFI Graphics Output Protocol (GOP)" + depends on EFI_BOOTUP + config DRIVER_VIDEO_IMX bool "i.MX framebuffer driver" depends on ARCH_IMX1 || ARCH_IMX21 || ARCH_IMX25 || ARCH_IMX27 diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 1bf2e1f3ca..97712182e2 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -21,3 +21,5 @@ obj-$(CONFIG_DRIVER_VIDEO_OMAP) += omap.o obj-$(CONFIG_DRIVER_VIDEO_BCM283X) += bcm2835.o obj-$(CONFIG_DRIVER_VIDEO_SIMPLEFB) += simplefb.o obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += imx-ipu-v3/ + +obj-$(CONFIG_DRIVER_VIDEO_EFI_GOP) += efi_gop.o diff --git a/drivers/video/efi_gop.c b/drivers/video/efi_gop.c new file mode 100644 index 0000000000..7c083e4fb3 --- /dev/null +++ b/drivers/video/efi_gop.c @@ -0,0 +1,267 @@ +/* + * Copyright 2011 Intel Corporation; author Matt Fleming + * Copyright (c) 2017 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * + * GPL v2 + */ + +#include <common.h> +#include <driver.h> +#include <init.h> +#include <malloc.h> +#include <fb.h> +#include <errno.h> +#include <gui/graphic_utils.h> +#include <efi.h> +#include <efi/efi.h> +#include <efi/efi-device.h> + +#define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 +#define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 +#define PIXEL_BIT_MASK 2 +#define PIXEL_BLT_ONLY 3 +#define PIXEL_FORMAT_MAX 4 + +struct efi_pixel_bitmask { + u32 red_mask; + u32 green_mask; + u32 blue_mask; + u32 reserved_mask; +}; + +struct efi_graphics_output_mode_info { + u32 version; + u32 horizontal_resolution; + u32 vertical_resolution; + int pixel_format; + struct efi_pixel_bitmask pixel_information; + u32 pixels_per_scan_line; +}; + +struct efi_graphics_output_protocol_mode { + uint32_t max_mode; + uint32_t mode; + struct efi_graphics_output_mode_info *info; + unsigned long size_of_info; + void *frame_buffer_base; + unsigned long frame_buffer_size; +}; + +struct efi_graphics_output_protocol { + efi_status_t (EFIAPI *query_mode) (struct efi_graphics_output_protocol *This, + uint32_t mode_number, unsigned long *size_of_info, + struct efi_graphics_output_mode_info **info); + efi_status_t (EFIAPI *set_mode) (struct efi_graphics_output_protocol *This, + uint32_t mode_number); + efi_status_t (EFIAPI *blt)(struct efi_graphics_output_protocol *This, + void *buffer, + unsigned long operation, + unsigned long sourcex, unsigned long sourcey, + unsigned long destinationx, unsigned long destinationy, + unsigned long width, unsigned long height, unsigned + long delta); + struct efi_graphics_output_protocol_mode *mode; +}; + +struct efi_gop_priv { + struct device_d *dev; + struct fb_info fb; + + uint32_t mode; + struct efi_graphics_output_protocol *gop; +}; + +static void find_bits(unsigned long mask, u32 *pos, u32 *size) +{ + u8 first, len; + + first = 0; + len = 0; + + if (mask) { + while (!(mask & 0x1)) { + mask = mask >> 1; + first++; + } + + while (mask & 0x1) { + mask = mask >> 1; + len++; + } + } + + *pos = first; + *size = len; +} + +static void setup_pixel_info(struct fb_info *fb, u32 pixels_per_scan_line, + struct efi_pixel_bitmask pixel_info, int pixel_format) +{ + if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { + fb->bits_per_pixel = 32; + fb->line_length = pixels_per_scan_line * 4; + fb->red.length = 8; + fb->red.offset = 0; + fb->green.length = 8; + fb->green.offset = 8; + fb->blue.length = 8; + fb->blue.offset = 16; + fb->transp.length = 8; + fb->transp.offset = 24; + } else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) { + fb->bits_per_pixel = 32; + fb->line_length = pixels_per_scan_line * 4; + fb->red.length = 8; + fb->red.offset = 16; + fb->green.length = 8; + fb->green.offset = 8; + fb->blue.length = 8; + fb->blue.offset = 0; + fb->transp.length = 8; + fb->transp.offset = 24; + } else if (pixel_format == PIXEL_BIT_MASK) { + find_bits(pixel_info.red_mask, &fb->red.offset, &fb->red.length); + find_bits(pixel_info.green_mask, &fb->green.offset, + &fb->green.length); + find_bits(pixel_info.blue_mask, &fb->blue.offset, &fb->blue.length); + find_bits(pixel_info.reserved_mask, &fb->transp.offset, + &fb->transp.length); + fb->bits_per_pixel = fb->red.length + fb->green.length + + fb->blue.length + fb->transp.length; + fb->line_length = (pixels_per_scan_line * fb->bits_per_pixel) / 8; + } else { + fb->bits_per_pixel = 4; + fb->line_length = fb->xres / 2; + fb->red.length = 0; + fb->red.offset = 0; + fb->green.length = 0; + fb->green.offset = 0; + fb->blue.length = 0; + fb->blue.offset = 0; + fb->transp.length = 0; + fb->transp.offset = 0; + } +} + +static int efi_gop_query(struct efi_gop_priv *priv) +{ + struct efi_graphics_output_protocol_mode *mode; + struct efi_graphics_output_mode_info *info; + efi_status_t efiret; + unsigned long size = 0; + int i; + struct fb_videomode *vmode; + + mode = priv->gop->mode; + vmode = xzalloc(sizeof(*vmode) * mode->max_mode); + + priv->fb.modes.num_modes = mode->max_mode; + priv->fb.modes.modes = vmode; + + for (i = 0; i < mode->max_mode; i++, vmode++) { + efiret = priv->gop->query_mode(priv->gop, i, &size, &info); + if (EFI_ERROR(efiret)) + continue; + + vmode->name = basprintf("%d", i); + vmode->xres = info->horizontal_resolution; + vmode->yres = info->vertical_resolution; + } + + priv->fb.screen_base = mode->frame_buffer_base; + priv->mode = mode->mode; + priv->fb.xres = priv->fb.mode->xres; + priv->fb.yres = priv->fb.mode->yres; + + return 0; +} + +static int efi_gop_fb_activate_var(struct fb_info *fb_info) +{ + struct efi_gop_priv *priv = fb_info->priv; + struct efi_graphics_output_mode_info *info; + int num; + unsigned long size = 0; + efi_status_t efiret; + + num = simple_strtoul(fb_info->mode->name, NULL, 0); + + if (priv->mode != num) { + efiret = priv->gop->set_mode(priv->gop, num); + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + priv->mode = num; + } + + efiret = priv->gop->query_mode(priv->gop, num, &size, &info); + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + setup_pixel_info(&priv->fb, info->pixels_per_scan_line, + info->pixel_information, info->pixel_format); + + return 0; +} + +static struct fb_ops efi_gop_ops = { + .fb_activate_var = efi_gop_fb_activate_var, +}; + +static int efi_gop_probe(struct efi_device *efidev) +{ + struct efi_gop_priv *priv; + int ret = 0; + efi_status_t efiret; + efi_guid_t got_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + void *protocol; + + efiret = BS->handle_protocol(efidev->handle, &got_guid, &protocol); + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + priv = xzalloc(sizeof(struct efi_gop_priv)); + priv->gop = protocol; + priv->dev = &efidev->dev; + + if (!priv->gop) { + ret = -EINVAL; + goto err; + } + + ret = efi_gop_query(priv); + if (ret) + goto err; + + priv->fb.priv = priv; + priv->fb.dev.parent = priv->dev; + priv->fb.fbops = &efi_gop_ops; + priv->fb.p_enable = 1; + priv->fb.current_mode = priv->mode; + + ret = register_framebuffer(&priv->fb); + if (!ret) { + priv->dev->priv = &priv->fb; + return 0; + } + + if (priv->fb.modes.modes) { + int i; + + for (i = 0; i < priv->fb.modes.num_modes; i++) + free((void*)priv->fb.modes.modes[i].name); + + free((void*)priv->fb.modes.modes); + } +err: + free(priv); + return ret; +} + +static struct efi_driver efi_gop_driver = { + .driver = { + .name = "efi-gop", + }, + .probe = efi_gop_probe, + .guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, +}; +device_efi_driver(efi_gop_driver); diff --git a/fs/Kconfig b/fs/Kconfig index c7c42acd76..57f2676f43 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -42,7 +42,7 @@ config FS_NFS prompt "nfs support" config FS_EFI - depends on ARCH_EFI + depends on EFI_BOOTUP bool prompt "EFI filesystem support" help @@ -50,7 +50,7 @@ config FS_EFI by the EFI Firmware via the EFI Simple File System Protocol. config FS_EFIVARFS - depends on ARCH_EFI + depends on EFI_BOOTUP bool prompt "EFI variable filesystem support (efivarfs)" help @@ -31,8 +31,8 @@ #include <wchar.h> #include <efi.h> #include <libfile.h> -#include <mach/efi.h> -#include <mach/efi-device.h> +#include <efi/efi.h> +#include <efi/efi-device.h> #include <linux/stddef.h> /* Open modes */ diff --git a/fs/efivarfs.c b/fs/efivarfs.c index 86cdcf0b59..bf7351e6db 100644 --- a/fs/efivarfs.c +++ b/fs/efivarfs.c @@ -31,8 +31,8 @@ #include <wchar.h> #include <linux/err.h> #include <linux/ctype.h> -#include <mach/efi.h> -#include <mach/efi-device.h> +#include <efi/efi.h> +#include <efi/efi-device.h> struct efivarfs_inode { s16 *name; diff --git a/include/clock.h b/include/clock.h index d65e404e86..5f2f53ab66 100644 --- a/include/clock.h +++ b/include/clock.h @@ -12,7 +12,8 @@ struct clocksource { uint64_t (*read)(void); uint64_t cycle_last; uint64_t mask; - + int priority; + int (*init)(struct clocksource*); }; static inline uint32_t cyc2ns(struct clocksource *cs, uint64_t cycles) diff --git a/include/efi.h b/include/efi.h index b2e965bae1..e1fc134ee7 100644 --- a/include/efi.h +++ b/include/efi.h @@ -14,7 +14,7 @@ #include <linux/string.h> #include <linux/types.h> -#ifdef CONFIG_ARCH_EFI +#ifdef CONFIG_EFI_BOOTUP #define EFIAPI __attribute__((ms_abi)) #else #define EFIAPI @@ -171,6 +171,12 @@ struct efi_open_protocol_information_entry { u32 open_count; }; +typedef enum { + EFI_TIMER_CANCEL = 0, + EFI_TIMER_PERIODIC = 1, + EFI_TIMER_RELATIVE = 2 +} efi_timer_delay_t; + /* * EFI Boot Services table */ @@ -185,12 +191,25 @@ typedef struct { unsigned long *, u32 *); efi_status_t (EFIAPI *allocate_pool)(int, unsigned long, void **); efi_status_t (EFIAPI *free_pool)(void *); - void *create_event; - void *set_timer; +#define EFI_EVT_TIMER 0x80000000 +#define EFI_EVT_RUNTIME 0x40000000 +#define EFI_EVT_NOTIFY_WAIT 0x00000100 +#define EFI_EVT_NOTIFY_SIGNAL 0x00000200 +#define EFI_EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201 +#define EFI_EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 + +#define EFI_TPL_APPLICATION 4 +#define EFI_TPL_CALLBACK 8 +#define EFI_TPL_NOTIFY 16 +#define EFI_TPL_HIGH_LEVEL 31 + efi_status_t(EFIAPI *create_event)(u32 type , unsigned long tpl, + void (*fn) (void *event, void *ctx), + void *ctx, void **event); + efi_status_t(EFIAPI *set_timer)(void *event, efi_timer_delay_t type, uint64_t time); efi_status_t(EFIAPI *wait_for_event)(unsigned long number_of_events, void *event, unsigned long *index); void *signal_event; - void *close_event; + efi_status_t(EFIAPI *close_event)(void *event); void *check_event; void *install_protocol_interface; void *reinstall_protocol_interface; @@ -469,6 +488,9 @@ extern efi_runtime_services_t *RT; #define EFI_VLANCONFIGDXE_INF_GUID \ EFI_GUID(0xe4f61863, 0xfe2c, 0x4b56, 0xa8, 0xf4, 0x08, 0x51, 0x9b, 0xc4, 0x39, 0xdf) +#define EFI_TIMESTAMP_PROTOCOL_GUID \ + EFI_GUID(0xafbfde41, 0x2e6e, 0x4262, 0xba, 0x65, 0x62, 0xb9, 0x23, 0x6e, 0x54, 0x95) + /* barebox specific GUIDs */ #define EFI_BAREBOX_VENDOR_GUID \ EFI_GUID(0x5b91f69c, 0x8b88, 0x4a2b, 0x92, 0x69, 0x5f, 0x1d, 0x80, 0x2b, 0x51, 0x75) @@ -477,6 +499,14 @@ extern efi_runtime_services_t *RT; #define EFI_SYSTEMD_VENDOR_GUID \ EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f) +/* for TPM 1.2 */ +#define EFI_TCG_PROTOCOL_GUID \ + EFI_GUID(0xf541796d, 0xa62e, 0x4954, 0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd) + +/* for TPM 2.0 */ +#define EFI_TCG2_PROTOCOL_GUID \ + EFI_GUID(0x607f766c, 0x7455, 0x42be, 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f) + extern efi_guid_t efi_file_info_id; extern efi_guid_t efi_simple_file_system_protocol_guid; extern efi_guid_t efi_device_path_protocol_guid; @@ -488,6 +518,11 @@ extern efi_guid_t efi_block_io_protocol_guid; extern efi_guid_t efi_barebox_vendor_guid; extern efi_guid_t efi_systemd_vendor_guid; +typedef struct { + efi_guid_t guid; + unsigned long table; +} efi_config_table_t; + #define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL) #define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30)) @@ -510,7 +545,7 @@ typedef struct { efi_runtime_services_t *runtime; efi_boot_services_t *boottime; unsigned long nr_tables; - unsigned long tables; + efi_config_table_t *tables; } efi_system_table_t; typedef struct { diff --git a/arch/efi/include/mach/debug_ll.h b/include/efi/debug_ll.h index 0fb2cb8c2a..4ca72de312 100644 --- a/arch/efi/include/mach/debug_ll.h +++ b/include/efi/debug_ll.h @@ -5,7 +5,7 @@ #define EFI_DEBUG_CLEAR_MEMORY 0 #include <efi.h> -#include <mach/efi.h> +#include <efi/efi.h> static inline void PUTC_LL(char c) { diff --git a/arch/efi/include/mach/efi-device.h b/include/efi/efi-device.h index fe074a44bb..8f5f1f3f13 100644 --- a/arch/efi/include/mach/efi-device.h +++ b/include/efi/efi-device.h @@ -1,5 +1,5 @@ -#ifndef __MACH_EFI_DEVICE_H -#define __MACH_EFI_DEVICE_H +#ifndef __EFI_EFI_DEVICE_H +#define __EFI_EFI_DEVICE_H struct efi_device { struct device_d dev; @@ -42,4 +42,4 @@ static inline int efi_driver_register(struct efi_driver *efidrv) int efi_connect_all(void); void efi_register_devices(void); -#endif /* __MACH_EFI_DEVICE_H */ +#endif /* __EFI_EFI_DEVICE_H */ diff --git a/arch/efi/include/mach/efi.h b/include/efi/efi.h index 2b25cf1868..648afb9ec5 100644 --- a/arch/efi/include/mach/efi.h +++ b/include/efi/efi.h @@ -12,8 +12,6 @@ extern efi_loaded_image_t *efi_loaded_image; int efi_errno(efi_status_t err); -int efi_clocksource_init(void); - void *efi_get_variable(char *name, efi_guid_t *vendor, int *var_size); static inline void *efi_get_global_var(char *name, int *var_size) |