mirror of
https://gitlab.com/qemu-project/ipxe.git
synced 2025-10-30 07:56:50 +08:00
Compare commits
89 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b0093571f8 | |||
| 6a7f560e60 | |||
| 5b43181436 | |||
| d2e1601cf4 | |||
| 95b8338f0d | |||
| 28184b7c22 | |||
| 3c214f0465 | |||
| ce2200d5fb | |||
| c4a8d90387 | |||
| 79d85e29aa | |||
| d27cd8196d | |||
| 03eea19c19 | |||
| 0bb0aea878 | |||
| f9beb20e99 | |||
| f93e6b712f | |||
| 22cc65535a | |||
| bd13697446 | |||
| 9fb28080d9 | |||
| 1e4c3789e9 | |||
| 0d04635ef0 | |||
| 1d1cf74a5e | |||
| aa368ba529 | |||
| 2c6a15d2a3 | |||
| 09e8a15408 | |||
| bf25e23d07 | |||
| 8f1c120119 | |||
| 54fcb7c29c | |||
| 9e1f7a3659 | |||
| e51e7bbad7 | |||
| 523788ccda | |||
| 96bb6ba441 | |||
| 33cb56cf1b | |||
| 60531ff6e2 | |||
| 04e60a278a | |||
| 471599dc77 | |||
| 7d71cf318a | |||
| 6625e49cea | |||
| 9f17d1116d | |||
| 2733c4763a | |||
| cff857461b | |||
| 6a004be0cc | |||
| cf9ad00afc | |||
| 76a286530a | |||
| 3c83843e11 | |||
| be8ecaf805 | |||
| 62a1d5c0f5 | |||
| 84cb774390 | |||
| bfa5262f0e | |||
| ef0a6f4792 | |||
| c6901792f0 | |||
| a2bed43939 | |||
| 7cc305f7b4 | |||
| dc16de3204 | |||
| 6c0335adf6 | |||
| 8450fa4a7b | |||
| 4e456d9928 | |||
| d405a0bd84 | |||
| 49c13e81bc | |||
| 8b645eea16 | |||
| 6f250be279 | |||
| b6304f2984 | |||
| aa85c2918a | |||
| 66a2ff442d | |||
| 3bcd0d3271 | |||
| 4bb521a8c4 | |||
| b9be454010 | |||
| e3d543437e | |||
| 137ca5d877 | |||
| 900379594a | |||
| 91944c6341 | |||
| dac41fc4ec | |||
| 5220bdc524 | |||
| 38f54fb413 | |||
| 5bf8b11527 | |||
| 2d180ce233 | |||
| 4bffe0f0d9 | |||
| c5426cdaa9 | |||
| e72670ad7b | |||
| 68734b9a4d | |||
| 2fef0c541e | |||
| 1cd0a248cc | |||
| 204d39222a | |||
| fcfb70bfb2 | |||
| c5e1f007ac | |||
| 9de6c45dd3 | |||
| 8f59911b20 | |||
| 2061d658b3 | |||
| 2ef5f5e05e | |||
| 475c0dfa8e |
64
.github/workflows/build.yml
vendored
64
.github/workflows/build.yml
vendored
@ -4,21 +4,53 @@ on: push
|
||||
|
||||
jobs:
|
||||
|
||||
cache:
|
||||
name: Cache
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Cache permissions
|
||||
run: |
|
||||
sudo chown $(id -un) /var/cache/apt/archives
|
||||
- name: Cache packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: /var/cache/apt/archives/*.deb
|
||||
key: apt-cache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
restore-keys: |
|
||||
apt-cache-
|
||||
- name: Download packages
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y -d -o Acquire::Retries=50 \
|
||||
mtools syslinux isolinux \
|
||||
libc6-dev-i386 valgrind \
|
||||
gcc-arm-none-eabi gcc-aarch64-linux-gnu
|
||||
|
||||
x86:
|
||||
name: x86
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
needs: cache
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Cache permissions
|
||||
run: |
|
||||
sudo chown $(id -un) /var/cache/apt/archives
|
||||
- name: Cache packages
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: /var/cache/apt/archives/*.deb
|
||||
key: apt-cache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt update
|
||||
sudo apt install -y -o Acquire::Retries=50 \
|
||||
mtools syslinux isolinux \
|
||||
libc6-dev-i386 libc6-dbg:i386 valgrind
|
||||
libc6-dev-i386 valgrind \
|
||||
libgcc-s1:i386 libc6-dbg:i386
|
||||
- name: Build (BIOS)
|
||||
run: |
|
||||
make -j 4 -C src
|
||||
@ -32,12 +64,21 @@ jobs:
|
||||
|
||||
arm32:
|
||||
name: ARM32
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
needs: cache
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Cache permissions
|
||||
run: |
|
||||
sudo chown $(id -un) /var/cache/apt/archives
|
||||
- name: Cache packages
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: /var/cache/apt/archives/*.deb
|
||||
key: apt-cache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt update
|
||||
@ -52,12 +93,21 @@ jobs:
|
||||
|
||||
arm64:
|
||||
name: ARM64
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
needs: cache
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Cache permissions
|
||||
run: |
|
||||
sudo chown $(id -un) /var/cache/apt/archives
|
||||
- name: Cache packages
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: /var/cache/apt/archives/*.deb
|
||||
key: apt-cache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt update
|
||||
|
||||
4
.github/workflows/coverity.yml
vendored
4
.github/workflows/coverity.yml
vendored
@ -8,10 +8,10 @@ on:
|
||||
jobs:
|
||||
submit:
|
||||
name: Submit
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Download Coverity Scan
|
||||
run: |
|
||||
curl --form token=${{ secrets.COVERITY_SCAN_TOKEN }} \
|
||||
|
||||
@ -369,7 +369,6 @@ endif
|
||||
# Include architecture-specific include path
|
||||
ifdef ARCH
|
||||
INCDIRS += arch/$(ARCH)/include
|
||||
INCDIRS += arch/$(ARCH)/include/$(PLATFORM)
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
@ -512,6 +511,10 @@ CFLAGS += -include include/compiler.h
|
||||
#
|
||||
CFLAGS += -DASM_TCHAR='$(ASM_TCHAR)' -DASM_TCHAR_OPS='$(ASM_TCHAR_OPS)'
|
||||
|
||||
# Inhibit the default -Dlinux
|
||||
#
|
||||
CFLAGS += -Ulinux
|
||||
|
||||
# CFLAGS for specific object types
|
||||
#
|
||||
CFLAGS_c +=
|
||||
|
||||
@ -8,6 +8,10 @@ SYMBOL_PREFIX = _ipxe__
|
||||
#
|
||||
CFLAGS += -UNVALGRIND
|
||||
|
||||
# The Linux linker script
|
||||
#
|
||||
LDSCRIPT = scripts/linux.lds
|
||||
|
||||
# Use a two-stage link
|
||||
#
|
||||
LDFLAGS += -r -d
|
||||
|
||||
6
src/arch/arm/Makefile.linux
Normal file
6
src/arch/arm/Makefile.linux
Normal file
@ -0,0 +1,6 @@
|
||||
# -*- makefile -*- : Force emacs to use Makefile mode
|
||||
|
||||
# Include generic Linux Makefile
|
||||
#
|
||||
MAKEDEPS += Makefile.linux
|
||||
include Makefile.linux
|
||||
@ -1,12 +0,0 @@
|
||||
#ifndef _BITS_ENTROPY_H
|
||||
#define _BITS_ENTROPY_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* ARM-specific entropy API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#endif /* _BITS_ENTROPY_H */
|
||||
@ -9,6 +9,9 @@
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
/** Page shift */
|
||||
#define PAGE_SHIFT 12
|
||||
|
||||
#include <ipxe/arm_io.h>
|
||||
|
||||
#endif /* _BITS_IO_H */
|
||||
|
||||
@ -20,9 +20,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
*
|
||||
*/
|
||||
|
||||
/** Page shift */
|
||||
#define PAGE_SHIFT 12
|
||||
|
||||
/*
|
||||
* Physical<->Bus address mappings
|
||||
*
|
||||
|
||||
@ -5,7 +5,7 @@ SRCDIRS += arch/arm32/libgcc
|
||||
|
||||
# ARM32-specific flags
|
||||
#
|
||||
CFLAGS += -mthumb -mcpu=cortex-a15 -mabi=aapcs -mfloat-abi=soft
|
||||
CFLAGS += -mthumb -mcpu=cortex-a15 -mabi=aapcs
|
||||
CFLAGS += -mword-relocations
|
||||
ASFLAGS += -mthumb -mcpu=cortex-a15
|
||||
|
||||
@ -13,6 +13,11 @@ ASFLAGS += -mthumb -mcpu=cortex-a15
|
||||
#
|
||||
CFLAGS += -fshort-wchar
|
||||
|
||||
# EFI requires that enums are always 32 bits, and nothing else
|
||||
# currently cares
|
||||
#
|
||||
CFLAGS += -fno-short-enums
|
||||
|
||||
# Include common ARM Makefile
|
||||
MAKEDEPS += arch/arm/Makefile
|
||||
include arch/arm/Makefile
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
# -*- makefile -*- : Force emacs to use Makefile mode
|
||||
|
||||
# UEFI requires that enums are always 32 bits
|
||||
# EFI uses the soft float ABI
|
||||
#
|
||||
CFLAGS += -fno-short-enums
|
||||
CFLAGS += -mfloat-abi=soft
|
||||
|
||||
# Specify EFI image builder
|
||||
#
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
|
||||
|
||||
.section ".note.GNU-stack", "", %progbits
|
||||
.text
|
||||
.arm
|
||||
|
||||
|
||||
@ -8,6 +8,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
/** Unprefixed constant operand modifier */
|
||||
#define ASM_NO_PREFIX "c"
|
||||
|
||||
#define __asmcall
|
||||
#define __libgcc
|
||||
|
||||
|
||||
20
src/arch/arm32/include/ipxe/efi/dhcparch.h
Normal file
20
src/arch/arm32/include/ipxe/efi/dhcparch.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef _IPXE_EFI_DHCPARCH_H
|
||||
#define _IPXE_EFI_DHCPARCH_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* DHCP client architecture definitions
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/dhcp.h>
|
||||
|
||||
/** DHCP client architecture */
|
||||
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_ARM32
|
||||
|
||||
/** DHCP client network device interface */
|
||||
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
|
||||
|
||||
#endif /* _IPXE_EFI_DHCPARCH_H */
|
||||
@ -1,5 +1,6 @@
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
|
||||
|
||||
.section ".note.GNU-stack", "", %progbits
|
||||
.text
|
||||
.thumb
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
|
||||
|
||||
.section ".note.GNU-stack", "", %progbits
|
||||
.text
|
||||
.arm
|
||||
|
||||
|
||||
10
src/arch/arm64/Makefile.linux
Normal file
10
src/arch/arm64/Makefile.linux
Normal file
@ -0,0 +1,10 @@
|
||||
# -*- makefile -*- : Force emacs to use Makefile mode
|
||||
|
||||
# Starting virtual address
|
||||
#
|
||||
LDFLAGS += -Ttext=0x400000
|
||||
|
||||
# Include generic Linux Makefile
|
||||
#
|
||||
MAKEDEPS += arch/arm/Makefile.linux
|
||||
include arch/arm/Makefile.linux
|
||||
@ -8,6 +8,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
/** Unprefixed constant operand modifier */
|
||||
#define ASM_NO_PREFIX "c"
|
||||
|
||||
#define __asmcall
|
||||
#define __libgcc
|
||||
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* You can also choose to distribute this program under the terms of
|
||||
* the Unmodified Binary Distribution Licence (as given in the file
|
||||
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||
*/
|
||||
|
||||
#ifndef _DHCP_ARCH_H
|
||||
#define _DHCP_ARCH_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Architecture-specific DHCP options
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/dhcp.h>
|
||||
|
||||
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_ARM64
|
||||
|
||||
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
|
||||
|
||||
#endif
|
||||
20
src/arch/arm64/include/ipxe/efi/dhcparch.h
Normal file
20
src/arch/arm64/include/ipxe/efi/dhcparch.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef _IPXE_EFI_DHCPARCH_H
|
||||
#define _IPXE_EFI_DHCPARCH_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* DHCP client architecture definitions
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/dhcp.h>
|
||||
|
||||
/** DHCP client architecture */
|
||||
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_ARM64
|
||||
|
||||
/** DHCP client network device interface */
|
||||
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
|
||||
|
||||
#endif /* _IPXE_EFI_DHCPARCH_H */
|
||||
@ -1,8 +1,8 @@
|
||||
# -*- makefile -*- : Force emacs to use Makefile mode
|
||||
|
||||
# Linker script
|
||||
# Starting virtual address
|
||||
#
|
||||
LDSCRIPT = arch/i386/scripts/linux.lds
|
||||
LDFLAGS += -Ttext=0x08048000
|
||||
|
||||
# Compiler flags for building host API wrapper
|
||||
#
|
||||
|
||||
@ -8,6 +8,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
/** Unprefixed constant operand modifier */
|
||||
#define ASM_NO_PREFIX "c"
|
||||
|
||||
/** Declare a function with standard calling conventions */
|
||||
#define __asmcall __attribute__ (( cdecl, regparm(0) ))
|
||||
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* You can also choose to distribute this program under the terms of
|
||||
* the Unmodified Binary Distribution Licence (as given in the file
|
||||
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||
*/
|
||||
|
||||
#ifndef _DHCP_ARCH_H
|
||||
#define _DHCP_ARCH_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Architecture-specific DHCP options
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/dhcp.h>
|
||||
|
||||
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_IA32
|
||||
|
||||
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
|
||||
|
||||
#endif
|
||||
20
src/arch/i386/include/ipxe/efi/dhcparch.h
Normal file
20
src/arch/i386/include/ipxe/efi/dhcparch.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef _IPXE_EFI_DHCPARCH_H
|
||||
#define _IPXE_EFI_DHCPARCH_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* DHCP client architecture definitions
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/dhcp.h>
|
||||
|
||||
/** DHCP client architecture */
|
||||
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_IA32
|
||||
|
||||
/** DHCP client network device interface */
|
||||
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
|
||||
|
||||
#endif /* _IPXE_EFI_DHCPARCH_H */
|
||||
26
src/arch/loong64/Makefile
Normal file
26
src/arch/loong64/Makefile
Normal file
@ -0,0 +1,26 @@
|
||||
# Assembler section type character
|
||||
#
|
||||
ASM_TCHAR := @
|
||||
ASM_TCHAR_OPS := @
|
||||
|
||||
# LoongArch64-specific flags
|
||||
#
|
||||
CFLAGS += -fstrength-reduce -fomit-frame-pointer
|
||||
CFLAGS += -falign-jumps=1 -falign-loops=1 -falign-functions=1
|
||||
|
||||
# Check if -mno-explicit-relocs is valid
|
||||
ifeq ($(CCTYPE),gcc)
|
||||
MNER_TEST = $(CC) -mno-explicit-relocs -x c -c /dev/null -o /dev/null >/dev/null 2>&1
|
||||
MNER_FLAGS := $(shell $(MNER_TEST) && $(ECHO) '-mno-explicit-relocs')
|
||||
WORKAROUND_CFLAGS += $(MNER_FLAGS)
|
||||
endif
|
||||
|
||||
# EFI requires -fshort-wchar, and nothing else currently uses wchar_t
|
||||
CFLAGS += -fshort-wchar
|
||||
|
||||
# LoongArch64-specific directories containing source files
|
||||
SRCDIRS += arch/loong64/core
|
||||
|
||||
# Include platform-specific Makefile
|
||||
MAKEDEPS += arch/loong64/Makefile.$(PLATFORM)
|
||||
include arch/loong64/Makefile.$(PLATFORM)
|
||||
10
src/arch/loong64/Makefile.linux
Normal file
10
src/arch/loong64/Makefile.linux
Normal file
@ -0,0 +1,10 @@
|
||||
# -*- makefile -*- : Force emacs to use Makefile mode
|
||||
|
||||
# Starting virtual address
|
||||
#
|
||||
LDFLAGS += -Ttext=0x120000000
|
||||
|
||||
# Include generic Linux Makefile
|
||||
#
|
||||
MAKEDEPS += Makefile.linux
|
||||
include Makefile.linux
|
||||
120
src/arch/loong64/core/loong64_bigint.c
Normal file
120
src/arch/loong64/core/loong64_bigint.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
* Copyright (c) 2023, Xiaotian Wu <wuxiaotian@loongson.cn>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* You can also choose to distribute this program under the terms of
|
||||
* the Unmodified Binary Distribution Licence (as given in the file
|
||||
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <ipxe/bigint.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Big integer support
|
||||
*/
|
||||
|
||||
/**
|
||||
* Multiply big integers
|
||||
*
|
||||
* @v multiplicand0 Element 0 of big integer to be multiplied
|
||||
* @v multiplier0 Element 0 of big integer to be multiplied
|
||||
* @v result0 Element 0 of big integer to hold result
|
||||
* @v size Number of elements
|
||||
*/
|
||||
void bigint_multiply_raw ( const uint64_t *multiplicand0,
|
||||
const uint64_t *multiplier0,
|
||||
uint64_t *result0, unsigned int size ) {
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand =
|
||||
( ( const void * ) multiplicand0 );
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier =
|
||||
( ( const void * ) multiplier0 );
|
||||
bigint_t ( size * 2 ) __attribute__ (( may_alias )) *result =
|
||||
( ( void * ) result0 );
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
uint64_t multiplicand_element;
|
||||
uint64_t multiplier_element;
|
||||
uint64_t *result_elements;
|
||||
uint64_t discard_low;
|
||||
uint64_t discard_high;
|
||||
uint64_t discard_temp_low;
|
||||
uint64_t discard_temp_high;
|
||||
|
||||
/* Zero result */
|
||||
memset ( result, 0, sizeof ( *result ) );
|
||||
|
||||
/* Multiply integers one element at a time */
|
||||
for ( i = 0 ; i < size ; i++ ) {
|
||||
multiplicand_element = multiplicand->element[i];
|
||||
for ( j = 0 ; j < size ; j++ ) {
|
||||
multiplier_element = multiplier->element[j];
|
||||
result_elements = &result->element[ i + j ];
|
||||
/* Perform a single multiply, and add the
|
||||
* resulting double-element into the result,
|
||||
* carrying as necessary. The carry can
|
||||
* never overflow beyond the end of the
|
||||
* result, since:
|
||||
*
|
||||
* a < 2^{n}, b < 2^{n} => ab < 2^{2n}
|
||||
*/
|
||||
__asm__ __volatile__ ( "mul.d %1, %6, %7\n\t"
|
||||
"mulh.du %2, %6, %7\n\t"
|
||||
|
||||
"ld.d %3, %0, 0\n\t"
|
||||
"ld.d %4, %0, 8\n\t"
|
||||
|
||||
"add.d %3, %3, %1\n\t"
|
||||
"sltu $t0, %3, %1\n\t"
|
||||
|
||||
"add.d %4, %4, %2\n\t"
|
||||
"sltu $t1, %4, %2\n\t"
|
||||
|
||||
"add.d %4, %4, $t0\n\t"
|
||||
"sltu $t0, %4, $t0\n\t"
|
||||
"or $t0, $t0, $t1\n\t"
|
||||
|
||||
"st.d %3, %0, 0\n\t"
|
||||
"st.d %4, %0, 8\n\t"
|
||||
|
||||
"addi.d %0, %0, 16\n\t"
|
||||
"beqz $t0, 2f\n"
|
||||
"1:\n\t"
|
||||
"ld.d %3, %0, 0\n\t"
|
||||
"add.d %3, %3, $t0\n\t"
|
||||
"sltu $t0, %3, $t0\n\t"
|
||||
"st.d %3, %0, 0\n\t"
|
||||
"addi.d %0, %0, 8\n\t"
|
||||
"bnez $t0, 1b\n"
|
||||
"2:"
|
||||
: "+r" ( result_elements ),
|
||||
"=&r" ( discard_low ),
|
||||
"=&r" ( discard_high ),
|
||||
"=r" ( discard_temp_low ),
|
||||
"=r" ( discard_temp_high ),
|
||||
"+m" ( *result )
|
||||
: "r" ( multiplicand_element ),
|
||||
"r" ( multiplier_element )
|
||||
: "t0", "t1" );
|
||||
}
|
||||
}
|
||||
}
|
||||
266
src/arch/loong64/core/loong64_string.c
Normal file
266
src/arch/loong64/core/loong64_string.c
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
* Copyright (c) 2023, Xiaotian Wu <wuxiaotian@loongson.cn>
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* You can also choose to distribute this program under the terms of
|
||||
* the Unmodified Binary Distribution Licence (as given in the file
|
||||
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Optimised string operations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Copy memory area
|
||||
*
|
||||
* @v dest Destination address
|
||||
* @v src Source address
|
||||
* @v len Length
|
||||
* @ret dest Destination address
|
||||
*/
|
||||
void loong64_memcpy ( void *dest, const void *src, size_t len ) {
|
||||
void *discard_dest;
|
||||
void *discard_end;
|
||||
const void *discard_src;
|
||||
size_t discard_offset;
|
||||
unsigned long discard_data;
|
||||
unsigned long discard_low;
|
||||
unsigned long discard_high;
|
||||
|
||||
/* If length is too short, then just copy individual bytes.
|
||||
*/
|
||||
if ( len < 16 ) {
|
||||
__asm__ __volatile__ ( "beqz %0, 2f\n\t"
|
||||
"\n1:\n\t"
|
||||
"addi.d %0, %0, -1\n\t"
|
||||
"ldx.b %1, %3, %0\n\t"
|
||||
"stx.b %1, %2, %0\n\t"
|
||||
"bnez %0, 1b\n\t"
|
||||
"\n2:\n\t"
|
||||
: "=&r" ( discard_offset ),
|
||||
"=&r" ( discard_data )
|
||||
: "r" ( dest ), "r" ( src ), "0" ( len )
|
||||
: "memory", "t0" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy 16 bytes at a time: one initial
|
||||
* potentially unaligned access, multiple destination-aligned
|
||||
* accesses, one final potentially unaligned access.
|
||||
*/
|
||||
__asm__ __volatile__ ( "ld.d %3, %1, 0\n\t"
|
||||
"ld.d %4, %1, 8\n\t"
|
||||
"addi.d %1, %1, 16\n\t"
|
||||
"st.d %3, %0, 0\n\t"
|
||||
"st.d %4, %0, 8\n\t"
|
||||
"addi.d %0, %0, 16\n\t"
|
||||
"andi %3, %0, 15\n\t"
|
||||
"sub.d %0, %0, %3\n\t"
|
||||
"sub.d %1, %1, %3\n\t"
|
||||
"addi.d $t0, $zero, 0xf\n\t"
|
||||
"andn %2, %5, $t0\n\t"
|
||||
"b 2f\n\t"
|
||||
"\n1:\n\t"
|
||||
"ld.d %3, %1, 0\n\t"
|
||||
"ld.d %4, %1, 8\n\t"
|
||||
"addi.d %1, %1, 16\n\t"
|
||||
"st.d %3, %0, 0\n\t"
|
||||
"st.d %4, %0, 8\n\t"
|
||||
"addi.d %0, %0, 16\n\t"
|
||||
"\n2:\n\t"
|
||||
"bne %0, %2, 1b\n\t"
|
||||
"ld.d %3, %6, -16\n\t"
|
||||
"ld.d %4, %6, -8\n\t"
|
||||
"st.d %3, %5, -16\n\t"
|
||||
"st.d %4, %5, -8\n\t"
|
||||
: "=&r" ( discard_dest ),
|
||||
"=&r" ( discard_src ),
|
||||
"=&r" ( discard_end ),
|
||||
"=&r" ( discard_low ),
|
||||
"=&r" ( discard_high )
|
||||
: "r" ( dest + len ), "r" ( src + len ),
|
||||
"0" ( dest ), "1" ( src )
|
||||
: "memory", "t0" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Zero memory region
|
||||
*
|
||||
* @v dest Destination region
|
||||
* @v len Length
|
||||
*/
|
||||
void loong64_bzero ( void *dest, size_t len ) {
|
||||
size_t discard_offset;
|
||||
void *discard_dest;
|
||||
void *discard_end;
|
||||
|
||||
/* If length is too short, then just zero individual bytes.
|
||||
*/
|
||||
if ( len < 16 ) {
|
||||
__asm__ __volatile__ ( "beqz %0, 2f\n\t"
|
||||
"\n1:\n\t"
|
||||
"addi.d %0, %0, -1\n\t"
|
||||
"stx.b $zero, %1, %0\n\t"
|
||||
"bnez %0, 1b\n\t"
|
||||
"\n2:\n\t"
|
||||
: "=&r" ( discard_offset )
|
||||
: "r" ( dest ), "0" ( len )
|
||||
: "memory" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* To zero 16 bytes at a time: one initial
|
||||
* potentially unaligned access, multiple aligned accesses,
|
||||
* one final potentially unaligned access.
|
||||
*/
|
||||
|
||||
__asm__ __volatile__ ( "st.d $zero, %0, 0\n\t"
|
||||
"st.d $zero, %0, 8\n\t"
|
||||
"addi.d %0, %0, 16\n\t"
|
||||
"addi.w $t0, $zero, 15\n\t"
|
||||
"andn %0, %0, $t0\n\t"
|
||||
"addi.w $t0, $zero, 15\n\t"
|
||||
"andn %1, %2, $t0\n\t"
|
||||
"b 2f\n\t"
|
||||
"\n1:\n\t"
|
||||
"st.d $zero, %0, 0\n\t"
|
||||
"st.d $zero, %0, 8\n\t"
|
||||
"addi.d %0, %0, 16\n\t"
|
||||
"\n2:\n\t"
|
||||
"bne %0, %1, 1b\n\t"
|
||||
"st.d $zero, %2, -16\n\t"
|
||||
"st.d $zero, %2, -8\n\t"
|
||||
: "=&r" ( discard_dest ),
|
||||
"=&r" ( discard_end )
|
||||
: "r" ( dest + len ), "0" ( dest )
|
||||
: "memory", "t0" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill memory region
|
||||
*
|
||||
* @v dest Destination region
|
||||
* @v len Length
|
||||
* @v character Fill character
|
||||
*
|
||||
* The unusual parameter order is to allow for more efficient
|
||||
* tail-calling to loong64_memset() when zeroing a region.
|
||||
*/
|
||||
void loong64_memset ( void *dest, size_t len, int character ) {
|
||||
size_t discard_offset;
|
||||
|
||||
/* Use optimised zeroing code if applicable */
|
||||
if ( character == 0 ) {
|
||||
loong64_bzero ( dest, len );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fill one byte at a time. Calling memset() with a non-zero
|
||||
* value is relatively rare and unlikely to be
|
||||
* performance-critical.
|
||||
*/
|
||||
__asm__ __volatile__ ( "beqz %0, 2f\n\t"
|
||||
"\n1:\n\t"
|
||||
"addi.d %0, %0, -1\n\t"
|
||||
"stx.b %2, %1, %0\n\t"
|
||||
"bnez %0, 1b\n\t"
|
||||
"\n2:\n\t"
|
||||
: "=&r" ( discard_offset )
|
||||
: "r" ( dest ), "r" ( character ), "0" ( len )
|
||||
: "memory" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy (possibly overlapping) memory region forwards
|
||||
*
|
||||
* @v dest Destination region
|
||||
* @v src Source region
|
||||
* @v len Length
|
||||
*/
|
||||
void loong64_memmove_forwards ( void *dest, const void *src, size_t len ) {
|
||||
void *discard_dest;
|
||||
const void *discard_src;
|
||||
unsigned long discard_data;
|
||||
|
||||
/* Assume memmove() is not performance-critical, and perform a
|
||||
* bytewise copy for simplicity.
|
||||
*/
|
||||
__asm__ __volatile__ ( "b 2f\n\t"
|
||||
"\n1:\n\t"
|
||||
"ld.b %2, %1, 0\n\t"
|
||||
"addi.d %1, %1, 1\n\t"
|
||||
"st.b %2, %0, 0\n\t"
|
||||
"addi.d %0, %0, 1\n\t"
|
||||
"\n2:\n\t"
|
||||
"bne %0, %3, 1b\n\t"
|
||||
: "=&r" ( discard_dest ),
|
||||
"=&r" ( discard_src ),
|
||||
"=&r" ( discard_data )
|
||||
: "r" ( dest + len ), "0" ( dest ), "1" ( src )
|
||||
: "memory" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy (possibly overlapping) memory region backwards
|
||||
*
|
||||
* @v dest Destination region
|
||||
* @v src Source region
|
||||
* @v len Length
|
||||
*/
|
||||
void loong64_memmove_backwards ( void *dest, const void *src, size_t len ) {
|
||||
size_t discard_offset;
|
||||
unsigned long discard_data;
|
||||
|
||||
/* Assume memmove() is not performance-critical, and perform a
|
||||
* bytewise copy for simplicity.
|
||||
*/
|
||||
__asm__ __volatile__ ( "beqz %0, 2f\n\t"
|
||||
"\n1:\n\t"
|
||||
"addi.d %0, %0, -1\n\t"
|
||||
"ldx.b %1, %3, %0\n\t"
|
||||
"stx.b %1, %2, %0\n\t"
|
||||
"bnez %0, 1b\n\t"
|
||||
"\n2:\n\t"
|
||||
: "=&r" ( discard_offset ),
|
||||
"=&r" ( discard_data )
|
||||
: "r" ( dest ), "r" ( src ), "0" ( len )
|
||||
: "memory" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy (possibly overlapping) memory region
|
||||
*
|
||||
* @v dest Destination region
|
||||
* @v src Source region
|
||||
* @v len Length
|
||||
*/
|
||||
void loong64_memmove ( void *dest, const void *src, size_t len ) {
|
||||
|
||||
if ( dest <= src ) {
|
||||
loong64_memmove_forwards ( dest, src, len );
|
||||
} else {
|
||||
loong64_memmove_backwards ( dest, src, len );
|
||||
}
|
||||
}
|
||||
53
src/arch/loong64/core/setjmp.S
Normal file
53
src/arch/loong64/core/setjmp.S
Normal file
@ -0,0 +1,53 @@
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
|
||||
|
||||
.section ".note.GNU-stack", "", %progbits
|
||||
.text
|
||||
/*
|
||||
int setjmp(jmp_buf env);
|
||||
*/
|
||||
.globl setjmp
|
||||
.type setjmp, %function
|
||||
setjmp:
|
||||
/* Store registers */
|
||||
st.d $s0, $a0, 0x0
|
||||
st.d $s1, $a0, 0x8
|
||||
st.d $s2, $a0, 0x10
|
||||
st.d $s3, $a0, 0x18
|
||||
st.d $s4, $a0, 0x20
|
||||
st.d $s5, $a0, 0x28
|
||||
st.d $s6, $a0, 0x30
|
||||
st.d $s7, $a0, 0x38
|
||||
st.d $s8, $a0, 0x40
|
||||
st.d $fp, $a0, 0x48
|
||||
st.d $sp, $a0, 0x50
|
||||
st.d $ra, $a0, 0x58
|
||||
|
||||
move $a0, $zero
|
||||
jirl $zero, $ra, 0
|
||||
.size setjmp, . - setjmp
|
||||
|
||||
/*
|
||||
void longjmp(jmp_buf env, int val);
|
||||
*/
|
||||
.globl longjmp
|
||||
.type longjmp, %function
|
||||
longjmp:
|
||||
/* Restore registers */
|
||||
ld.d $s0, $a0, 0x0
|
||||
ld.d $s1, $a0, 0x8
|
||||
ld.d $s2, $a0, 0x10
|
||||
ld.d $s3, $a0, 0x18
|
||||
ld.d $s4, $a0, 0x20
|
||||
ld.d $s5, $a0, 0x28
|
||||
ld.d $s6, $a0, 0x30
|
||||
ld.d $s7, $a0, 0x38
|
||||
ld.d $s8, $a0, 0x40
|
||||
ld.d $fp, $a0, 0x48
|
||||
ld.d $sp, $a0, 0x50
|
||||
ld.d $ra, $a0, 0x58
|
||||
addi.d $a0, $zero, 1 # a0 = 1
|
||||
beqz $a1, .exit # if (a1 == 0); goto L0
|
||||
move $a0, $a1 # a0 = a1
|
||||
.exit:
|
||||
jirl $zero, $ra, 0
|
||||
.size longjmp, . - longjmp
|
||||
12
src/arch/loong64/include/bits/acpi.h
Normal file
12
src/arch/loong64/include/bits/acpi.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _BITS_ACPI_H
|
||||
#define _BITS_ACPI_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* LoongArch64-specific ACPI API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#endif /* _BITS_ACPI_H */
|
||||
336
src/arch/loong64/include/bits/bigint.h
Normal file
336
src/arch/loong64/include/bits/bigint.h
Normal file
@ -0,0 +1,336 @@
|
||||
#ifndef _BITS_BIGINT_H
|
||||
#define _BITS_BIGINT_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Big integer support
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
/** Element of a big integer */
|
||||
typedef uint64_t bigint_element_t;
|
||||
|
||||
/**
|
||||
* Initialise big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer to initialise
|
||||
* @v size Number of elements
|
||||
* @v data Raw data
|
||||
* @v len Length of raw data
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_init_raw ( uint64_t *value0, unsigned int size,
|
||||
const void *data, size_t len ) {
|
||||
size_t pad_len = ( sizeof ( bigint_t ( size ) ) - len );
|
||||
uint8_t *value_byte = ( ( void * ) value0 );
|
||||
const uint8_t *data_byte = ( data + len );
|
||||
|
||||
/* Copy raw data in reverse order, padding with zeros */
|
||||
while ( len-- )
|
||||
*(value_byte++) = *(--data_byte);
|
||||
while ( pad_len-- )
|
||||
*(value_byte++) = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add big integers
|
||||
*
|
||||
* @v addend0 Element 0 of big integer to add
|
||||
* @v value0 Element 0 of big integer to be added to
|
||||
* @v size Number of elements
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
|
||||
unsigned int size ) {
|
||||
bigint_t ( size ) __attribute__ (( may_alias )) *value =
|
||||
( ( void * ) value0 );
|
||||
uint64_t *discard_addend;
|
||||
uint64_t *discard_value;
|
||||
uint64_t discard_addend_i;
|
||||
uint64_t discard_value_i;
|
||||
unsigned int discard_size;
|
||||
__asm__ __volatile__ ( "move $t0, $zero\n"
|
||||
"1:\n\t"
|
||||
"ld.d %3, %0, 0\n\t"
|
||||
"addi.d %0, %0, 8\n\t"
|
||||
"ld.d %4, %1, 0\n\t"
|
||||
|
||||
"add.d %4, %4, $t0\n\t"
|
||||
"sltu $t0, %4, $t0\n\t"
|
||||
|
||||
"add.d %4, %4, %3\n\t"
|
||||
"sltu $t1, %4, %3\n\t"
|
||||
|
||||
"or $t0, $t0, $t1\n\t"
|
||||
"st.d %4, %1, 0\n\t"
|
||||
"addi.d %1, %1, 8\n\t"
|
||||
"addi.w %2, %2, -1\n\t"
|
||||
"bnez %2, 1b"
|
||||
: "=r" ( discard_addend ),
|
||||
"=r" ( discard_value ),
|
||||
"=r" ( discard_size ),
|
||||
"=r" ( discard_addend_i ),
|
||||
"=r" ( discard_value_i ),
|
||||
"+m" ( *value )
|
||||
: "0" ( addend0 ),
|
||||
"1" ( value0 ),
|
||||
"2" ( size )
|
||||
: "t0", "t1" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract big integers
|
||||
*
|
||||
* @v subtrahend0 Element 0 of big integer to subtract
|
||||
* @v value0 Element 0 of big integer to be subtracted from
|
||||
* @v size Number of elements
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
|
||||
unsigned int size ) {
|
||||
uint64_t *discard_subtrahend;
|
||||
uint64_t *discard_value;
|
||||
uint64_t discard_subtrahend_i;
|
||||
uint64_t discard_value_i;
|
||||
unsigned int discard_size;
|
||||
unsigned int flag = 0;
|
||||
|
||||
discard_subtrahend = (uint64_t*) subtrahend0;
|
||||
discard_value = value0;
|
||||
discard_size = size;
|
||||
|
||||
do {
|
||||
discard_subtrahend_i = *discard_subtrahend;
|
||||
discard_subtrahend++;
|
||||
discard_value_i = *discard_value;
|
||||
|
||||
discard_value_i = discard_value_i - discard_subtrahend_i - flag;
|
||||
|
||||
if ( *discard_value < (discard_subtrahend_i + flag)) {
|
||||
flag = 1;
|
||||
} else {
|
||||
flag = 0;
|
||||
}
|
||||
|
||||
*discard_value = discard_value_i;
|
||||
|
||||
discard_value++;
|
||||
discard_size -= 1;
|
||||
} while (discard_size != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate big integer left
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_rol_raw ( uint64_t *value0, unsigned int size ) {
|
||||
uint64_t *discard_value;
|
||||
uint64_t discard_value_i;
|
||||
unsigned int discard_size;
|
||||
uint64_t current_value_i;
|
||||
unsigned int flag = 0;
|
||||
|
||||
discard_value = value0;
|
||||
discard_size = size;
|
||||
do {
|
||||
discard_value_i = *discard_value;
|
||||
current_value_i = discard_value_i;
|
||||
|
||||
discard_value_i += discard_value_i + flag;
|
||||
|
||||
if (discard_value_i < current_value_i) {
|
||||
flag = 1;
|
||||
} else {
|
||||
flag = 0;
|
||||
}
|
||||
|
||||
*discard_value = discard_value_i;
|
||||
discard_value++;
|
||||
discard_size -= 1;
|
||||
} while ( discard_size != 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate big integer right
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_ror_raw ( uint64_t *value0, unsigned int size ) {
|
||||
uint64_t *discard_value;
|
||||
uint64_t discard_value_i;
|
||||
uint64_t discard_value_j;
|
||||
unsigned int discard_size;
|
||||
|
||||
discard_value = value0;
|
||||
discard_size = size;
|
||||
|
||||
discard_value_j = 0;
|
||||
|
||||
do {
|
||||
discard_size -= 1;
|
||||
|
||||
discard_value_i = *(discard_value + discard_size);
|
||||
|
||||
discard_value_j = (discard_value_j << 63) | (discard_value_i >> 1);
|
||||
|
||||
*(discard_value + discard_size) = discard_value_j;
|
||||
|
||||
discard_value_j = discard_value_i;
|
||||
} while ( discard_size > 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if big integer is equal to zero
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @ret is_zero Big integer is equal to zero
|
||||
*/
|
||||
static inline __attribute__ (( always_inline, pure )) int
|
||||
bigint_is_zero_raw ( const uint64_t *value0, unsigned int size ) {
|
||||
const uint64_t *value = value0;
|
||||
uint64_t value_i;
|
||||
|
||||
do {
|
||||
value_i = *(value++);
|
||||
if ( value_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return ( value_i == 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare big integers
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v reference0 Element 0 of reference big integer
|
||||
* @v size Number of elements
|
||||
* @ret geq Big integer is greater than or equal to the reference
|
||||
*/
|
||||
static inline __attribute__ (( always_inline, pure )) int
|
||||
bigint_is_geq_raw ( const uint64_t *value0, const uint64_t *reference0,
|
||||
unsigned int size ) {
|
||||
const uint64_t *value = ( value0 + size );
|
||||
const uint64_t *reference = ( reference0 + size );
|
||||
uint64_t value_i;
|
||||
uint64_t reference_i;
|
||||
|
||||
do {
|
||||
value_i = *(--value);
|
||||
reference_i = *(--reference);
|
||||
if ( value_i != reference_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return ( value_i >= reference_i );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if bit is set in big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @v bit Bit to test
|
||||
* @ret is_set Bit is set
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
bigint_bit_is_set_raw ( const uint64_t *value0, unsigned int size,
|
||||
unsigned int bit ) {
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *value =
|
||||
( ( const void * ) value0 );
|
||||
unsigned int index = ( bit / ( 8 * sizeof ( value->element[0] ) ) );
|
||||
unsigned int subindex = ( bit % ( 8 * sizeof ( value->element[0] ) ) );
|
||||
|
||||
return ( !! ( value->element[index] & ( 1UL << subindex ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find highest bit set in big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @ret max_bit Highest bit set + 1 (or 0 if no bits set)
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
bigint_max_set_bit_raw ( const uint64_t *value0, unsigned int size ) {
|
||||
const uint64_t *value = ( value0 + size );
|
||||
int max_bit = ( 8 * sizeof ( bigint_t ( size ) ) );
|
||||
uint64_t value_i;
|
||||
|
||||
do {
|
||||
value_i = *(--value);
|
||||
max_bit -= ( 64 - fls ( value_i ) );
|
||||
if ( value_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return max_bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow big integer
|
||||
*
|
||||
* @v source0 Element 0 of source big integer
|
||||
* @v source_size Number of elements in source big integer
|
||||
* @v dest0 Element 0 of destination big integer
|
||||
* @v dest_size Number of elements in destination big integer
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_grow_raw ( const uint64_t *source0, unsigned int source_size,
|
||||
uint64_t *dest0, unsigned int dest_size ) {
|
||||
unsigned int pad_size = ( dest_size - source_size );
|
||||
|
||||
memcpy ( dest0, source0, sizeof ( bigint_t ( source_size ) ) );
|
||||
memset ( ( dest0 + source_size ), 0, sizeof ( bigint_t ( pad_size ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Shrink big integer
|
||||
*
|
||||
* @v source0 Element 0 of source big integer
|
||||
* @v source_size Number of elements in source big integer
|
||||
* @v dest0 Element 0 of destination big integer
|
||||
* @v dest_size Number of elements in destination big integer
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_shrink_raw ( const uint64_t *source0, unsigned int source_size __unused,
|
||||
uint64_t *dest0, unsigned int dest_size ) {
|
||||
|
||||
memcpy ( dest0, source0, sizeof ( bigint_t ( dest_size ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalise big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer to finalise
|
||||
* @v size Number of elements
|
||||
* @v out Output buffer
|
||||
* @v len Length of output buffer
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_done_raw ( const uint64_t *value0, unsigned int size __unused,
|
||||
void *out, size_t len ) {
|
||||
const uint8_t *value_byte = ( ( const void * ) value0 );
|
||||
uint8_t *out_byte = ( out + len );
|
||||
|
||||
/* Copy raw data in reverse order */
|
||||
while ( len-- )
|
||||
*(--out_byte) = *(value_byte++);
|
||||
}
|
||||
|
||||
extern void bigint_multiply_raw ( const uint64_t *multiplicand0,
|
||||
const uint64_t *multiplier0,
|
||||
uint64_t *value0, unsigned int size );
|
||||
|
||||
#endif /* _BITS_BIGINT_H */
|
||||
102
src/arch/loong64/include/bits/bitops.h
Normal file
102
src/arch/loong64/include/bits/bitops.h
Normal file
@ -0,0 +1,102 @@
|
||||
#ifndef _BITS_BITOPS_H
|
||||
#define _BITS_BITOPS_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* loongArch bit operations
|
||||
*
|
||||
* We perform atomic bit set and bit clear operations using "ll"
|
||||
* and "sc". We use the output constraint to inform the
|
||||
* compiler that any memory from the start of the bit field up to and
|
||||
* including the byte containing the bit may be modified. (This is
|
||||
* overkill but shouldn't matter in practice since we're unlikely to
|
||||
* subsequently read other bits from the same bit field.)
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Test and set bit atomically
|
||||
*
|
||||
* @v bit Bit to set
|
||||
* @v bits Bit field
|
||||
* @ret old Old value of bit (zero or non-zero)
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
test_and_set_bit ( unsigned int bit, volatile void *bits ) {
|
||||
unsigned int index = ( bit / 64 );
|
||||
unsigned int offset = ( bit % 64 );
|
||||
volatile uint64_t *qword = ( ( ( volatile uint64_t * ) bits ) + index );
|
||||
uint64_t mask = ( 1UL << offset );
|
||||
uint64_t old;
|
||||
uint64_t new;
|
||||
|
||||
__asm__ __volatile__ ( "1: \n\t"
|
||||
"ll.d %[old], %[qword] \n\t"
|
||||
"or %[new], %[old], %[mask] \n\t"
|
||||
"sc.d %[new], %[qword] \n\t"
|
||||
"beqz %[new], 1b \n\t"
|
||||
: [old] "=&r" ( old ),
|
||||
[new] "=&r" ( new ),
|
||||
[qword] "+m" ( *qword )
|
||||
: [mask] "r" ( mask )
|
||||
: "cc", "memory");
|
||||
return ( !! ( old & mask ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test and clear bit atomically
|
||||
*
|
||||
* @v bit Bit to set
|
||||
* @v bits Bit field
|
||||
* @ret old Old value of bit (zero or non-zero)
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
test_and_clear_bit ( unsigned int bit, volatile void *bits ) {
|
||||
unsigned int index = ( bit / 64 );
|
||||
unsigned int offset = ( bit % 64 );
|
||||
volatile uint64_t *qword = ( ( ( volatile uint64_t * ) bits ) + index );
|
||||
uint64_t mask = ( 1UL << offset );
|
||||
uint64_t old;
|
||||
uint64_t new;
|
||||
|
||||
__asm__ __volatile__ ( "1: \n\t"
|
||||
"ll.d %[old], %[qword] \n\t"
|
||||
"andn %[new], %[old], %[mask] \n\t"
|
||||
"sc.d %[new], %[qword] \n\t"
|
||||
"beqz %[new], 1b \n\t"
|
||||
: [old] "=&r" ( old ),
|
||||
[new] "=&r" ( new ),
|
||||
[qword] "+m" ( *qword )
|
||||
: [mask] "r" ( mask )
|
||||
: "cc", "memory");
|
||||
return ( !! ( old & mask ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bit atomically
|
||||
*
|
||||
* @v bit Bit to set
|
||||
* @v bits Bit field
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
set_bit ( unsigned int bit, volatile void *bits ) {
|
||||
|
||||
test_and_set_bit ( bit, bits );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear bit atomically
|
||||
*
|
||||
* @v bit Bit to set
|
||||
* @v bits Bit field
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
clear_bit ( unsigned int bit, volatile void *bits ) {
|
||||
|
||||
test_and_clear_bit ( bit, bits );
|
||||
}
|
||||
|
||||
#endif /* _BITS_BITOPS_H */
|
||||
47
src/arch/loong64/include/bits/byteswap.h
Normal file
47
src/arch/loong64/include/bits/byteswap.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef _BITS_BYTESWAP_H
|
||||
#define _BITS_BYTESWAP_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Byte-order swapping functions
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
static inline __attribute__ (( always_inline, const )) uint16_t
|
||||
__bswap_variable_16 ( uint16_t x ) {
|
||||
__asm__ ( "revb.2h %0, %1" : "=r" ( x ) : "r" ( x ) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
__bswap_16s ( uint16_t *x ) {
|
||||
*x = __bswap_variable_16 ( *x );
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline, const )) uint32_t
|
||||
__bswap_variable_32 ( uint32_t x ) {
|
||||
__asm__ ( "revb.2w %0, %1" : "=r" ( x ) : "r" ( x ) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
__bswap_32s ( uint32_t *x ) {
|
||||
*x = __bswap_variable_32 ( *x );
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline, const )) uint64_t
|
||||
__bswap_variable_64 ( uint64_t x ) {
|
||||
__asm__ ( "revb.d %0, %1" : "=r" ( x ) : "r" ( x ) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
__bswap_64s ( uint64_t *x ) {
|
||||
*x = __bswap_variable_64 ( *x );
|
||||
}
|
||||
|
||||
#endif
|
||||
19
src/arch/loong64/include/bits/compiler.h
Normal file
19
src/arch/loong64/include/bits/compiler.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef _BITS_COMPILER_H
|
||||
#define _BITS_COMPILER_H
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
/** Dummy relocation type */
|
||||
#define RELOC_TYPE_NONE R_LARCH_NONE
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
/** Unprefixed constant operand modifier */
|
||||
#define ASM_NO_PREFIX "a"
|
||||
|
||||
#define __asmcall
|
||||
#define __libgcc
|
||||
|
||||
#endif /* ASSEMBLY */
|
||||
|
||||
#endif /*_BITS_COMPILER_H */
|
||||
8
src/arch/loong64/include/bits/endian.h
Normal file
8
src/arch/loong64/include/bits/endian.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef _BITS_ENDIAN_H
|
||||
#define _BITS_ENDIAN_H
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
|
||||
#endif /* _BITS_ENDIAN_H */
|
||||
19
src/arch/loong64/include/bits/errfile.h
Normal file
19
src/arch/loong64/include/bits/errfile.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef _BITS_ERRFILE_H
|
||||
#define _BITS_ERRFILE_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* LoongArch64-specific error file identifiers
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
/**
|
||||
* @addtogroup errfile Error file identifiers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* _BITS_ERRFILE_H */
|
||||
12
src/arch/loong64/include/bits/hyperv.h
Normal file
12
src/arch/loong64/include/bits/hyperv.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _BITS_HYPERV_H
|
||||
#define _BITS_HYPERV_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Hyper-V interface
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#endif /* _BITS_HYPERV_H */
|
||||
15
src/arch/loong64/include/bits/io.h
Normal file
15
src/arch/loong64/include/bits/io.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef _BITS_IO_H
|
||||
#define _BITS_IO_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* LoongArch64-specific I/O API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
/** Page shift */
|
||||
#define PAGE_SHIFT 12
|
||||
|
||||
#endif /* _BITS_IO_H */
|
||||
12
src/arch/loong64/include/bits/iomap.h
Normal file
12
src/arch/loong64/include/bits/iomap.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _BITS_IOMAP_H
|
||||
#define _BITS_IOMAP_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* LoongArch64-specific I/O mapping API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#endif /* _BITS_IOMAP_H */
|
||||
12
src/arch/loong64/include/bits/nap.h
Normal file
12
src/arch/loong64/include/bits/nap.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _BITS_NAP_H
|
||||
#define _BITS_NAP_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* LoongArch64-specific CPU sleeping API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#endif /* _BITS_MAP_H */
|
||||
12
src/arch/loong64/include/bits/pci_io.h
Normal file
12
src/arch/loong64/include/bits/pci_io.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _BITS_PCI_IO_H
|
||||
#define _BITS_PCI_IO_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* LoongArch64-specific PCI I/O API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#endif /* _BITS_PCI_IO_H */
|
||||
28
src/arch/loong64/include/bits/profile.h
Normal file
28
src/arch/loong64/include/bits/profile.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef _BITS_PROFILE_H
|
||||
#define _BITS_PROFILE_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Profiling
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Get profiling timestamp
|
||||
*
|
||||
* @ret timestamp Timestamp
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) uint64_t
|
||||
profile_timestamp ( void ) {
|
||||
uint64_t cycles;
|
||||
|
||||
/* Read cycle counter */
|
||||
__asm__ __volatile__ ( "rdtime.d %0, $zero\n\t" : "=r" ( cycles ) );
|
||||
return cycles;
|
||||
}
|
||||
|
||||
#endif /* _BITS_PROFILE_H */
|
||||
12
src/arch/loong64/include/bits/reboot.h
Normal file
12
src/arch/loong64/include/bits/reboot.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _BITS_REBOOT_H
|
||||
#define _BITS_REBOOT_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* LoongArch64-specific reboot API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#endif /* _BITS_REBOOT_H */
|
||||
12
src/arch/loong64/include/bits/sanboot.h
Normal file
12
src/arch/loong64/include/bits/sanboot.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _BITS_SANBOOT_H
|
||||
#define _BITS_SANBOOT_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* LoongArch64-specific sanboot API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#endif /* _BITS_SANBOOT_H */
|
||||
12
src/arch/loong64/include/bits/smbios.h
Normal file
12
src/arch/loong64/include/bits/smbios.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _BITS_SMBIOS_H
|
||||
#define _BITS_SMBIOS_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* LoongArch64-specific SMBIOS API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#endif /* _BITS_SMBIOS_H */
|
||||
23
src/arch/loong64/include/bits/stdint.h
Normal file
23
src/arch/loong64/include/bits/stdint.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef _BITS_STDINT_H
|
||||
#define _BITS_STDINT_H
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef signed long ssize_t;
|
||||
typedef signed long off_t;
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef signed long long int64_t;
|
||||
|
||||
typedef unsigned long physaddr_t;
|
||||
typedef unsigned long intptr_t;
|
||||
|
||||
#endif /* _BITS_STDINT_H */
|
||||
61
src/arch/loong64/include/bits/string.h
Normal file
61
src/arch/loong64/include/bits/string.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef _BITS_STRING_H
|
||||
#define _BITS_STRING_H
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* String functions
|
||||
*
|
||||
*/
|
||||
|
||||
extern void loong64_bzero ( void *dest, size_t len );
|
||||
extern void loong64_memset ( void *dest, size_t len, int character );
|
||||
extern void loong64_memcpy ( void *dest, const void *src, size_t len );
|
||||
extern void loong64_memmove_forwards ( void *dest, const void *src, size_t len );
|
||||
extern void loong64_memmove_backwards ( void *dest, const void *src, size_t len );
|
||||
extern void loong64_memmove ( void *dest, const void *src, size_t len );
|
||||
|
||||
/**
|
||||
* Fill memory region
|
||||
*
|
||||
* @v dest Destination region
|
||||
* @v character Fill character
|
||||
* @v len Length
|
||||
* @ret dest Destination region
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void *
|
||||
memset ( void *dest, int character, size_t len ) {
|
||||
loong64_memset ( dest, len, character );
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy memory region
|
||||
*
|
||||
* @v dest Destination region
|
||||
* @v src Source region
|
||||
* @v len Length
|
||||
* @ret dest Destination region
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void *
|
||||
memcpy ( void *dest, const void *src, size_t len ) {
|
||||
loong64_memcpy ( dest, src, len );
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy (possibly overlapping) memory region
|
||||
*
|
||||
* @v dest Destination region
|
||||
* @v src Source region
|
||||
* @v len Length
|
||||
* @ret dest Destination region
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void *
|
||||
memmove ( void *dest, const void *src, size_t len ) {
|
||||
loong64_memmove ( dest, src, len );
|
||||
return dest;
|
||||
}
|
||||
|
||||
#endif /* _BITS_STRING_H */
|
||||
69
src/arch/loong64/include/bits/strings.h
Normal file
69
src/arch/loong64/include/bits/strings.h
Normal file
@ -0,0 +1,69 @@
|
||||
#ifndef _BITS_STRINGS_H
|
||||
#define _BITS_STRINGS_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* String functions
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
/**
|
||||
* Find first (i.e. least significant) set bit
|
||||
*
|
||||
* @v value Value
|
||||
* @ret lsb Least significant bit set in value (LSB=1), or zero
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int __ffsll ( long long value ){
|
||||
unsigned long long bits = value;
|
||||
unsigned long long lsb;
|
||||
unsigned int lz;
|
||||
|
||||
/* Extract least significant set bit */
|
||||
lsb = ( bits & -bits );
|
||||
|
||||
/* Count number of leading zeroes before LSB */
|
||||
__asm__ ( "clz.d %0, %1" : "=r" ( lz ) : "r" ( lsb ) );
|
||||
|
||||
return ( 64 - lz );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find first (i.e. least significant) set bit
|
||||
*
|
||||
* @v value Value
|
||||
* @ret lsb Least significant bit set in value (LSB=1), or zero
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int __ffsl ( long value ) {
|
||||
|
||||
return __ffsll ( value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find last (i.e. most significant) set bit
|
||||
*
|
||||
* @v value Value
|
||||
* @ret msb Most significant bit set in value (LSB=1), or zero
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int __flsll ( long long value ){
|
||||
unsigned int lz;
|
||||
|
||||
/* Count number of leading zeroes */
|
||||
__asm__ ( "clz.d %0, %1" : "=r" ( lz ) : "r" ( value ) );
|
||||
|
||||
return ( 64 - lz );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find last (i.e. most significant) set bit
|
||||
*
|
||||
* @v value Value
|
||||
* @ret msb Most significant bit set in value (LSB=1), or zero
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int __flsl ( long value ) {
|
||||
|
||||
return __flsll ( value );
|
||||
}
|
||||
|
||||
#endif /* _BITS_STRINGS_H */
|
||||
19
src/arch/loong64/include/bits/tcpip.h
Normal file
19
src/arch/loong64/include/bits/tcpip.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef _BITS_TCPIP_H
|
||||
#define _BITS_TCPIP_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Transport-network layer interface
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
static inline __attribute__ (( always_inline )) uint16_t
|
||||
tcpip_continue_chksum ( uint16_t partial, const void *data, size_t len ) {
|
||||
|
||||
/* Not yet optimised */
|
||||
return generic_tcpip_continue_chksum ( partial, data, len );
|
||||
}
|
||||
|
||||
#endif /* _BITS_TCPIP_H */
|
||||
12
src/arch/loong64/include/bits/time.h
Normal file
12
src/arch/loong64/include/bits/time.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _BITS_TIME_H
|
||||
#define _BITS_TIME_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* LoongArch64-specific time API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#endif /* _BITS_TIME_H */
|
||||
12
src/arch/loong64/include/bits/uaccess.h
Normal file
12
src/arch/loong64/include/bits/uaccess.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _BITS_UACCESS_H
|
||||
#define _BITS_UACCESS_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* LoongArch64-specific user access API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#endif /* _BITS_UACCESS_H */
|
||||
12
src/arch/loong64/include/bits/uart.h
Normal file
12
src/arch/loong64/include/bits/uart.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _BITS_UART_H
|
||||
#define _BITS_UART_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* 16550-compatible UART
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#endif /* _BITS_UART_H */
|
||||
12
src/arch/loong64/include/bits/umalloc.h
Normal file
12
src/arch/loong64/include/bits/umalloc.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _BITS_UMALLOC_H
|
||||
#define _BITS_UMALLOC_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* LoongArch64-specific user memory allocation API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#endif /* _BITS_UMALLOC_H */
|
||||
13
src/arch/loong64/include/bits/xen.h
Normal file
13
src/arch/loong64/include/bits/xen.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef _BITS_XEN_H
|
||||
#define _BITS_XEN_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Xen interface
|
||||
*
|
||||
*/
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/nonxen.h>
|
||||
|
||||
#endif /* _BITS_XEN_H */
|
||||
45
src/arch/loong64/include/gdbmach.h
Normal file
45
src/arch/loong64/include/gdbmach.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef GDBMACH_H
|
||||
#define GDBMACH_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* GDB architecture specifics
|
||||
*
|
||||
* This file declares functions for manipulating the machine state and
|
||||
* debugging context.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef unsigned long gdbreg_t;
|
||||
|
||||
/* Register snapshot */
|
||||
enum {
|
||||
/* Not yet implemented */
|
||||
GDBMACH_NREGS,
|
||||
};
|
||||
|
||||
#define GDBMACH_SIZEOF_REGS ( GDBMACH_NREGS * sizeof ( gdbreg_t ) )
|
||||
|
||||
static inline void gdbmach_set_pc ( gdbreg_t *regs, gdbreg_t pc ) {
|
||||
/* Not yet implemented */
|
||||
( void ) regs;
|
||||
( void ) pc;
|
||||
}
|
||||
|
||||
static inline void gdbmach_set_single_step ( gdbreg_t *regs, int step ) {
|
||||
/* Not yet implemented */
|
||||
( void ) regs;
|
||||
( void ) step;
|
||||
}
|
||||
|
||||
static inline void gdbmach_breakpoint ( void ) {
|
||||
/* Not yet implemented */
|
||||
}
|
||||
|
||||
extern int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len,
|
||||
int enable );
|
||||
extern void gdbmach_init ( void );
|
||||
|
||||
#endif /* GDBMACH_H */
|
||||
20
src/arch/loong64/include/ipxe/efi/dhcparch.h
Normal file
20
src/arch/loong64/include/ipxe/efi/dhcparch.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef _IPXE_EFI_DHCPARCH_H
|
||||
#define _IPXE_EFI_DHCPARCH_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* DHCP client architecture definitions
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/dhcp.h>
|
||||
|
||||
/** DHCP client architecture */
|
||||
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_LOONG64
|
||||
|
||||
/** DHCP client network device interface */
|
||||
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
|
||||
|
||||
#endif /* _IPXE_EFI_DHCPARCH_H */
|
||||
53
src/arch/loong64/include/limits.h
Normal file
53
src/arch/loong64/include/limits.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef LIMITS_H
|
||||
#define LIMITS_H 1
|
||||
|
||||
/* Number of bits in a `char' */
|
||||
#define CHAR_BIT 8
|
||||
|
||||
/* Minimum and maximum values a `signed char' can hold */
|
||||
#define SCHAR_MIN (-128)
|
||||
#define SCHAR_MAX 127
|
||||
|
||||
/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */
|
||||
#define UCHAR_MAX 255
|
||||
|
||||
/* Minimum and maximum values a `char' can hold */
|
||||
#define CHAR_MIN SCHAR_MIN
|
||||
#define CHAR_MAX SCHAR_MAX
|
||||
|
||||
/* Minimum and maximum values a `signed short int' can hold */
|
||||
#define SHRT_MIN (-32768)
|
||||
#define SHRT_MAX 32767
|
||||
|
||||
/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */
|
||||
#define USHRT_MAX 65535
|
||||
|
||||
/* Minimum and maximum values a `signed int' can hold */
|
||||
#define INT_MIN (-INT_MAX - 1)
|
||||
#define INT_MAX 2147483647
|
||||
|
||||
/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
|
||||
#define UINT_MAX 4294967295U
|
||||
|
||||
/* Minimum and maximum values a `signed int' can hold */
|
||||
#define INT_MAX 2147483647
|
||||
#define INT_MIN (-INT_MAX - 1)
|
||||
|
||||
/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
|
||||
#define UINT_MAX 4294967295U
|
||||
|
||||
/* Minimum and maximum values a `signed long' can hold */
|
||||
#define LONG_MAX 9223372036854775807L
|
||||
#define LONG_MIN (-LONG_MAX - 1L)
|
||||
|
||||
/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */
|
||||
#define ULONG_MAX 18446744073709551615UL
|
||||
|
||||
/* Minimum and maximum values a `signed long long' can hold */
|
||||
#define LLONG_MAX 9223372036854775807LL
|
||||
#define LLONG_MIN (-LONG_MAX - 1LL)
|
||||
|
||||
/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */
|
||||
#define ULLONG_MAX 18446744073709551615ULL
|
||||
|
||||
#endif /* LIMITS_H */
|
||||
31
src/arch/loong64/include/setjmp.h
Normal file
31
src/arch/loong64/include/setjmp.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef _SETJMP_H
|
||||
#define _SETJMP_H
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** jump buffer env*/
|
||||
typedef struct {
|
||||
uint64_t s0;
|
||||
uint64_t s1;
|
||||
uint64_t s2;
|
||||
uint64_t s3;
|
||||
uint64_t s4;
|
||||
uint64_t s5;
|
||||
uint64_t s6;
|
||||
uint64_t s7;
|
||||
uint64_t s8;
|
||||
|
||||
uint64_t fp;
|
||||
uint64_t sp;
|
||||
uint64_t ra;
|
||||
} jmp_buf[1];
|
||||
|
||||
extern int __asmcall __attribute__ (( returns_twice ))
|
||||
setjmp ( jmp_buf env );
|
||||
|
||||
extern void __asmcall __attribute__ (( noreturn ))
|
||||
longjmp ( jmp_buf env, int val );
|
||||
|
||||
#endif /* _SETJMP_H */
|
||||
@ -22,9 +22,6 @@ SRCDIRS += arch/x86/drivers/xen
|
||||
SRCDIRS += arch/x86/drivers/hyperv
|
||||
SRCDIRS += arch/x86/transitions
|
||||
|
||||
# breaks building some of the linux-related objects
|
||||
CFLAGS += -Ulinux
|
||||
|
||||
# disable valgrind
|
||||
CFLAGS += -DNVALGRIND
|
||||
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
# -*- makefile -*- : Force emacs to use Makefile mode
|
||||
|
||||
# Include x86 Linux headers
|
||||
#
|
||||
INCDIRS += arch/x86/include/linux
|
||||
|
||||
# Include generic Linux Makefile
|
||||
#
|
||||
MAKEDEPS += Makefile.linux
|
||||
|
||||
103
src/arch/x86/core/rdrand.c
Normal file
103
src/arch/x86/core/rdrand.c
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* You can also choose to distribute this program under the terms of
|
||||
* the Unmodified Binary Distribution Licence (as given in the file
|
||||
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Hardware random number generator
|
||||
*
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <ipxe/cpuid.h>
|
||||
#include <ipxe/entropy.h>
|
||||
#include <ipxe/drbg.h>
|
||||
|
||||
struct entropy_source rdrand_entropy __entropy_source ( ENTROPY_PREFERRED );
|
||||
|
||||
/** Number of times to retry RDRAND instruction */
|
||||
#define RDRAND_RETRY_COUNT 16
|
||||
|
||||
/** Colour for debug messages */
|
||||
#define colour &rdrand_entropy
|
||||
|
||||
/**
|
||||
* Enable entropy gathering
|
||||
*
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int rdrand_entropy_enable ( void ) {
|
||||
struct x86_features features;
|
||||
|
||||
/* Check that RDRAND is supported */
|
||||
x86_features ( &features );
|
||||
if ( ! ( features.intel.ecx & CPUID_FEATURES_INTEL_ECX_RDRAND ) ) {
|
||||
DBGC ( colour, "RDRAND not supported\n" );
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Data returned by RDRAND is theoretically full entropy, up
|
||||
* to a security strength of 128 bits, so assume that each
|
||||
* sample contains exactly 8 bits of entropy.
|
||||
*/
|
||||
if ( DRBG_SECURITY_STRENGTH > 128 )
|
||||
return -ENOTSUP;
|
||||
entropy_init ( &rdrand_entropy, MIN_ENTROPY ( 8.0 ) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get noise sample
|
||||
*
|
||||
* @ret noise Noise sample
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int rdrand_get_noise ( noise_sample_t *noise ) {
|
||||
unsigned int result;
|
||||
unsigned int discard_c;
|
||||
unsigned int ok;
|
||||
|
||||
/* Issue RDRAND, retrying until CF is set */
|
||||
__asm__ ( "\n1:\n\t"
|
||||
"rdrand %0\n\t"
|
||||
"sbb %1, %1\n\t"
|
||||
"loopz 1b\n\t"
|
||||
: "=r" ( result ), "=r" ( ok ), "=c" ( discard_c )
|
||||
: "2" ( RDRAND_RETRY_COUNT ) );
|
||||
if ( ! ok ) {
|
||||
DBGC ( colour, "RDRAND failed to become ready\n" );
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
*noise = result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Hardware random number generator entropy source */
|
||||
struct entropy_source rdrand_entropy __entropy_source ( ENTROPY_PREFERRED ) = {
|
||||
.name = "rdrand",
|
||||
.enable = rdrand_entropy_enable,
|
||||
.get_noise = rdrand_get_noise,
|
||||
};
|
||||
@ -247,19 +247,17 @@ static void bzimage_update_header ( struct image *image,
|
||||
*
|
||||
* @v image bzImage file
|
||||
* @v bzimg bzImage context
|
||||
* @v cmdline Kernel command line
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int bzimage_parse_cmdline ( struct image *image,
|
||||
struct bzimage_context *bzimg,
|
||||
char *cmdline ) {
|
||||
struct bzimage_context *bzimg ) {
|
||||
const char *vga;
|
||||
const char *mem;
|
||||
char *sep;
|
||||
char *vga;
|
||||
char *mem;
|
||||
char *end;
|
||||
|
||||
/* Look for "vga=" */
|
||||
if ( ( vga = strstr ( cmdline, "vga=" ) ) ) {
|
||||
vga += 4;
|
||||
if ( ( vga = image_argument ( image, "vga=" ) ) ) {
|
||||
sep = strchr ( vga, ' ' );
|
||||
if ( sep )
|
||||
*sep = '\0';
|
||||
@ -270,10 +268,10 @@ static int bzimage_parse_cmdline ( struct image *image,
|
||||
} else if ( strcmp ( vga, "ask" ) == 0 ) {
|
||||
bzimg->vid_mode = BZI_VID_MODE_ASK;
|
||||
} else {
|
||||
bzimg->vid_mode = strtoul ( vga, &vga, 0 );
|
||||
if ( *vga ) {
|
||||
bzimg->vid_mode = strtoul ( vga, &end, 0 );
|
||||
if ( *end ) {
|
||||
DBGC ( image, "bzImage %p strange \"vga=\" "
|
||||
"terminator '%c'\n", image, *vga );
|
||||
"terminator '%c'\n", image, *end );
|
||||
}
|
||||
}
|
||||
if ( sep )
|
||||
@ -281,10 +279,9 @@ static int bzimage_parse_cmdline ( struct image *image,
|
||||
}
|
||||
|
||||
/* Look for "mem=" */
|
||||
if ( ( mem = strstr ( cmdline, "mem=" ) ) ) {
|
||||
mem += 4;
|
||||
bzimg->mem_limit = strtoul ( mem, &mem, 0 );
|
||||
switch ( *mem ) {
|
||||
if ( ( mem = image_argument ( image, "mem=" ) ) ) {
|
||||
bzimg->mem_limit = strtoul ( mem, &end, 0 );
|
||||
switch ( *end ) {
|
||||
case 'G':
|
||||
case 'g':
|
||||
bzimg->mem_limit <<= 10;
|
||||
@ -302,7 +299,7 @@ static int bzimage_parse_cmdline ( struct image *image,
|
||||
break;
|
||||
default:
|
||||
DBGC ( image, "bzImage %p strange \"mem=\" "
|
||||
"terminator '%c'\n", image, *mem );
|
||||
"terminator '%c'\n", image, *end );
|
||||
break;
|
||||
}
|
||||
bzimg->mem_limit -= 1;
|
||||
@ -316,11 +313,10 @@ static int bzimage_parse_cmdline ( struct image *image,
|
||||
*
|
||||
* @v image bzImage image
|
||||
* @v bzimg bzImage context
|
||||
* @v cmdline Kernel command line
|
||||
*/
|
||||
static void bzimage_set_cmdline ( struct image *image,
|
||||
struct bzimage_context *bzimg,
|
||||
const char *cmdline ) {
|
||||
struct bzimage_context *bzimg ) {
|
||||
const char *cmdline = ( image->cmdline ? image->cmdline : "" );
|
||||
size_t cmdline_len;
|
||||
|
||||
/* Copy command line down to real-mode portion */
|
||||
@ -359,8 +355,8 @@ static size_t bzimage_load_initrd ( struct image *image,
|
||||
size_t offset;
|
||||
size_t pad_len;
|
||||
|
||||
/* Do not include kernel image itself as an initrd */
|
||||
if ( initrd == image )
|
||||
/* Skip hidden images */
|
||||
if ( initrd->flags & IMAGE_HIDDEN )
|
||||
return 0;
|
||||
|
||||
/* Create cpio header for non-prebuilt images */
|
||||
@ -410,10 +406,6 @@ static int bzimage_check_initrds ( struct image *image,
|
||||
/* Calculate total loaded length of initrds */
|
||||
for_each_image ( initrd ) {
|
||||
|
||||
/* Skip kernel */
|
||||
if ( initrd == image )
|
||||
continue;
|
||||
|
||||
/* Calculate length */
|
||||
len += bzimage_load_initrd ( image, initrd, UNULL );
|
||||
len = bzimage_align ( len );
|
||||
@ -528,7 +520,6 @@ static void bzimage_load_initrds ( struct image *image,
|
||||
*/
|
||||
static int bzimage_exec ( struct image *image ) {
|
||||
struct bzimage_context bzimg;
|
||||
char *cmdline = ( image->cmdline ? image->cmdline : "" );
|
||||
int rc;
|
||||
|
||||
/* Read and parse header from image */
|
||||
@ -551,7 +542,7 @@ static int bzimage_exec ( struct image *image ) {
|
||||
}
|
||||
|
||||
/* Parse command line for bootloader parameters */
|
||||
if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0)
|
||||
if ( ( rc = bzimage_parse_cmdline ( image, &bzimg ) ) != 0)
|
||||
return rc;
|
||||
|
||||
/* Check that initrds can be loaded */
|
||||
@ -568,7 +559,7 @@ static int bzimage_exec ( struct image *image ) {
|
||||
bzimg.rm_filesz, bzimg.pm_sz );
|
||||
|
||||
/* Store command line */
|
||||
bzimage_set_cmdline ( image, &bzimg, cmdline );
|
||||
bzimage_set_cmdline ( image, &bzimg );
|
||||
|
||||
/* Prepare for exiting. Must do this before loading initrds,
|
||||
* since loading the initrds will corrupt the external heap.
|
||||
|
||||
@ -204,8 +204,8 @@ static int multiboot_add_modules ( struct image *image, physaddr_t start,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Do not include kernel image itself as a module */
|
||||
if ( module_image == image )
|
||||
/* Skip hidden images */
|
||||
if ( module_image->flags & IMAGE_HIDDEN )
|
||||
continue;
|
||||
|
||||
/* Page-align the module */
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
#ifndef _BITS_ENTROPY_H
|
||||
#define _BITS_ENTROPY_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* x86-specific entropy API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/rtc_entropy.h>
|
||||
|
||||
#endif /* _BITS_ENTROPY_H */
|
||||
@ -28,6 +28,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#define ERRFILE_cpuid ( ERRFILE_ARCH | ERRFILE_CORE | 0x00110000 )
|
||||
#define ERRFILE_rdtsc_timer ( ERRFILE_ARCH | ERRFILE_CORE | 0x00120000 )
|
||||
#define ERRFILE_acpi_timer ( ERRFILE_ARCH | ERRFILE_CORE | 0x00130000 )
|
||||
#define ERRFILE_rdrand ( ERRFILE_ARCH | ERRFILE_CORE | 0x00140000 )
|
||||
|
||||
#define ERRFILE_bootsector ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 )
|
||||
#define ERRFILE_bzimage ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 )
|
||||
|
||||
@ -9,6 +9,9 @@
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
/** Page shift */
|
||||
#define PAGE_SHIFT 12
|
||||
|
||||
#include <ipxe/x86_io.h>
|
||||
|
||||
#endif /* _BITS_IO_H */
|
||||
|
||||
@ -39,6 +39,9 @@ struct x86_features {
|
||||
/** Get standard features */
|
||||
#define CPUID_FEATURES 0x00000001UL
|
||||
|
||||
/** RDRAND instruction is supported */
|
||||
#define CPUID_FEATURES_INTEL_ECX_RDRAND 0x40000000UL
|
||||
|
||||
/** Hypervisor is present */
|
||||
#define CPUID_FEATURES_INTEL_ECX_HYPERVISOR 0x80000000UL
|
||||
|
||||
|
||||
20
src/arch/x86/include/ipxe/pcbios/dhcparch.h
Normal file
20
src/arch/x86/include/ipxe/pcbios/dhcparch.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef _IPXE_PCBIOS_DHCPARCH_H
|
||||
#define _IPXE_PCBIOS_DHCPARCH_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* DHCP client architecture definitions
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/dhcp.h>
|
||||
|
||||
/** DHCP client architecture */
|
||||
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_X86
|
||||
|
||||
/** DHCP client network device interface */
|
||||
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 2, 1 /* v2.1 */
|
||||
|
||||
#endif /* _IPXE_PCBIOS_DHCPARCH_H */
|
||||
@ -1,62 +0,0 @@
|
||||
#ifndef _IPXE_RTC_ENTROPY_H
|
||||
#define _IPXE_RTC_ENTROPY_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* RTC-based entropy source
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef ENTROPY_RTC
|
||||
#define ENTROPY_PREFIX_rtc
|
||||
#else
|
||||
#define ENTROPY_PREFIX_rtc __rtc_
|
||||
#endif
|
||||
|
||||
/**
|
||||
* min-entropy per sample
|
||||
*
|
||||
* @ret min_entropy min-entropy of each sample
|
||||
*/
|
||||
static inline __always_inline min_entropy_t
|
||||
ENTROPY_INLINE ( rtc, min_entropy_per_sample ) ( void ) {
|
||||
|
||||
/* The min-entropy has been measured on several platforms
|
||||
* using the entropy_sample test code. Modelling the samples
|
||||
* as independent, and using a confidence level of 99.99%, the
|
||||
* measurements were as follows:
|
||||
*
|
||||
* qemu-kvm : 7.38 bits
|
||||
* VMware : 7.46 bits
|
||||
* Physical hardware : 2.67 bits
|
||||
*
|
||||
* We choose the lowest of these (2.67 bits) and apply a 50%
|
||||
* safety margin to allow for some potential non-independence
|
||||
* of samples.
|
||||
*/
|
||||
return MIN_ENTROPY ( 1.3 );
|
||||
}
|
||||
|
||||
extern uint8_t rtc_sample ( void );
|
||||
|
||||
/**
|
||||
* Get noise sample
|
||||
*
|
||||
* @ret noise Noise sample
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static inline __always_inline int
|
||||
ENTROPY_INLINE ( rtc, get_noise ) ( noise_sample_t *noise ) {
|
||||
|
||||
/* Get sample */
|
||||
*noise = rtc_sample();
|
||||
|
||||
/* Always successful */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _IPXE_RTC_ENTROPY_H */
|
||||
@ -28,9 +28,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
*
|
||||
*/
|
||||
|
||||
/** Page shift */
|
||||
#define PAGE_SHIFT 12
|
||||
|
||||
/*
|
||||
* Physical<->Bus address mappings
|
||||
*
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* You can also choose to distribute this program under the terms of
|
||||
* the Unmodified Binary Distribution Licence (as given in the file
|
||||
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_DHCP_ARCH_H
|
||||
#define _LINUX_DHCP_ARCH_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Architecture-specific DHCP options
|
||||
*/
|
||||
|
||||
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL);
|
||||
|
||||
#include <ipxe/dhcp.h>
|
||||
|
||||
// Emulate one of the supported arch-platforms
|
||||
#include <arch/i386/include/pcbios/ipxe/dhcp_arch.h>
|
||||
//#include <arch/i386/include/efi/ipxe/dhcp_arch.h>
|
||||
//#include <arch/x86_64/include/efi/ipxe/dhcp_arch.h>
|
||||
|
||||
#endif
|
||||
@ -39,9 +39,14 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#include <ipxe/cpuid.h>
|
||||
#include <ipxe/entropy.h>
|
||||
|
||||
struct entropy_source rtc_entropy __entropy_source ( ENTROPY_NORMAL );
|
||||
|
||||
/** Maximum time to wait for an RTC interrupt, in milliseconds */
|
||||
#define RTC_MAX_WAIT_MS 100
|
||||
|
||||
/** Number of RTC interrupts to check for */
|
||||
#define RTC_CHECK_COUNT 3
|
||||
|
||||
/** RTC interrupt handler */
|
||||
extern void rtc_isr ( void );
|
||||
|
||||
@ -145,6 +150,7 @@ static void rtc_disable_int ( void ) {
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int rtc_entropy_check ( void ) {
|
||||
unsigned int count = 0;
|
||||
unsigned int i;
|
||||
|
||||
/* Check that RTC interrupts are working */
|
||||
@ -158,14 +164,18 @@ static int rtc_entropy_check ( void ) {
|
||||
"cli\n\t" );
|
||||
|
||||
/* Check for RTC interrupt flag */
|
||||
if ( rtc_flag )
|
||||
return 0;
|
||||
if ( rtc_flag ) {
|
||||
rtc_flag = 0;
|
||||
if ( ++count >= RTC_CHECK_COUNT )
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Delay */
|
||||
mdelay ( 1 );
|
||||
}
|
||||
|
||||
DBGC ( &rtc_flag, "RTC timed out waiting for interrupt\n" );
|
||||
DBGC ( &rtc_flag, "RTC timed out waiting for interrupt %d/%d\n",
|
||||
( count + 1 ), RTC_CHECK_COUNT );
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -195,6 +205,21 @@ static int rtc_entropy_enable ( void ) {
|
||||
if ( ( rc = rtc_entropy_check() ) != 0 )
|
||||
goto err_check;
|
||||
|
||||
/* The min-entropy has been measured on several platforms
|
||||
* using the entropy_sample test code. Modelling the samples
|
||||
* as independent, and using a confidence level of 99.99%, the
|
||||
* measurements were as follows:
|
||||
*
|
||||
* qemu-kvm : 7.38 bits
|
||||
* VMware : 7.46 bits
|
||||
* Physical hardware : 2.67 bits
|
||||
*
|
||||
* We choose the lowest of these (2.67 bits) and apply a 50%
|
||||
* safety margin to allow for some potential non-independence
|
||||
* of samples.
|
||||
*/
|
||||
entropy_init ( &rtc_entropy, MIN_ENTROPY ( 1.3 ) );
|
||||
|
||||
return 0;
|
||||
|
||||
err_check:
|
||||
@ -218,11 +243,12 @@ static void rtc_entropy_disable ( void ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Measure a single RTC tick
|
||||
* Get noise sample
|
||||
*
|
||||
* @ret delta Length of RTC tick (in TSC units)
|
||||
* @ret noise Noise sample
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
uint8_t rtc_sample ( void ) {
|
||||
static int rtc_get_noise ( noise_sample_t *noise ) {
|
||||
uint32_t before;
|
||||
uint32_t after;
|
||||
uint32_t temp;
|
||||
@ -257,10 +283,14 @@ uint8_t rtc_sample ( void ) {
|
||||
: "=a" ( after ), "=d" ( before ), "=Q" ( temp )
|
||||
: "2" ( 0 ) );
|
||||
|
||||
return ( after - before );
|
||||
*noise = ( after - before );
|
||||
return 0;
|
||||
}
|
||||
|
||||
PROVIDE_ENTROPY_INLINE ( rtc, min_entropy_per_sample );
|
||||
PROVIDE_ENTROPY ( rtc, entropy_enable, rtc_entropy_enable );
|
||||
PROVIDE_ENTROPY ( rtc, entropy_disable, rtc_entropy_disable );
|
||||
PROVIDE_ENTROPY_INLINE ( rtc, get_noise );
|
||||
/** RTC entropy source */
|
||||
struct entropy_source rtc_entropy __entropy_source ( ENTROPY_NORMAL ) = {
|
||||
.name = "rtc",
|
||||
.enable = rtc_entropy_enable,
|
||||
.disable = rtc_entropy_disable,
|
||||
.get_noise = rtc_get_noise,
|
||||
};
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include <ipxe/uaccess.h>
|
||||
#include <ipxe/process.h>
|
||||
#include <ipxe/netdevice.h>
|
||||
#include <ipxe/malloc.h>
|
||||
#include <realmode.h>
|
||||
#include <pxe.h>
|
||||
|
||||
@ -482,3 +483,28 @@ struct pxe_api_call pxe_udp_api[] __pxe_api_call = {
|
||||
PXE_API_CALL ( PXENV_UDP_READ, pxenv_udp_read,
|
||||
struct s_PXENV_UDP_READ ),
|
||||
};
|
||||
|
||||
/**
|
||||
* Discard some cached PXE UDP data
|
||||
*
|
||||
* @ret discarded Number of cached items discarded
|
||||
*/
|
||||
static unsigned int pxe_udp_discard ( void ) {
|
||||
struct io_buffer *iobuf;
|
||||
unsigned int discarded = 0;
|
||||
|
||||
/* Try to discard the oldest received UDP packet */
|
||||
iobuf = list_first_entry ( &pxe_udp.list, struct io_buffer, list );
|
||||
if ( iobuf ) {
|
||||
list_del ( &iobuf->list );
|
||||
free_iob ( iobuf );
|
||||
discarded++;
|
||||
}
|
||||
|
||||
return discarded;
|
||||
}
|
||||
|
||||
/** PXE UDP cache discarder */
|
||||
struct cache_discarder pxe_udp_discarder __cache_discarder ( CACHE_NORMAL ) = {
|
||||
.discard = pxe_udp_discard,
|
||||
};
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
# -*- makefile -*- : Force emacs to use Makefile mode
|
||||
|
||||
# Linker script
|
||||
# Starting virtual address
|
||||
#
|
||||
LDSCRIPT = arch/x86_64/scripts/linux.lds
|
||||
LDFLAGS += -Ttext=0x400000
|
||||
|
||||
# Include generic Linux Makefile
|
||||
#
|
||||
|
||||
@ -8,6 +8,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
/** Unprefixed constant operand modifier */
|
||||
#define ASM_NO_PREFIX "c"
|
||||
|
||||
/** Declare a function with standard calling conventions */
|
||||
#define __asmcall __attribute__ (( regparm(0) ))
|
||||
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* You can also choose to distribute this program under the terms of
|
||||
* the Unmodified Binary Distribution Licence (as given in the file
|
||||
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||
*/
|
||||
|
||||
#ifndef _DHCP_ARCH_H
|
||||
#define _DHCP_ARCH_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Architecture-specific DHCP options
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/dhcp.h>
|
||||
|
||||
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_X86_64
|
||||
|
||||
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
|
||||
|
||||
#endif
|
||||
20
src/arch/x86_64/include/ipxe/efi/dhcparch.h
Normal file
20
src/arch/x86_64/include/ipxe/efi/dhcparch.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef _IPXE_EFI_DHCPARCH_H
|
||||
#define _IPXE_EFI_DHCPARCH_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* DHCP client architecture definitions
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/dhcp.h>
|
||||
|
||||
/** DHCP client architecture */
|
||||
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_X86_64
|
||||
|
||||
/** DHCP client network device interface */
|
||||
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
|
||||
|
||||
#endif /* _IPXE_EFI_DHCPARCH_H */
|
||||
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* You can also choose to distribute this program under the terms of
|
||||
* the Unmodified Binary Distribution Licence (as given in the file
|
||||
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||
*/
|
||||
|
||||
#ifndef _DHCP_ARCH_H
|
||||
#define _DHCP_ARCH_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Architecture-specific DHCP options
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/dhcp.h>
|
||||
|
||||
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_X86
|
||||
|
||||
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 2, 1 /* v2.1 */
|
||||
|
||||
#endif
|
||||
@ -1,106 +0,0 @@
|
||||
/* -*- sh -*- */
|
||||
|
||||
/*
|
||||
* Linker script for x86_64 Linux images
|
||||
*
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT ( "elf64-x86-64", "elf64-x86-64", "elf64-x86-64" )
|
||||
OUTPUT_ARCH ( i386:x86-64 )
|
||||
|
||||
SECTIONS {
|
||||
_max_align = 32;
|
||||
|
||||
. = 0x400000;
|
||||
|
||||
/*
|
||||
* The text section
|
||||
*
|
||||
*/
|
||||
|
||||
. = ALIGN ( _max_align );
|
||||
.text : {
|
||||
_text = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
_etext = .;
|
||||
}
|
||||
|
||||
/*
|
||||
* The rodata section
|
||||
*
|
||||
*/
|
||||
|
||||
. = ALIGN ( _max_align );
|
||||
.rodata : {
|
||||
_rodata = .;
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
_erodata = .;
|
||||
}
|
||||
|
||||
/*
|
||||
* The data section
|
||||
*
|
||||
* Adjust the address for the data segment. We want to adjust up to
|
||||
* the same address within the page on the next page up.
|
||||
*/
|
||||
|
||||
. = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1));
|
||||
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
|
||||
.data : {
|
||||
_data = .;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
KEEP(*(SORT(.tbl.*)))
|
||||
KEEP(*(.provided))
|
||||
KEEP(*(.provided.*))
|
||||
_edata = .;
|
||||
}
|
||||
|
||||
/*
|
||||
* The bss section
|
||||
*
|
||||
*/
|
||||
|
||||
. = ALIGN ( _max_align );
|
||||
.bss : {
|
||||
_bss = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(COMMON)
|
||||
_ebss = .;
|
||||
}
|
||||
|
||||
/*
|
||||
* Weak symbols that need zero values if not otherwise defined
|
||||
*
|
||||
*/
|
||||
|
||||
.weak 0x0 : {
|
||||
_weak = .;
|
||||
*(.weak)
|
||||
*(.weak.*)
|
||||
_eweak = .;
|
||||
}
|
||||
_assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
|
||||
|
||||
/*
|
||||
* Dispose of the comment and note sections to make the link map
|
||||
* easier to read
|
||||
*
|
||||
*/
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.comment)
|
||||
*(.comment.*)
|
||||
*(.note)
|
||||
*(.note.*)
|
||||
*(.rel)
|
||||
*(.rel.*)
|
||||
*(.discard)
|
||||
*(.discard.*)
|
||||
*(.sbat)
|
||||
*(.sbat.*)
|
||||
}
|
||||
}
|
||||
@ -290,6 +290,9 @@ REQUIRE_OBJECT ( cert_cmd );
|
||||
#ifdef IMAGE_MEM_CMD
|
||||
REQUIRE_OBJECT ( image_mem_cmd );
|
||||
#endif
|
||||
#ifdef SHIM_CMD
|
||||
REQUIRE_OBJECT ( shim_cmd );
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Drag in miscellaneous objects
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* Copyright (C) 2010 VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
@ -21,20 +19,33 @@
|
||||
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||
*/
|
||||
|
||||
#ifndef _DHCP_ARCH_H
|
||||
#define _DHCP_ARCH_H
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <config/entropy.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Architecture-specific DHCP options
|
||||
* Entropy configuration options
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/dhcp.h>
|
||||
|
||||
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_X86
|
||||
|
||||
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 2, 1 /* v2.1 */
|
||||
PROVIDE_REQUIRING_SYMBOL();
|
||||
|
||||
/*
|
||||
* Drag in entropy sources
|
||||
*/
|
||||
#ifdef ENTROPY_RTC
|
||||
REQUIRE_OBJECT ( rtc_entropy );
|
||||
#endif
|
||||
#ifdef ENTROPY_EFITICK
|
||||
REQUIRE_OBJECT ( efi_entropy );
|
||||
#endif
|
||||
#ifdef ENTROPY_EFIRNG
|
||||
REQUIRE_OBJECT ( efi_rng );
|
||||
#endif
|
||||
#ifdef ENTROPY_LINUX
|
||||
REQUIRE_OBJECT ( linux_entropy );
|
||||
#endif
|
||||
#ifdef ENTROPY_RDRAND
|
||||
REQUIRE_OBJECT ( rdrand );
|
||||
#endif
|
||||
@ -49,3 +49,6 @@ REQUIRE_OBJECT ( eth_slow );
|
||||
#ifdef NET_PROTO_EAPOL
|
||||
REQUIRE_OBJECT ( eapol );
|
||||
#endif
|
||||
#ifdef NET_PROTO_LLDP
|
||||
REQUIRE_OBJECT ( lldp );
|
||||
#endif
|
||||
|
||||
@ -19,13 +19,15 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#define SMBIOS_EFI
|
||||
#define SANBOOT_EFI
|
||||
#define BOFM_EFI
|
||||
#define ENTROPY_EFI
|
||||
#define ENTROPY_EFITICK
|
||||
#define ENTROPY_EFIRNG
|
||||
#define TIME_EFI
|
||||
#define REBOOT_EFI
|
||||
#define ACPI_EFI
|
||||
#define FDT_EFI
|
||||
|
||||
#define NET_PROTO_IPV6 /* IPv6 protocol */
|
||||
#define NET_PROTO_LLDP /* Link Layer Discovery protocol */
|
||||
|
||||
#define DOWNLOAD_PROTO_FILE /* Local filesystem access */
|
||||
|
||||
@ -49,6 +51,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#if defined ( __i386__ ) || defined ( __x86_64__ )
|
||||
#define IOAPI_X86
|
||||
#define NAP_EFIX86
|
||||
#define ENTROPY_RDRAND
|
||||
#define CPUID_CMD /* x86 CPU feature detection command */
|
||||
#define UNSAFE_STD /* Avoid setting direction flag */
|
||||
#endif
|
||||
|
||||
@ -33,4 +33,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#define SANBOOT_PROTO_FCP
|
||||
#define SANBOOT_PROTO_HTTP
|
||||
|
||||
#if defined ( __i386__ ) || defined ( __x86_64__ )
|
||||
#define ENTROPY_RDRAND
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_DEFAULTS_LINUX_H */
|
||||
|
||||
@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#define SMBIOS_PCBIOS
|
||||
#define SANBOOT_PCBIOS
|
||||
#define ENTROPY_RTC
|
||||
#define ENTROPY_RDRAND
|
||||
#define TIME_RTC
|
||||
#define REBOOT_PCBIOS
|
||||
#define ACPI_RSDP
|
||||
|
||||
@ -40,6 +40,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#define NET_PROTO_STP /* Spanning Tree protocol */
|
||||
#define NET_PROTO_LACP /* Link Aggregation control protocol */
|
||||
#define NET_PROTO_EAPOL /* EAP over LAN protocol */
|
||||
//#define NET_PROTO_LLDP /* Link Layer Discovery protocol */
|
||||
|
||||
/*
|
||||
* PXE support
|
||||
@ -149,7 +150,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
//#define POWEROFF_CMD /* Power off command */
|
||||
//#define IMAGE_TRUST_CMD /* Image trust management commands */
|
||||
//#define PCI_CMD /* PCI commands */
|
||||
//#define PARAM_CMD /* Form parameter commands */
|
||||
//#define PARAM_CMD /* Request parameter commands */
|
||||
//#define NEIGHBOUR_CMD /* Neighbour management commands */
|
||||
//#define PING_CMD /* Ping command */
|
||||
//#define CONSOLE_CMD /* Console command */
|
||||
@ -159,6 +160,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
//#define CERT_CMD /* Certificate management commands */
|
||||
//#define IMAGE_MEM_CMD /* Read memory command */
|
||||
#define IMAGE_ARCHIVE_CMD /* Archive image management commands */
|
||||
#define SHIM_CMD /* EFI shim command (or dummy command) */
|
||||
|
||||
/*
|
||||
* ROM-specific options
|
||||
|
||||
@ -77,17 +77,12 @@ size_t cpio_name_len ( struct image *image ) {
|
||||
*/
|
||||
static void cpio_parse_cmdline ( struct image *image,
|
||||
struct cpio_header *cpio ) {
|
||||
const char *cmdline;
|
||||
char *arg;
|
||||
const char *arg;
|
||||
char *end;
|
||||
unsigned int mode;
|
||||
|
||||
/* Skip image filename */
|
||||
cmdline = ( cpio_name ( image ) + cpio_name_len ( image ) );
|
||||
|
||||
/* Look for "mode=" */
|
||||
if ( ( arg = strstr ( cmdline, "mode=" ) ) ) {
|
||||
arg += 5;
|
||||
if ( ( arg = image_argument ( image, "mode=" ) ) ) {
|
||||
mode = strtoul ( arg, &end, 8 /* Octal for file mode */ );
|
||||
if ( *end && ( *end != ' ' ) ) {
|
||||
DBGC ( image, "CPIO %p strange \"mode=\" "
|
||||
|
||||
114
src/core/image.c
114
src/core/image.c
@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <libgen.h>
|
||||
@ -55,8 +56,15 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
/** List of registered images */
|
||||
struct list_head images = LIST_HEAD_INIT ( images );
|
||||
|
||||
/** Image selected for execution */
|
||||
struct image_tag selected_image __image_tag = {
|
||||
.name = "SELECTED",
|
||||
};
|
||||
|
||||
/** Currently-executing image */
|
||||
struct image *current_image;
|
||||
struct image_tag current_image __image_tag = {
|
||||
.name = "CURRENT",
|
||||
};
|
||||
|
||||
/** Current image trust requirement */
|
||||
static int require_trusted_images = 0;
|
||||
@ -71,8 +79,13 @@ static int require_trusted_images_permanent = 0;
|
||||
*/
|
||||
static void free_image ( struct refcnt *refcnt ) {
|
||||
struct image *image = container_of ( refcnt, struct image, refcnt );
|
||||
struct image_tag *tag;
|
||||
|
||||
DBGC ( image, "IMAGE %s freed\n", image->name );
|
||||
for_each_table_entry ( tag, IMAGE_TAGS ) {
|
||||
if ( tag->image == image )
|
||||
tag->image = NULL;
|
||||
}
|
||||
free ( image->name );
|
||||
free ( image->cmdline );
|
||||
uri_put ( image->uri );
|
||||
@ -260,12 +273,6 @@ int register_image ( struct image *image ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Avoid ending up with multiple "selected" images on
|
||||
* re-registration
|
||||
*/
|
||||
if ( image_find_selected() )
|
||||
image->flags &= ~IMAGE_SELECTED;
|
||||
|
||||
/* Add to image list */
|
||||
image_get ( image );
|
||||
image->flags |= IMAGE_REGISTERED;
|
||||
@ -311,7 +318,7 @@ void unregister_image ( struct image *image ) {
|
||||
struct image * find_image ( const char *name ) {
|
||||
struct image *image;
|
||||
|
||||
list_for_each_entry ( image, &images, list ) {
|
||||
for_each_image ( image ) {
|
||||
if ( strcmp ( image->name, name ) == 0 )
|
||||
return image;
|
||||
}
|
||||
@ -319,6 +326,23 @@ struct image * find_image ( const char *name ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find image by tag
|
||||
*
|
||||
* @v tag Image tag
|
||||
* @ret image Executable image, or NULL
|
||||
*/
|
||||
struct image * find_image_tag ( struct image_tag *tag ) {
|
||||
struct image *image;
|
||||
|
||||
for_each_image ( image ) {
|
||||
if ( tag->image == image )
|
||||
return image;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute image
|
||||
*
|
||||
@ -345,14 +369,13 @@ int image_exec ( struct image *image ) {
|
||||
if ( image->uri )
|
||||
churi ( image->uri );
|
||||
|
||||
/* Preserve record of any currently-running image */
|
||||
saved_current_image = current_image;
|
||||
/* Set as currently running image */
|
||||
saved_current_image = image_tag ( image, ¤t_image );
|
||||
|
||||
/* Take out a temporary reference to the image. This allows
|
||||
* the image to unregister itself if necessary, without
|
||||
* automatically freeing itself.
|
||||
/* Take out a temporary reference to the image, so that it
|
||||
* does not get freed when temporarily unregistered.
|
||||
*/
|
||||
current_image = image_get ( image );
|
||||
image_get ( image );
|
||||
|
||||
/* Check that this image can be executed */
|
||||
if ( ! ( image->type && image->type->exec ) ) {
|
||||
@ -370,6 +393,9 @@ int image_exec ( struct image *image ) {
|
||||
/* Record boot attempt */
|
||||
syslog ( LOG_NOTICE, "Executing \"%s\"\n", image->name );
|
||||
|
||||
/* Temporarily unregister the image during its execution */
|
||||
unregister_image ( image );
|
||||
|
||||
/* Try executing the image */
|
||||
if ( ( rc = image->type->exec ( image ) ) != 0 ) {
|
||||
DBGC ( image, "IMAGE %s could not execute: %s\n",
|
||||
@ -386,6 +412,10 @@ int image_exec ( struct image *image ) {
|
||||
image->name, strerror ( rc ) );
|
||||
}
|
||||
|
||||
/* Re-register image (unless due to be replaced) */
|
||||
if ( ! image->replacement )
|
||||
register_image ( image );
|
||||
|
||||
/* Pick up replacement image before we drop the original
|
||||
* image's temporary reference. The replacement image must
|
||||
* already be registered, so we don't need to hold a temporary
|
||||
@ -412,7 +442,7 @@ int image_exec ( struct image *image ) {
|
||||
image_put ( image );
|
||||
|
||||
/* Restore previous currently-running image */
|
||||
current_image = saved_current_image;
|
||||
image_tag ( saved_current_image, ¤t_image );
|
||||
|
||||
/* Reset current working directory */
|
||||
churi ( old_cwuri );
|
||||
@ -435,7 +465,7 @@ int image_exec ( struct image *image ) {
|
||||
* registered until the currently-executing image returns.
|
||||
*/
|
||||
int image_replace ( struct image *replacement ) {
|
||||
struct image *image = current_image;
|
||||
struct image *image = current_image.image;
|
||||
int rc;
|
||||
|
||||
/* Sanity check */
|
||||
@ -471,37 +501,17 @@ int image_replace ( struct image *replacement ) {
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int image_select ( struct image *image ) {
|
||||
struct image *tmp;
|
||||
|
||||
/* Unselect all other images */
|
||||
for_each_image ( tmp )
|
||||
tmp->flags &= ~IMAGE_SELECTED;
|
||||
|
||||
/* Check that this image can be executed */
|
||||
if ( ! ( image->type && image->type->exec ) )
|
||||
return -ENOEXEC;
|
||||
|
||||
/* Mark image as selected */
|
||||
image->flags |= IMAGE_SELECTED;
|
||||
image_tag ( image, &selected_image );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find selected image
|
||||
*
|
||||
* @ret image Executable image, or NULL
|
||||
*/
|
||||
struct image * image_find_selected ( void ) {
|
||||
struct image *image;
|
||||
|
||||
for_each_image ( image ) {
|
||||
if ( image->flags & IMAGE_SELECTED )
|
||||
return image;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change image trust requirement
|
||||
*
|
||||
@ -569,3 +579,33 @@ struct image * image_memory ( const char *name, userptr_t data, size_t len ) {
|
||||
err_alloc_image:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find argument within image command line
|
||||
*
|
||||
* @v image Image
|
||||
* @v key Argument search key (including trailing delimiter)
|
||||
* @ret value Argument value, or NULL if not found
|
||||
*/
|
||||
const char * image_argument ( struct image *image, const char *key ) {
|
||||
const char *cmdline = image->cmdline;
|
||||
const char *search;
|
||||
const char *match;
|
||||
const char *next;
|
||||
|
||||
/* Find argument */
|
||||
for ( search = cmdline ; search ; search = next ) {
|
||||
|
||||
/* Find next occurrence, if any */
|
||||
match = strstr ( search, key );
|
||||
if ( ! match )
|
||||
break;
|
||||
next = ( match + strlen ( key ) );
|
||||
|
||||
/* Check preceding delimiter, if any */
|
||||
if ( ( match == cmdline ) || isspace ( match[-1] ) )
|
||||
return next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Form parameters
|
||||
* Request parameters
|
||||
*
|
||||
*/
|
||||
|
||||
@ -37,7 +37,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
static LIST_HEAD ( parameters );
|
||||
|
||||
/**
|
||||
* Free form parameter list
|
||||
* Free request parameter list
|
||||
*
|
||||
* @v refcnt Reference count
|
||||
*/
|
||||
@ -60,7 +60,7 @@ static void free_parameters ( struct refcnt *refcnt ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Find form parameter list by name
|
||||
* Find request parameter list by name
|
||||
*
|
||||
* @v name Parameter list name (may be NULL)
|
||||
* @ret params Parameter list, or NULL if not found
|
||||
@ -78,7 +78,7 @@ struct parameters * find_parameters ( const char *name ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create form parameter list
|
||||
* Create request parameter list
|
||||
*
|
||||
* @v name Parameter list name (may be NULL)
|
||||
* @ret params Parameter list, or NULL on failure
|
||||
@ -118,15 +118,17 @@ struct parameters * create_parameters ( const char *name ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add form parameter
|
||||
* Add request parameter
|
||||
*
|
||||
* @v params Parameter list
|
||||
* @v key Parameter key
|
||||
* @v value Parameter value
|
||||
* @v flags Parameter flags
|
||||
* @ret param Parameter, or NULL on failure
|
||||
*/
|
||||
struct parameter * add_parameter ( struct parameters *params,
|
||||
const char *key, const char *value ) {
|
||||
const char *key, const char *value,
|
||||
unsigned int flags ) {
|
||||
struct parameter *param;
|
||||
size_t key_len;
|
||||
size_t value_len;
|
||||
@ -147,11 +149,14 @@ struct parameter * add_parameter ( struct parameters *params,
|
||||
param->key = key_copy;
|
||||
strcpy ( value_copy, value );
|
||||
param->value = value_copy;
|
||||
param->flags = flags;
|
||||
|
||||
/* Add to list of parameters */
|
||||
list_add_tail ( ¶m->list, ¶ms->entries );
|
||||
|
||||
DBGC ( params, "PARAMS \"%s\" added \"%s\"=\"%s\"\n",
|
||||
params->name, param->key, param->value );
|
||||
DBGC ( params, "PARAMS \"%s\" added \"%s\"=\"%s\"%s%s\n",
|
||||
params->name, param->key, param->value,
|
||||
( ( param->flags & PARAMETER_FORM ) ? " (form)" : "" ),
|
||||
( ( param->flags & PARAMETER_HEADER ) ? " (header)" : "" ) );
|
||||
return param;
|
||||
}
|
||||
|
||||
@ -302,7 +302,7 @@ int parse_autovivified_setting ( char *text, struct named_setting *setting ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse form parameter list name
|
||||
* Parse request parameter list name
|
||||
*
|
||||
* @v text Text
|
||||
* @ret params Parameter list
|
||||
|
||||
@ -589,6 +589,32 @@ int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check ASN.1 OID-identified algorithm
|
||||
*
|
||||
* @v cursor ASN.1 object cursor
|
||||
* @v expected Expected algorithm
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int asn1_check_algorithm ( const struct asn1_cursor *cursor,
|
||||
struct asn1_algorithm *expected ) {
|
||||
struct asn1_algorithm *actual;
|
||||
int rc;
|
||||
|
||||
/* Parse algorithm */
|
||||
if ( ( rc = asn1_algorithm ( cursor, &actual ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Check algorithm matches */
|
||||
if ( actual != expected ) {
|
||||
DBGC ( cursor, "ASN1 %p algorithm %s does not match %s\n",
|
||||
cursor, actual->name, expected->name );
|
||||
return -ENOTTY_ALGORITHM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse ASN.1 GeneralizedTime
|
||||
*
|
||||
|
||||
@ -51,59 +51,33 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
__einfo_uniqify ( EINFO_EPIPE, 0x02, "Adaptive proportion test failed" )
|
||||
|
||||
/**
|
||||
* Calculate cutoff value for the repetition count test
|
||||
* Initialise repetition count test
|
||||
*
|
||||
* @ret cutoff Cutoff value
|
||||
*
|
||||
* This is the cutoff value for the Repetition Count Test defined in
|
||||
* ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.2.
|
||||
* @v source Entropy source
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) unsigned int
|
||||
repetition_count_cutoff ( void ) {
|
||||
double max_repetitions;
|
||||
unsigned int cutoff;
|
||||
static void repetition_count_test_init ( struct entropy_source *source ) {
|
||||
struct entropy_repetition_count_test *test =
|
||||
&source->repetition_count_test;
|
||||
|
||||
/* The cutoff formula for the repetition test is:
|
||||
*
|
||||
* C = ( 1 + ( -log2(W) / H_min ) )
|
||||
*
|
||||
* where W is set at 2^(-30) (in ANS X9.82 Part 2 (October
|
||||
* 2011 Draft) Section 8.5.2.1.3.1).
|
||||
*/
|
||||
max_repetitions = ( 1 + ( MIN_ENTROPY ( 30 ) /
|
||||
min_entropy_per_sample() ) );
|
||||
|
||||
/* Round up to a whole number of repetitions. We don't have
|
||||
* the ceil() function available, so do the rounding by hand.
|
||||
*/
|
||||
cutoff = max_repetitions;
|
||||
if ( cutoff < max_repetitions )
|
||||
cutoff++;
|
||||
linker_assert ( ( cutoff >= max_repetitions ), rounding_error );
|
||||
|
||||
/* Floating-point operations are not allowed in iPXE since we
|
||||
* never set up a suitable environment. Abort the build
|
||||
* unless the calculated number of repetitions is a
|
||||
* compile-time constant.
|
||||
*/
|
||||
linker_assert ( __builtin_constant_p ( cutoff ),
|
||||
repetition_count_cutoff_not_constant );
|
||||
|
||||
return cutoff;
|
||||
/* Sanity checks */
|
||||
assert ( test->repetition_count == 0 );
|
||||
assert ( test->cutoff > 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform repetition count test
|
||||
*
|
||||
* @v source Entropy source
|
||||
* @v sample Noise sample
|
||||
* @ret rc Return status code
|
||||
*
|
||||
* This is the Repetition Count Test defined in ANS X9.82 Part 2
|
||||
* (October 2011 Draft) Section 8.5.2.1.2.
|
||||
*/
|
||||
static int repetition_count_test ( noise_sample_t sample ) {
|
||||
static noise_sample_t most_recent_sample;
|
||||
static unsigned int repetition_count = 0;
|
||||
static int repetition_count_test ( struct entropy_source *source,
|
||||
noise_sample_t sample ) {
|
||||
struct entropy_repetition_count_test *test =
|
||||
&source->repetition_count_test;
|
||||
|
||||
/* A = the most recently seen sample value
|
||||
* B = the number of times that value A has been seen in a row
|
||||
@ -116,158 +90,71 @@ static int repetition_count_test ( noise_sample_t sample ) {
|
||||
* the initial value of most_recent_sample is treated as being
|
||||
* undefined.)
|
||||
*/
|
||||
if ( ( sample == most_recent_sample ) && ( repetition_count > 0 ) ) {
|
||||
if ( ( sample == test->most_recent_sample ) &&
|
||||
( test->repetition_count > 0 ) ) {
|
||||
|
||||
/* a) If the new sample = A, then B is incremented by one. */
|
||||
repetition_count++;
|
||||
test->repetition_count++;
|
||||
|
||||
/* i. If B >= C, then an error condition is raised
|
||||
* due to a failure of the test
|
||||
*/
|
||||
if ( repetition_count >= repetition_count_cutoff() )
|
||||
if ( test->repetition_count >= test->cutoff ) {
|
||||
DBGC ( source, "ENTROPY %s excessively repeated "
|
||||
"value %d (%d/%d)\n", source->name, sample,
|
||||
test->repetition_count, test->cutoff );
|
||||
return -EPIPE_REPETITION_COUNT_TEST;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* b) Else:
|
||||
* i. A = new sample
|
||||
*/
|
||||
most_recent_sample = sample;
|
||||
test->most_recent_sample = sample;
|
||||
|
||||
/* ii. B = 1 */
|
||||
repetition_count = 1;
|
||||
test->repetition_count = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Window size for the adaptive proportion test
|
||||
* Initialise adaptive proportion test
|
||||
*
|
||||
* ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.1.1 allows
|
||||
* five possible window sizes: 16, 64, 256, 4096 and 65536.
|
||||
*
|
||||
* We expect to generate relatively few (<256) entropy samples during
|
||||
* a typical iPXE run; the use of a large window size would mean that
|
||||
* the test would never complete a single cycle. We use a window size
|
||||
* of 64, which is the smallest window size that permits values of
|
||||
* H_min down to one bit per sample.
|
||||
* @v source Entropy source
|
||||
*/
|
||||
#define ADAPTIVE_PROPORTION_WINDOW_SIZE 64
|
||||
static void adaptive_proportion_test_init ( struct entropy_source *source ) {
|
||||
struct entropy_adaptive_proportion_test *test =
|
||||
&source->adaptive_proportion_test;
|
||||
|
||||
/**
|
||||
* Combine adaptive proportion test window size and min-entropy
|
||||
*
|
||||
* @v n N (window size)
|
||||
* @v h H (min-entropy)
|
||||
* @ret n_h (N,H) combined value
|
||||
*/
|
||||
#define APC_N_H( n, h ) ( ( (n) << 8 ) | (h) )
|
||||
/* Sanity checks */
|
||||
assert ( test->sample_count == 0 );
|
||||
assert ( test->repetition_count == 0 );
|
||||
assert ( test->cutoff > 0 );
|
||||
|
||||
/**
|
||||
* Define a row of the adaptive proportion cutoff table
|
||||
*
|
||||
* @v h H (min-entropy)
|
||||
* @v c16 Cutoff for N=16
|
||||
* @v c64 Cutoff for N=64
|
||||
* @v c256 Cutoff for N=256
|
||||
* @v c4096 Cutoff for N=4096
|
||||
* @v c65536 Cutoff for N=65536
|
||||
*/
|
||||
#define APC_TABLE_ROW( h, c16, c64, c256, c4096, c65536) \
|
||||
case APC_N_H ( 16, h ) : return c16; \
|
||||
case APC_N_H ( 64, h ) : return c64; \
|
||||
case APC_N_H ( 256, h ) : return c256; \
|
||||
case APC_N_H ( 4096, h ) : return c4096; \
|
||||
case APC_N_H ( 65536, h ) : return c65536;
|
||||
|
||||
/** Value used to represent "N/A" in adaptive proportion cutoff table */
|
||||
#define APC_NA 0
|
||||
|
||||
/**
|
||||
* Look up value in adaptive proportion test cutoff table
|
||||
*
|
||||
* @v n N (window size)
|
||||
* @v h H (min-entropy)
|
||||
* @ret cutoff Cutoff
|
||||
*
|
||||
* This is the table of cutoff values defined in ANS X9.82 Part 2
|
||||
* (October 2011 Draft) Section 8.5.2.1.3.1.2.
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) unsigned int
|
||||
adaptive_proportion_cutoff_lookup ( unsigned int n, unsigned int h ) {
|
||||
switch ( APC_N_H ( n, h ) ) {
|
||||
APC_TABLE_ROW ( 1, APC_NA, 51, 168, 2240, 33537 );
|
||||
APC_TABLE_ROW ( 2, APC_NA, 35, 100, 1193, 17053 );
|
||||
APC_TABLE_ROW ( 3, 10, 24, 61, 643, 8705 );
|
||||
APC_TABLE_ROW ( 4, 8, 16, 38, 354, 4473 );
|
||||
APC_TABLE_ROW ( 5, 6, 12, 25, 200, 2321 );
|
||||
APC_TABLE_ROW ( 6, 5, 9, 17, 117, 1220 );
|
||||
APC_TABLE_ROW ( 7, 4, 7, 15, 71, 653 );
|
||||
APC_TABLE_ROW ( 8, 4, 5, 9, 45, 358 );
|
||||
APC_TABLE_ROW ( 9, 3, 4, 7, 30, 202 );
|
||||
APC_TABLE_ROW ( 10, 3, 4, 5, 21, 118 );
|
||||
APC_TABLE_ROW ( 11, 2, 3, 4, 15, 71 );
|
||||
APC_TABLE_ROW ( 12, 2, 3, 4, 11, 45 );
|
||||
APC_TABLE_ROW ( 13, 2, 2, 3, 9, 30 );
|
||||
APC_TABLE_ROW ( 14, 2, 2, 3, 7, 21 );
|
||||
APC_TABLE_ROW ( 15, 1, 2, 2, 6, 15 );
|
||||
APC_TABLE_ROW ( 16, 1, 2, 2, 5, 11 );
|
||||
APC_TABLE_ROW ( 17, 1, 1, 2, 4, 9 );
|
||||
APC_TABLE_ROW ( 18, 1, 1, 2, 4, 7 );
|
||||
APC_TABLE_ROW ( 19, 1, 1, 1, 3, 6 );
|
||||
APC_TABLE_ROW ( 20, 1, 1, 1, 3, 5 );
|
||||
default:
|
||||
return APC_NA;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate cutoff value for the adaptive proportion test
|
||||
*
|
||||
* @ret cutoff Cutoff value
|
||||
*
|
||||
* This is the cutoff value for the Adaptive Proportion Test defined
|
||||
* in ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.1.2.
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) unsigned int
|
||||
adaptive_proportion_cutoff ( void ) {
|
||||
unsigned int h;
|
||||
unsigned int n;
|
||||
unsigned int cutoff;
|
||||
|
||||
/* Look up cutoff value in cutoff table */
|
||||
n = ADAPTIVE_PROPORTION_WINDOW_SIZE;
|
||||
h = ( min_entropy_per_sample() / MIN_ENTROPY_SCALE );
|
||||
cutoff = adaptive_proportion_cutoff_lookup ( n, h );
|
||||
|
||||
/* Fail unless cutoff value is a build-time constant */
|
||||
linker_assert ( __builtin_constant_p ( cutoff ),
|
||||
adaptive_proportion_cutoff_not_constant );
|
||||
|
||||
/* Fail if cutoff value is N/A */
|
||||
linker_assert ( ( cutoff != APC_NA ),
|
||||
adaptive_proportion_cutoff_not_applicable );
|
||||
|
||||
return cutoff;
|
||||
/* Ensure that a new test run starts immediately */
|
||||
test->sample_count = ADAPTIVE_PROPORTION_WINDOW_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform adaptive proportion test
|
||||
*
|
||||
* @v source Entropy source
|
||||
* @v sample Noise sample
|
||||
* @ret rc Return status code
|
||||
*
|
||||
* This is the Adaptive Proportion Test for the Most Common Value
|
||||
* defined in ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.
|
||||
*/
|
||||
static int adaptive_proportion_test ( noise_sample_t sample ) {
|
||||
static noise_sample_t current_counted_sample;
|
||||
static unsigned int sample_count = ADAPTIVE_PROPORTION_WINDOW_SIZE;
|
||||
static unsigned int repetition_count;
|
||||
static int adaptive_proportion_test ( struct entropy_source *source,
|
||||
noise_sample_t sample ) {
|
||||
struct entropy_adaptive_proportion_test *test =
|
||||
&source->adaptive_proportion_test;
|
||||
|
||||
/* A = the sample value currently being counted
|
||||
* B = the number of samples examined in this run of the test so far
|
||||
* S = the number of samples examined in this run of the test so far
|
||||
* N = the total number of samples that must be observed in
|
||||
* one run of the test, also known as the "window size" of
|
||||
* the test
|
||||
@ -284,37 +171,41 @@ static int adaptive_proportion_test ( noise_sample_t sample ) {
|
||||
*/
|
||||
|
||||
/* 2. If S = N, then a new run of the test begins: */
|
||||
if ( sample_count == ADAPTIVE_PROPORTION_WINDOW_SIZE ) {
|
||||
if ( test->sample_count == ADAPTIVE_PROPORTION_WINDOW_SIZE ) {
|
||||
|
||||
/* a. A = the current sample */
|
||||
current_counted_sample = sample;
|
||||
test->current_counted_sample = sample;
|
||||
|
||||
/* b. S = 0 */
|
||||
sample_count = 0;
|
||||
test->sample_count = 0;
|
||||
|
||||
/* c. B = 0 */
|
||||
repetition_count = 0;
|
||||
test->repetition_count = 0;
|
||||
|
||||
} else {
|
||||
|
||||
/* Else: (the test is already running)
|
||||
* a. S = S + 1
|
||||
*/
|
||||
sample_count++;
|
||||
test->sample_count++;
|
||||
|
||||
/* b. If A = the current sample, then: */
|
||||
if ( sample == current_counted_sample ) {
|
||||
if ( sample == test->current_counted_sample ) {
|
||||
|
||||
/* i. B = B + 1 */
|
||||
repetition_count++;
|
||||
test->repetition_count++;
|
||||
|
||||
/* ii. If S (sic) > C then raise an error
|
||||
* condition, because the test has
|
||||
* detected a failure
|
||||
*/
|
||||
if ( repetition_count > adaptive_proportion_cutoff() )
|
||||
if ( test->repetition_count > test->cutoff ) {
|
||||
DBGC ( source, "ENTROPY %s excessively "
|
||||
"repeated value %d (%d/%d)\n",
|
||||
source->name, sample,
|
||||
test->repetition_count, test->cutoff );
|
||||
return -EPIPE_ADAPTIVE_PROPORTION_TEST;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,62 +215,180 @@ static int adaptive_proportion_test ( noise_sample_t sample ) {
|
||||
/**
|
||||
* Get entropy sample
|
||||
*
|
||||
* @v source Entropy source
|
||||
* @ret entropy Entropy sample
|
||||
* @ret rc Return status code
|
||||
*
|
||||
* This is the GetEntropy function defined in ANS X9.82 Part 2
|
||||
* (October 2011 Draft) Section 6.5.1.
|
||||
*/
|
||||
static int get_entropy ( entropy_sample_t *entropy ) {
|
||||
static int rc = 0;
|
||||
static int get_entropy ( struct entropy_source *source,
|
||||
entropy_sample_t *entropy ) {
|
||||
noise_sample_t noise;
|
||||
int rc;
|
||||
|
||||
/* Any failure is permanent */
|
||||
if ( rc != 0 )
|
||||
return rc;
|
||||
if ( ( rc = source->rc ) != 0 )
|
||||
goto err_broken;
|
||||
|
||||
/* Get noise sample */
|
||||
if ( ( rc = get_noise ( &noise ) ) != 0 )
|
||||
return rc;
|
||||
if ( ( rc = get_noise ( source, &noise ) ) != 0 )
|
||||
goto err_get_noise;
|
||||
|
||||
/* Perform Repetition Count Test and Adaptive Proportion Test
|
||||
* as mandated by ANS X9.82 Part 2 (October 2011 Draft)
|
||||
* Section 8.5.2.1.1.
|
||||
*/
|
||||
if ( ( rc = repetition_count_test ( noise ) ) != 0 )
|
||||
return rc;
|
||||
if ( ( rc = adaptive_proportion_test ( noise ) ) != 0 )
|
||||
return rc;
|
||||
if ( ( rc = repetition_count_test ( source, noise ) ) != 0 )
|
||||
goto err_repetition_count_test;
|
||||
if ( ( rc = adaptive_proportion_test ( source, noise ) ) != 0 )
|
||||
goto err_adaptive_proportion_test;
|
||||
|
||||
/* We do not use any optional conditioning component */
|
||||
*entropy = noise;
|
||||
|
||||
return 0;
|
||||
|
||||
err_adaptive_proportion_test:
|
||||
err_repetition_count_test:
|
||||
err_get_noise:
|
||||
source->rc = rc;
|
||||
err_broken:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate number of samples required for startup tests
|
||||
* Initialise startup test
|
||||
*
|
||||
* @ret num_samples Number of samples required
|
||||
*
|
||||
* ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.5 requires
|
||||
* that at least one full cycle of the continuous tests must be
|
||||
* performed at start-up.
|
||||
* @v source Entropy source
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) unsigned int
|
||||
startup_test_count ( void ) {
|
||||
unsigned int num_samples;
|
||||
static void startup_test_init ( struct entropy_source *source ) {
|
||||
struct entropy_startup_test *test = &source->startup_test;
|
||||
|
||||
/* At least max(N,C) samples shall be generated by the noise
|
||||
* source for start-up testing.
|
||||
*/
|
||||
num_samples = repetition_count_cutoff();
|
||||
if ( num_samples < adaptive_proportion_cutoff() )
|
||||
num_samples = adaptive_proportion_cutoff();
|
||||
linker_assert ( __builtin_constant_p ( num_samples ),
|
||||
startup_test_count_not_constant );
|
||||
/* Sanity check */
|
||||
assert ( test->tested == 0 );
|
||||
assert ( test->count > 0 );
|
||||
}
|
||||
|
||||
return num_samples;
|
||||
/**
|
||||
* Perform startup test
|
||||
*
|
||||
* @v source Entropy source
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int startup_test ( struct entropy_source *source ) {
|
||||
struct entropy_startup_test *test = &source->startup_test;
|
||||
entropy_sample_t sample;
|
||||
int rc;
|
||||
|
||||
/* Perform mandatory number of startup tests */
|
||||
for ( ; test->tested < test->count ; test->tested++ ) {
|
||||
if ( ( rc = get_entropy ( source, &sample ) ) != 0 ) {
|
||||
DBGC ( source, "ENTROPY %s failed: %s\n",
|
||||
source->name, strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable entropy gathering
|
||||
*
|
||||
* @v source Entropy source
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int entropy_enable ( struct entropy_source *source ) {
|
||||
int rc;
|
||||
|
||||
/* Refuse to enable a previously failed source */
|
||||
if ( ( rc = source->rc ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Enable entropy source */
|
||||
if ( ( rc = source->enable() ) != 0 ) {
|
||||
DBGC ( source, "ENTROPY %s could not enable: %s\n",
|
||||
source->name, strerror ( rc ) );
|
||||
source->rc = rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
assert ( source->min_entropy_per_sample > 0 );
|
||||
|
||||
/* Initialise test state if this source has not previously been used */
|
||||
if ( source->startup_test.tested == 0 ) {
|
||||
repetition_count_test_init ( source );
|
||||
adaptive_proportion_test_init ( source );
|
||||
startup_test_init ( source );
|
||||
}
|
||||
|
||||
DBGC ( source, "ENTROPY %s enabled\n", source->name );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable and test entropy source
|
||||
*
|
||||
* @v source Entropy source
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int entropy_enable_and_test ( struct entropy_source *source ) {
|
||||
int rc;
|
||||
|
||||
/* Enable source */
|
||||
if ( ( rc = entropy_enable ( source ) ) != 0 )
|
||||
goto err_enable;
|
||||
|
||||
/* Test source */
|
||||
if ( ( rc = startup_test ( source ) ) != 0 )
|
||||
goto err_test;
|
||||
|
||||
DBGC ( source, "ENTROPY %s passed %d startup tests\n",
|
||||
source->name, source->startup_test.count );
|
||||
return 0;
|
||||
|
||||
err_test:
|
||||
entropy_disable ( source );
|
||||
err_enable:
|
||||
assert ( source->rc == rc );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable first working entropy source
|
||||
*
|
||||
* @v source Entropy source to fill in
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int entropy_enable_working ( struct entropy_source **source ) {
|
||||
int rc;
|
||||
|
||||
/* Find the first working source */
|
||||
rc = -ENOENT;
|
||||
for_each_table_entry ( *source, ENTROPY_SOURCES ) {
|
||||
if ( ( rc = entropy_enable_and_test ( *source ) ) == 0 )
|
||||
return 0;
|
||||
}
|
||||
|
||||
DBGC ( *source, "ENTROPY has no working sources: %s\n",
|
||||
strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable entropy gathering
|
||||
*
|
||||
* @v source Entropy source
|
||||
*/
|
||||
void entropy_disable ( struct entropy_source *source ) {
|
||||
|
||||
/* Disable entropy gathering, if applicable */
|
||||
if ( source->disable )
|
||||
source->disable();
|
||||
|
||||
DBGC ( source, "ENTROPY %s disabled\n", source->name );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -402,7 +411,7 @@ static uint32_t make_next_nonce ( void ) {
|
||||
/**
|
||||
* Obtain entropy input temporary buffer
|
||||
*
|
||||
* @v num_samples Number of entropy samples
|
||||
* @v min_entropy Min-entropy required
|
||||
* @v tmp Temporary buffer
|
||||
* @v tmp_len Length of temporary buffer
|
||||
* @ret rc Return status code
|
||||
@ -412,47 +421,41 @@ static uint32_t make_next_nonce ( void ) {
|
||||
* and condensing each entropy source output after each GetEntropy
|
||||
* call) as defined in ANS X9.82 Part 4 (April 2011 Draft) Section
|
||||
* 13.3.4.2.
|
||||
*
|
||||
* To minimise code size, the number of samples required is calculated
|
||||
* at compilation time.
|
||||
*/
|
||||
int get_entropy_input_tmp ( unsigned int num_samples, uint8_t *tmp,
|
||||
int get_entropy_input_tmp ( min_entropy_t min_entropy, uint8_t *tmp,
|
||||
size_t tmp_len ) {
|
||||
static unsigned int startup_tested = 0;
|
||||
struct entropy_source *source;
|
||||
struct {
|
||||
uint32_t nonce;
|
||||
entropy_sample_t sample;
|
||||
} __attribute__ (( packed )) data;;
|
||||
uint8_t df_buf[tmp_len];
|
||||
min_entropy_t entropy_total;
|
||||
unsigned int num_samples;
|
||||
unsigned int i;
|
||||
int rc;
|
||||
|
||||
/* Enable entropy gathering */
|
||||
if ( ( rc = entropy_enable() ) != 0 )
|
||||
return rc;
|
||||
if ( ( rc = entropy_enable_working ( &source ) ) != 0 )
|
||||
goto err_enable_working;
|
||||
|
||||
/* Perform mandatory startup tests, if not yet performed */
|
||||
for ( ; startup_tested < startup_test_count() ; startup_tested++ ) {
|
||||
if ( ( rc = get_entropy ( &data.sample ) ) != 0 )
|
||||
goto err_get_entropy;
|
||||
}
|
||||
/* Sanity checks */
|
||||
assert ( source->startup_test.count > 0 );
|
||||
assert ( source->startup_test.tested >= source->startup_test.count );
|
||||
|
||||
/* 3. entropy_total = 0
|
||||
*
|
||||
* (Nothing to do; the number of entropy samples required has
|
||||
* already been precalculated.)
|
||||
*/
|
||||
/* 3. entropy_total = 0 */
|
||||
entropy_total = MIN_ENTROPY ( 0 );
|
||||
|
||||
/* 4. tmp = a fixed n-bit value, such as 0^n */
|
||||
memset ( tmp, 0, tmp_len );
|
||||
|
||||
/* 5. While ( entropy_total < min_entropy ) */
|
||||
while ( num_samples-- ) {
|
||||
for ( num_samples = 0 ; entropy_total < min_entropy ; num_samples++ ) {
|
||||
/* 5.1. ( status, entropy_bitstring, assessed_entropy )
|
||||
* = GetEntropy()
|
||||
* 5.2. If status indicates an error, return ( status, Null )
|
||||
*/
|
||||
if ( ( rc = get_entropy ( &data.sample ) ) != 0 )
|
||||
if ( ( rc = get_entropy ( source, &data.sample ) ) != 0 )
|
||||
goto err_get_entropy;
|
||||
|
||||
/* 5.3. nonce = MakeNextNonce() */
|
||||
@ -466,19 +469,26 @@ int get_entropy_input_tmp ( unsigned int num_samples, uint8_t *tmp,
|
||||
for ( i = 0 ; i < tmp_len ; i++ )
|
||||
tmp[i] ^= df_buf[i];
|
||||
|
||||
/* 5.5. entropy_total = entropy_total + assessed_entropy
|
||||
*
|
||||
* (Nothing to do; the number of entropy samples
|
||||
* required has already been precalculated.)
|
||||
*/
|
||||
/* 5.5. entropy_total = entropy_total + assessed_entropy */
|
||||
entropy_total += source->min_entropy_per_sample;
|
||||
}
|
||||
|
||||
/* Disable entropy gathering */
|
||||
entropy_disable();
|
||||
entropy_disable ( source );
|
||||
|
||||
DBGC ( source, "ENTROPY %s gathered %d bits in %d samples\n",
|
||||
source->name, ( min_entropy / MIN_ENTROPY_SCALE ), num_samples );
|
||||
return 0;
|
||||
|
||||
err_get_entropy:
|
||||
entropy_disable();
|
||||
entropy_disable ( source );
|
||||
assert ( source->rc == rc );
|
||||
err_enable_working:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Drag in objects via entropy_enable */
|
||||
REQUIRING_SYMBOL ( entropy_enable );
|
||||
|
||||
/* Drag in entropy configuration */
|
||||
REQUIRE_OBJECT ( config_entropy );
|
||||
|
||||
@ -164,7 +164,7 @@ static int rsa_parse_mod_exp ( struct asn1_cursor *modulus,
|
||||
int is_private;
|
||||
int rc;
|
||||
|
||||
/* Enter subjectPublicKeyInfo/RSAPrivateKey */
|
||||
/* Enter subjectPublicKeyInfo/privateKeyInfo/RSAPrivateKey */
|
||||
memcpy ( &cursor, raw, sizeof ( cursor ) );
|
||||
asn1_enter ( &cursor, ASN1_SEQUENCE );
|
||||
|
||||
@ -177,6 +177,23 @@ static int rsa_parse_mod_exp ( struct asn1_cursor *modulus,
|
||||
/* Skip version */
|
||||
asn1_skip_any ( &cursor );
|
||||
|
||||
/* Enter privateKey, if present */
|
||||
if ( asn1_check_algorithm ( &cursor,
|
||||
&rsa_encryption_algorithm ) == 0 ) {
|
||||
|
||||
/* Skip privateKeyAlgorithm */
|
||||
asn1_skip_any ( &cursor );
|
||||
|
||||
/* Enter privateKey */
|
||||
asn1_enter ( &cursor, ASN1_OCTET_STRING );
|
||||
|
||||
/* Enter RSAPrivateKey */
|
||||
asn1_enter ( &cursor, ASN1_SEQUENCE );
|
||||
|
||||
/* Skip version */
|
||||
asn1_skip ( &cursor, ASN1_INTEGER );
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Public key */
|
||||
|
||||
@ -609,6 +609,7 @@ static void scsicmd_read_capacity_cmd ( struct scsi_command *scsicmd,
|
||||
*/
|
||||
static void scsicmd_read_capacity_done ( struct scsi_command *scsicmd,
|
||||
int rc ) {
|
||||
struct scsi_device *scsidev = scsicmd->scsidev;
|
||||
struct scsi_read_capacity_private *priv = scsicmd_priv ( scsicmd );
|
||||
struct scsi_capacity_16 *capacity16 = &priv->capacity.capacity16;
|
||||
struct scsi_capacity_10 *capacity10 = &priv->capacity.capacity10;
|
||||
@ -645,6 +646,9 @@ static void scsicmd_read_capacity_done ( struct scsi_command *scsicmd,
|
||||
}
|
||||
capacity.max_count = -1U;
|
||||
|
||||
/* Allow transport layer to update capacity */
|
||||
block_capacity ( &scsidev->scsi, &capacity );
|
||||
|
||||
/* Return capacity to caller */
|
||||
block_capacity ( &scsicmd->block, &capacity );
|
||||
|
||||
|
||||
@ -98,8 +98,16 @@ static void eisa_remove ( struct eisa_device *eisa ) {
|
||||
static int eisabus_probe ( struct root_device *rootdev ) {
|
||||
struct eisa_device *eisa = NULL;
|
||||
unsigned int slot;
|
||||
uint8_t system;
|
||||
int rc;
|
||||
|
||||
/* Check for EISA system board */
|
||||
system = inb ( EISA_VENDOR_ID );
|
||||
if ( system & 0x80 ) {
|
||||
DBG ( "No EISA system board (read %02x)\n", system );
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for ( slot = EISA_MIN_SLOT ; slot <= EISA_MAX_SLOT ; slot++ ) {
|
||||
/* Allocate struct eisa_device */
|
||||
if ( ! eisa )
|
||||
|
||||
@ -205,6 +205,7 @@ int pci_read_config ( struct pci_device *pci ) {
|
||||
pci_read_config_dword ( pci, PCI_REVISION, &tmp );
|
||||
pci->class = ( tmp >> 8 );
|
||||
pci_read_config_byte ( pci, PCI_INTERRUPT_LINE, &pci->irq );
|
||||
pci_read_config_byte ( pci, PCI_HEADER_TYPE, &pci->hdrtype );
|
||||
pci_read_bases ( pci );
|
||||
|
||||
/* Initialise generic device component */
|
||||
|
||||
@ -2647,6 +2647,7 @@ static struct pci_device_id golan_nics[] = {
|
||||
PCI_ROM ( 0x15b3, 0x1021, "ConnectX-7", "ConnectX-7 HCA driver, DevID 4129", 0 ),
|
||||
PCI_ROM ( 0x15b3, 0xa2d2, "BlueField", "BlueField integrated ConnectX-5 network controller HCA driver, DevID 41682", 0 ),
|
||||
PCI_ROM ( 0x15b3, 0xa2d6, "BlueField-2", "BlueField-2 network controller HCA driver, DevID 41686", 0 ),
|
||||
PCI_ROM ( 0x15b3, 0xa2dc, "BlueField-3", "BlueField-3 network controller HCA driver, DevID 41692", 0 ),
|
||||
};
|
||||
|
||||
struct pci_driver golan_driver __pci_driver = {
|
||||
|
||||
@ -222,7 +222,7 @@ static int nii_pci_open ( struct nii_nic *nii ) {
|
||||
|
||||
/* Locate PCI I/O protocol */
|
||||
if ( ( rc = efi_locate_device ( device, &efi_pci_io_protocol_guid,
|
||||
&pci_device ) ) != 0 ) {
|
||||
&pci_device, 0 ) ) != 0 ) {
|
||||
DBGC ( nii, "NII %s could not locate PCI I/O protocol: %s\n",
|
||||
nii->dev.name, strerror ( rc ) );
|
||||
goto err_locate;
|
||||
|
||||
@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#include <ipxe/efi/efi.h>
|
||||
#include <ipxe/efi/efi_driver.h>
|
||||
#include <ipxe/efi/efi_snp.h>
|
||||
#include <ipxe/efi/efi_utils.h>
|
||||
#include "snpnet.h"
|
||||
#include "nii.h"
|
||||
|
||||
@ -40,34 +41,60 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
* Check to see if driver supports a device
|
||||
*
|
||||
* @v device EFI device handle
|
||||
* @v protocol Protocol GUID
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int snp_supported ( EFI_HANDLE device ) {
|
||||
static int snp_nii_supported ( EFI_HANDLE device, EFI_GUID *protocol ) {
|
||||
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
||||
EFI_HANDLE parent;
|
||||
EFI_STATUS efirc;
|
||||
int rc;
|
||||
|
||||
/* Check that this is not a device we are providing ourselves */
|
||||
if ( find_snpdev ( device ) != NULL ) {
|
||||
DBGCP ( device, "SNP %s is provided by this binary\n",
|
||||
DBGCP ( device, "HANDLE %s is provided by this binary\n",
|
||||
efi_handle_name ( device ) );
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/* Test for presence of simple network protocol */
|
||||
if ( ( efirc = bs->OpenProtocol ( device,
|
||||
&efi_simple_network_protocol_guid,
|
||||
/* Test for presence of protocol */
|
||||
if ( ( efirc = bs->OpenProtocol ( device, protocol,
|
||||
NULL, efi_image_handle, device,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL))!=0){
|
||||
DBGCP ( device, "SNP %s is not an SNP device\n",
|
||||
efi_handle_name ( device ) );
|
||||
DBGCP ( device, "HANDLE %s is not a %s device\n",
|
||||
efi_handle_name ( device ),
|
||||
efi_guid_ntoa ( protocol ) );
|
||||
return -EEFI ( efirc );
|
||||
}
|
||||
DBGC ( device, "SNP %s is an SNP device\n",
|
||||
efi_handle_name ( device ) );
|
||||
|
||||
/* Check that there are no instances of this protocol further
|
||||
* up this device path.
|
||||
*/
|
||||
if ( ( rc = efi_locate_device ( device, protocol,
|
||||
&parent, 1 ) ) == 0 ) {
|
||||
DBGC2 ( device, "HANDLE %s has %s-supporting parent ",
|
||||
efi_handle_name ( device ),
|
||||
efi_guid_ntoa ( protocol ) );
|
||||
DBGC2 ( device, "%s\n", efi_handle_name ( parent ) );
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
DBGC ( device, "HANDLE %s is a %s device\n",
|
||||
efi_handle_name ( device ), efi_guid_ntoa ( protocol ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if driver supports a device
|
||||
*
|
||||
* @v device EFI device handle
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int snp_supported ( EFI_HANDLE device ) {
|
||||
|
||||
return snp_nii_supported ( device, &efi_simple_network_protocol_guid );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if driver supports a device
|
||||
*
|
||||
@ -75,29 +102,8 @@ static int snp_supported ( EFI_HANDLE device ) {
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int nii_supported ( EFI_HANDLE device ) {
|
||||
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
||||
EFI_STATUS efirc;
|
||||
|
||||
/* Check that this is not a device we are providing ourselves */
|
||||
if ( find_snpdev ( device ) != NULL ) {
|
||||
DBGCP ( device, "NII %s is provided by this binary\n",
|
||||
efi_handle_name ( device ) );
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/* Test for presence of NII protocol */
|
||||
if ( ( efirc = bs->OpenProtocol ( device,
|
||||
&efi_nii31_protocol_guid,
|
||||
NULL, efi_image_handle, device,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL))!=0){
|
||||
DBGCP ( device, "NII %s is not an NII device\n",
|
||||
efi_handle_name ( device ) );
|
||||
return -EEFI ( efirc );
|
||||
}
|
||||
DBGC ( device, "NII %s is an NII device\n",
|
||||
efi_handle_name ( device ) );
|
||||
|
||||
return 0;
|
||||
return snp_nii_supported ( device, &efi_nii31_protocol_guid );
|
||||
}
|
||||
|
||||
/** EFI SNP driver */
|
||||
|
||||
@ -80,7 +80,7 @@ static int chained_locate ( struct chained_protocol *chained ) {
|
||||
|
||||
/* Locate handle supporting this protocol */
|
||||
if ( ( rc = efi_locate_device ( device, chained->protocol,
|
||||
&parent ) ) != 0 ) {
|
||||
&parent, 0 ) ) != 0 ) {
|
||||
DBGC ( device, "CHAINED %s does not support %s: %s\n",
|
||||
efi_handle_name ( device ),
|
||||
efi_guid_ntoa ( chained->protocol ), strerror ( rc ) );
|
||||
|
||||
@ -290,6 +290,18 @@ static int intel_reset ( struct intel_nic *intel ) {
|
||||
pba, readl ( intel->regs + INTEL_PBA ) );
|
||||
}
|
||||
|
||||
/* The Intel I210's packet buffer size registers reset only on
|
||||
* power up. If an operating system changes these but then
|
||||
* the computer recieves a reset signal without losing power,
|
||||
* the registers will stay the same (but be incompatible with
|
||||
* other register defaults), thus making the device unable to
|
||||
* pass traffic.
|
||||
*/
|
||||
if ( intel->flags & INTEL_PBSIZE_RST ) {
|
||||
writel ( INTEL_RXPBS_I210, intel->regs + INTEL_RXPBS );
|
||||
writel ( INTEL_TXPBS_I210, intel->regs + INTEL_TXPBS );
|
||||
}
|
||||
|
||||
/* Always reset MAC. Required to reset the TX and RX rings. */
|
||||
writel ( ( ctrl | INTEL_CTRL_RST ), intel->regs + INTEL_CTRL );
|
||||
mdelay ( INTEL_RESET_DELAY_MS );
|
||||
@ -1139,7 +1151,7 @@ static struct pci_device_id intel_nics[] = {
|
||||
PCI_ROM ( 0x8086, 0x1525, "82567v-4", "82567V-4", 0 ),
|
||||
PCI_ROM ( 0x8086, 0x1526, "82576-5", "82576", 0 ),
|
||||
PCI_ROM ( 0x8086, 0x1527, "82580-f2", "82580 Fiber", 0 ),
|
||||
PCI_ROM ( 0x8086, 0x1533, "i210", "I210", 0 ),
|
||||
PCI_ROM ( 0x8086, 0x1533, "i210", "I210", INTEL_PBSIZE_RST ),
|
||||
PCI_ROM ( 0x8086, 0x1539, "i211", "I211", 0 ),
|
||||
PCI_ROM ( 0x8086, 0x153a, "i217lm", "I217-LM", INTEL_NO_PHY_RST ),
|
||||
PCI_ROM ( 0x8086, 0x153b, "i217v", "I217-V", 0 ),
|
||||
@ -1147,7 +1159,7 @@ static struct pci_device_id intel_nics[] = {
|
||||
PCI_ROM ( 0x8086, 0x155a, "i218lm", "I218-LM", INTEL_NO_PHY_RST ),
|
||||
PCI_ROM ( 0x8086, 0x156f, "i219lm", "I219-LM", INTEL_I219 ),
|
||||
PCI_ROM ( 0x8086, 0x1570, "i219v", "I219-V", INTEL_I219 ),
|
||||
PCI_ROM ( 0x8086, 0x157b, "i210-2", "I210", 0 ),
|
||||
PCI_ROM ( 0x8086, 0x157b, "i210-2", "I210", INTEL_PBSIZE_RST ),
|
||||
PCI_ROM ( 0x8086, 0x15a0, "i218lm-2", "I218-LM", INTEL_NO_PHY_RST ),
|
||||
PCI_ROM ( 0x8086, 0x15a1, "i218v-2", "I218-V", 0 ),
|
||||
PCI_ROM ( 0x8086, 0x15a2, "i218lm-3", "I218-LM", INTEL_NO_PHY_RST ),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user