Compare commits

..

1 Commits

Author SHA1 Message Date
62b6def339 [tls] Handle fragmented handshake records
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-03-30 16:28:40 +01:00
337 changed files with 3074 additions and 24090 deletions

View File

@ -12,7 +12,7 @@ jobs:
run: |
sudo chown $(id -un) /var/cache/apt/archives
- name: Cache packages
uses: actions/cache@v4
uses: actions/cache@v3
with:
path: /var/cache/apt/archives/*.deb
key: apt-cache-${{ github.run_id }}-${{ github.run_attempt }}
@ -32,14 +32,14 @@ jobs:
needs: cache
steps:
- name: Check out code
uses: actions/checkout@v4
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@v4
uses: actions/cache/restore@v3
with:
path: /var/cache/apt/archives/*.deb
key: apt-cache-${{ github.run_id }}-${{ github.run_attempt }}
@ -49,8 +49,7 @@ jobs:
sudo apt update
sudo apt install -y -o Acquire::Retries=50 \
mtools syslinux isolinux \
libc6-dev-i386 valgrind \
libgcc-s1:i386 libc6-dbg:i386
libc6-dev-i386 libc6-dbg:i386 valgrind
- name: Build (BIOS)
run: |
make -j 4 -C src
@ -68,14 +67,14 @@ jobs:
needs: cache
steps:
- name: Check out code
uses: actions/checkout@v4
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@v4
uses: actions/cache/restore@v3
with:
path: /var/cache/apt/archives/*.deb
key: apt-cache-${{ github.run_id }}-${{ github.run_attempt }}
@ -97,14 +96,14 @@ jobs:
needs: cache
steps:
- name: Check out code
uses: actions/checkout@v4
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@v4
uses: actions/cache/restore@v3
with:
path: /var/cache/apt/archives/*.deb
key: apt-cache-${{ github.run_id }}-${{ github.run_attempt }}

View File

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Check out code
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Download Coverity Scan
run: |
curl --form token=${{ secrets.COVERITY_SCAN_TOKEN }} \

View File

@ -46,19 +46,11 @@ def create_snapshot(region, description, image):
return snapshot_id
def import_image(region, name, architecture, image, public, overwrite):
def import_image(region, name, architecture, image, public):
"""Import an AMI image"""
client = boto3.client('ec2', region_name=region)
resource = boto3.resource('ec2', region_name=region)
description = '%s (%s)' % (name, architecture)
images = client.describe_images(Filters=[{'Name': 'name',
'Values': [description]}])
if overwrite and images['Images']:
images = images['Images'][0]
image_id = images['ImageId']
snapshot_id = images['BlockDeviceMappings'][0]['Ebs']['SnapshotId']
resource.Image(image_id).deregister()
resource.Snapshot(snapshot_id).delete()
snapshot_id = create_snapshot(region=region, description=description,
image=image)
client.get_waiter('snapshot_completed').wait(SnapshotIds=[snapshot_id])
@ -96,8 +88,6 @@ parser.add_argument('--name', '-n',
help="Image name")
parser.add_argument('--public', '-p', action='store_true',
help="Make image public")
parser.add_argument('--overwrite', action='store_true',
help="Overwrite any existing image with same name")
parser.add_argument('--region', '-r', action='append',
help="AWS region(s)")
parser.add_argument('--wiki', '-w', metavar='FILE',
@ -125,8 +115,7 @@ with ThreadPoolExecutor(max_workers=len(imports)) as executor:
name=args.name,
architecture=architectures[image],
image=image,
public=args.public,
overwrite=args.overwrite): (region, image)
public=args.public): (region, image)
for region, image in imports}
results = {futures[future]: future.result()
for future in as_completed(futures)}

View File

@ -1,68 +0,0 @@
#!/usr/bin/env python3
import argparse
import boto3
BLOCKSIZE = 512 * 1024
IPXELOG_OFFSET = 16 * 1024
IPXELOG_MAGIC = b'iPXE LOG'
def create_snapshot(region, instance_id):
"""Create root volume snapshot"""
client = boto3.client('ec2', region_name=region)
resource = boto3.resource('ec2', region_name=region)
instance = resource.Instance(instance_id)
volumes = list(instance.volumes.all())
snapshot = volumes[0].create_snapshot()
snapshot.wait_until_completed()
return snapshot.id
def get_snapshot_block(region, snapshot_id, index):
"""Get block content from snapshot"""
client = boto3.client('ebs', region_name=region)
blocks = client.list_snapshot_blocks(SnapshotId=snapshot_id,
StartingBlockIndex=index)
token = blocks['Blocks'][0]['BlockToken']
block = client.get_snapshot_block(SnapshotId=snapshot_id,
BlockIndex=index,
BlockToken=token)
return block['BlockData'].read()
def get_block0_content(region, instance_id):
"""Get content of root volume block zero from instance"""
client = boto3.client('ec2', region_name=region)
resource = boto3.resource('ec2', region_name=region)
snapshot_id = create_snapshot(region, instance_id)
block = get_snapshot_block(region, snapshot_id, 0)
resource.Snapshot(snapshot_id).delete()
return block
def get_int13con_output(region, instance_id):
"""Get INT13 console output"""
block = get_block0_content(region, instance_id)
logpart = block[IPXELOG_OFFSET:]
magic = logpart[:len(IPXELOG_MAGIC)]
if magic != IPXELOG_MAGIC:
raise ValueError("Invalid log magic signature")
log = logpart[len(IPXELOG_MAGIC):].split(b'\0')[0]
return log.decode()
# Parse command-line arguments
parser = argparse.ArgumentParser(description="Get AWS INT13 console output")
parser.add_argument('--region', '-r', help="AWS region")
parser.add_argument('id', help="Instance ID")
args = parser.parse_args()
# Get console output from INT13CON partition
output = get_int13con_output(args.region, args.id)
# Print console output
print(output)

2
src/.gitignore vendored
View File

@ -1,4 +1,4 @@
.toolcheck
.echocheck
TAGS*
bin-*
bin*

View File

@ -23,9 +23,9 @@ NON_AUTO_MEDIA += efidrv
NON_AUTO_MEDIA += drv.efi
NON_AUTO_MEDIA += efirom
# Include SNP and MNP drivers in the all-drivers build
# Include SNP driver in the all-drivers build
#
DRIVERS_net += snp mnp
DRIVERS_net += snp
# Rules for building EFI files
#
@ -50,10 +50,6 @@ $(BIN)/efidrv.cab : $(BIN)/alldrv.efis # $(ALL_drv.efi) is not yet defined
$(QM)$(ECHO) " [CAB] $@"
$(Q)$(LCAB) -n -q $(ALL_drv.efi) $@
$(BIN)/%.iso : $(BIN)/%.efi util/genfsimg
$(QM)$(ECHO) " [GENFSIMG] $@"
$(Q)util/genfsimg -o $@ $<
$(BIN)/%.usb : $(BIN)/%.efi util/genfsimg
$(BIN)/%.iso $(BIN)/%.usb : $(BIN)/%.efi util/genfsimg
$(QM)$(ECHO) " [GENFSIMG] $@"
$(Q)util/genfsimg -o $@ $<

View File

@ -502,13 +502,6 @@ LDFLAGS += --gc-sections
#
LDFLAGS += -static
# Use separate code segment if supported by linker
#
ZSC_TEST = $(LD) -z separate-code --version 2>&1 > /dev/null
ZSC_FLAGS := $(shell [ -z "`$(ZSC_TEST)`" ] && \
$(ECHO) '-z separate-code -z max-page-size=4096')
LDFLAGS += $(ZSC_FLAGS)
# compiler.h is needed for our linking and debugging system
#
CFLAGS += -include include/compiler.h
@ -1009,7 +1002,6 @@ endif
# Device ID tables (using IDs from ROM definition file)
#
define obj_pci_id_asm
.section ".note.GNU-stack", "", $(ASM_TCHAR)progbits
.section ".pci_devlist.$(1)", "a", $(ASM_TCHAR)progbits
.globl pci_devlist_$(1)
pci_devlist_$(1):
@ -1179,7 +1171,7 @@ BLIB = $(BIN)/blib.a
$(BLIB) : $(BLIB_OBJS) $(BLIB_LIST) $(MAKEDEPS)
$(Q)$(RM) $(BLIB)
$(QM)$(ECHO) " [AR] $@"
$(Q)$(AR) rcD $@ $(sort $(BLIB_OBJS))
$(Q)$(AR) rD $@ $(sort $(BLIB_OBJS))
$(Q)$(OBJCOPY) --enable-deterministic-archives \
--prefix-symbols=$(SYMBOL_PREFIX) $@
$(Q)$(RANLIB) -D $@

View File

@ -9,5 +9,4 @@ INCDIRS += arch/arm/include
# ARM-specific directories containing source files
#
SRCDIRS += arch/arm/core
SRCDIRS += arch/arm/interface/efi

View File

@ -46,7 +46,7 @@ union arm32_io_qword {
*
* This is not atomic for ARM32.
*/
static __unused uint64_t arm32_readq ( volatile uint64_t *io_addr ) {
static uint64_t arm32_readq ( volatile uint64_t *io_addr ) {
volatile union arm32_io_qword *ptr =
container_of ( io_addr, union arm32_io_qword, qword );
union arm32_io_qword tmp;
@ -64,8 +64,7 @@ static __unused uint64_t arm32_readq ( volatile uint64_t *io_addr ) {
*
* This is not atomic for ARM32.
*/
static __unused void arm32_writeq ( uint64_t data,
volatile uint64_t *io_addr ) {
static void arm32_writeq ( uint64_t data, volatile uint64_t *io_addr ) {
volatile union arm32_io_qword *ptr =
container_of ( io_addr, union arm32_io_qword, qword );
union arm32_io_qword tmp;
@ -83,6 +82,7 @@ PROVIDE_IOAPI_INLINE ( arm, readl );
PROVIDE_IOAPI_INLINE ( arm, writeb );
PROVIDE_IOAPI_INLINE ( arm, writew );
PROVIDE_IOAPI_INLINE ( arm, writel );
PROVIDE_IOAPI_INLINE ( arm, iodelay );
PROVIDE_IOAPI_INLINE ( arm, mb );
#ifdef __aarch64__
PROVIDE_IOAPI_INLINE ( arm, readq );
@ -91,4 +91,3 @@ PROVIDE_IOAPI_INLINE ( arm, writeq );
PROVIDE_IOAPI ( arm, readq, arm32_readq );
PROVIDE_IOAPI ( arm, writeq, arm32_writeq );
#endif
PROVIDE_DUMMY_PIO ( arm );

View File

@ -1,12 +0,0 @@
#ifndef _BITS_MP_H
#define _BITS_MP_H
/** @file
*
* ARM-specific multiprocessor API implementation
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_MP_H */

View File

@ -9,4 +9,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/io.h>
#endif /* _BITS_PCI_IO_H */

View File

@ -15,8 +15,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define IOAPI_PREFIX_arm __arm_
#endif
#include <ipxe/dummy_pio.h>
/*
* Memory space mappings
*
@ -79,6 +77,55 @@ ARM_WRITEX ( w, uint16_t, "h", "" );
ARM_WRITEX ( l, uint32_t, "", "" );
#endif
/*
* Dummy PIO reads and writes up to 32 bits
*
* There is no common standard for I/O-space access for ARM, and
* non-MMIO peripherals are vanishingly rare. Provide dummy
* implementations that will allow code to link and should cause
* drivers to simply fail to detect hardware at runtime.
*
*/
#define ARM_INX( _suffix, _type ) \
static inline __always_inline _type \
IOAPI_INLINE ( arm, in ## _suffix ) ( volatile _type *io_addr __unused) { \
return ~( (_type) 0 ); \
} \
static inline __always_inline void \
IOAPI_INLINE ( arm, ins ## _suffix ) ( volatile _type *io_addr __unused, \
_type *data, unsigned int count ) { \
memset ( data, 0xff, count * sizeof ( *data ) ); \
}
ARM_INX ( b, uint8_t );
ARM_INX ( w, uint16_t );
ARM_INX ( l, uint32_t );
#define ARM_OUTX( _suffix, _type ) \
static inline __always_inline void \
IOAPI_INLINE ( arm, out ## _suffix ) ( _type data __unused, \
volatile _type *io_addr __unused ) { \
/* Do nothing */ \
} \
static inline __always_inline void \
IOAPI_INLINE ( arm, outs ## _suffix ) ( volatile _type *io_addr __unused, \
const _type *data __unused, \
unsigned int count __unused ) { \
/* Do nothing */ \
}
ARM_OUTX ( b, uint8_t );
ARM_OUTX ( w, uint16_t );
ARM_OUTX ( l, uint32_t );
/*
* Slow down I/O
*
*/
static inline __always_inline void
IOAPI_INLINE ( arm, iodelay ) ( void ) {
/* Nothing to do */
}
/*
* Memory barrier
*
@ -93,7 +140,4 @@ IOAPI_INLINE ( arm, mb ) ( void ) {
#endif
}
/* Dummy PIO */
DUMMY_PIO ( arm );
#endif /* _IPXE_ARM_IO_H */

View File

@ -46,12 +46,8 @@ static void efiarm_cpu_nap ( void ) {
* The EFI shell doesn't seem to bother sleeping the CPU; it
* just sits there idly burning power.
*
* If a shutdown is in progess, there may be nothing to
* generate an interrupt since the timer is disabled in the
* first step of ExitBootServices().
*/
if ( ! efi_shutdown_in_progress )
__asm__ __volatile__ ( "wfi" );
__asm__ __volatile__ ( "wfi" );
}
PROVIDE_NAP ( efiarm, cpu_nap, efiarm_cpu_nap );

View File

@ -36,23 +36,19 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* Multiply big integers
*
* @v multiplicand0 Element 0 of big integer to be multiplied
* @v multiplicand_size Number of elements in multiplicand
* @v multiplier0 Element 0 of big integer to be multiplied
* @v multiplier_size Number of elements in multiplier
* @v result0 Element 0 of big integer to hold result
* @v size Number of elements
*/
void bigint_multiply_raw ( const uint32_t *multiplicand0,
unsigned int multiplicand_size,
const uint32_t *multiplier0,
unsigned int multiplier_size,
uint32_t *result0 ) {
unsigned int result_size = ( multiplicand_size + multiplier_size );
const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
*multiplicand = ( ( const void * ) multiplicand0 );
const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
*multiplier = ( ( const void * ) multiplier0 );
bigint_t ( result_size ) __attribute__ (( may_alias ))
*result = ( ( void * ) result0 );
uint32_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;
uint32_t multiplicand_element;
@ -66,9 +62,9 @@ void bigint_multiply_raw ( const uint32_t *multiplicand0,
memset ( result, 0, sizeof ( *result ) );
/* Multiply integers one element at a time */
for ( i = 0 ; i < multiplicand_size ; i++ ) {
for ( i = 0 ; i < size ; i++ ) {
multiplicand_element = multiplicand->element[i];
for ( j = 0 ; j < multiplier_size ; j++ ) {
for ( j = 0 ; j < size ; j++ ) {
multiplier_element = multiplier->element[j];
result_elements = &result->element[ i + j ];
/* Perform a single multiply, and add the
@ -77,7 +73,7 @@ void bigint_multiply_raw ( const uint32_t *multiplicand0,
* never overflow beyond the end of the
* result, since:
*
* a < 2^{n}, b < 2^{m} => ab < 2^{n+m}
* a < 2^{n}, b < 2^{n} => ab < 2^{2n}
*/
__asm__ __volatile__ ( "umull %1, %2, %5, %6\n\t"
"ldr %3, [%0]\n\t"

View File

@ -310,9 +310,7 @@ bigint_done_raw ( const uint32_t *value0, unsigned int size __unused,
}
extern void bigint_multiply_raw ( const uint32_t *multiplicand0,
unsigned int multiplicand_size,
const uint32_t *multiplier0,
unsigned int multiplier_size,
uint32_t *value0 );
uint32_t *value0, unsigned int size );
#endif /* _BITS_BIGINT_H */

View File

@ -1,6 +1,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", %progbits
.text
.thumb
/**

View File

@ -1,6 +1,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", %progbits
.text
.arm
/**

View File

@ -36,23 +36,19 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* Multiply big integers
*
* @v multiplicand0 Element 0 of big integer to be multiplied
* @v multiplicand_size Number of elements in multiplicand
* @v multiplier0 Element 0 of big integer to be multiplied
* @v multiplier_size Number of elements in multiplier
* @v result0 Element 0 of big integer to hold result
* @v size Number of elements
*/
void bigint_multiply_raw ( const uint64_t *multiplicand0,
unsigned int multiplicand_size,
const uint64_t *multiplier0,
unsigned int multiplier_size,
uint64_t *result0 ) {
unsigned int result_size = ( multiplicand_size + multiplier_size );
const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
*multiplicand = ( ( const void * ) multiplicand0 );
const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
*multiplier = ( ( const void * ) multiplier0 );
bigint_t ( result_size ) __attribute__ (( may_alias ))
*result = ( ( void * ) result0 );
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;
@ -67,9 +63,9 @@ void bigint_multiply_raw ( const uint64_t *multiplicand0,
memset ( result, 0, sizeof ( *result ) );
/* Multiply integers one element at a time */
for ( i = 0 ; i < multiplicand_size ; i++ ) {
for ( i = 0 ; i < size ; i++ ) {
multiplicand_element = multiplicand->element[i];
for ( j = 0 ; j < multiplier_size ; j++ ) {
for ( j = 0 ; j < size ; j++ ) {
multiplier_element = multiplier->element[j];
result_elements = &result->element[ i + j ];
/* Perform a single multiply, and add the
@ -78,7 +74,7 @@ void bigint_multiply_raw ( const uint64_t *multiplicand0,
* never overflow beyond the end of the
* result, since:
*
* a < 2^{n}, b < 2^{m} => ab < 2^{n+m}
* a < 2^{n}, b < 2^{n} => ab < 2^{2n}
*/
__asm__ __volatile__ ( "mul %1, %6, %7\n\t"
"umulh %2, %6, %7\n\t"

View File

@ -1,6 +1,5 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", %progbits
.text
/* Must match jmp_buf structure layout */

View File

@ -311,9 +311,7 @@ bigint_done_raw ( const uint64_t *value0, unsigned int size __unused,
}
extern void bigint_multiply_raw ( const uint64_t *multiplicand0,
unsigned int multiplicand_size,
const uint64_t *multiplier0,
unsigned int multiplier_size,
uint64_t *value0 );
uint64_t *value0, unsigned int size );
#endif /* _BITS_BIGINT_H */

View File

@ -9,7 +9,6 @@
* Interrupt handlers
****************************************************************************
*/
.section ".note.GNU-stack", "", @progbits
.section ".text", "ax", @progbits
.code32

View File

@ -1,9 +1,8 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.text
.code32
.arch i386
.code32
/* Must match jmp_buf structure layout */
.struct 0

View File

@ -1,5 +1,3 @@
.section ".note.GNU-stack", "", @progbits
.code32
.arch i386
.section ".data", "aw", @progbits

View File

@ -20,7 +20,6 @@ CFLAGS += -fshort-wchar
# LoongArch64-specific directories containing source files
SRCDIRS += arch/loong64/core
SRCDIRS += arch/loong64/interface/efi
# Include platform-specific Makefile
MAKEDEPS += arch/loong64/Makefile.$(PLATFORM)

View File

@ -1,14 +0,0 @@
# -*- makefile -*- : Force emacs to use Makefile mode
# Specify EFI image builder
#
ELF2EFI = $(ELF2EFI64)
# Specify EFI boot file
#
EFI_BOOT_FILE = bootloongarch64.efi
# Include generic EFI Makefile
#
MAKEDEPS += Makefile.efi
include Makefile.efi

View File

@ -37,23 +37,19 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* Multiply big integers
*
* @v multiplicand0 Element 0 of big integer to be multiplied
* @v multiplicand_size Number of elements in multiplicand
* @v multiplier0 Element 0 of big integer to be multiplied
* @v multiplier_size Number of elements in multiplier
* @v result0 Element 0 of big integer to hold result
* @v size Number of elements
*/
void bigint_multiply_raw ( const uint64_t *multiplicand0,
unsigned int multiplicand_size,
const uint64_t *multiplier0,
unsigned int multiplier_size,
uint64_t *result0 ) {
unsigned int result_size = ( multiplicand_size + multiplier_size );
const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
*multiplicand = ( ( const void * ) multiplicand0 );
const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
*multiplier = ( ( const void * ) multiplier0 );
bigint_t ( result_size ) __attribute__ (( may_alias ))
*result = ( ( void * ) result0 );
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;
@ -68,9 +64,9 @@ void bigint_multiply_raw ( const uint64_t *multiplicand0,
memset ( result, 0, sizeof ( *result ) );
/* Multiply integers one element at a time */
for ( i = 0 ; i < multiplicand_size ; i++ ) {
for ( i = 0 ; i < size ; i++ ) {
multiplicand_element = multiplicand->element[i];
for ( j = 0 ; j < multiplier_size ; j++ ) {
for ( j = 0 ; j < size ; j++ ) {
multiplier_element = multiplier->element[j];
result_elements = &result->element[ i + j ];
/* Perform a single multiply, and add the
@ -79,7 +75,7 @@ void bigint_multiply_raw ( const uint64_t *multiplicand0,
* never overflow beyond the end of the
* result, since:
*
* a < 2^{n}, b < 2^{m} => ab < 2^{n+m}
* 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"

View File

@ -1,46 +0,0 @@
/*
* 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 <ipxe/io.h>
#include <ipxe/loong64_io.h>
/** @file
*
* iPXE I/O API for LoongArch64
*
*/
PROVIDE_IOAPI_INLINE ( loong64, phys_to_bus );
PROVIDE_IOAPI_INLINE ( loong64, bus_to_phys );
PROVIDE_IOAPI_INLINE ( loong64, readb );
PROVIDE_IOAPI_INLINE ( loong64, readw );
PROVIDE_IOAPI_INLINE ( loong64, readl );
PROVIDE_IOAPI_INLINE ( loong64, readq );
PROVIDE_IOAPI_INLINE ( loong64, writeb );
PROVIDE_IOAPI_INLINE ( loong64, writew );
PROVIDE_IOAPI_INLINE ( loong64, writel );
PROVIDE_IOAPI_INLINE ( loong64, writeq );
PROVIDE_IOAPI_INLINE ( loong64, mb );
PROVIDE_DUMMY_PIO ( loong64 );

View File

@ -53,37 +53,34 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
uint64_t *discard_value;
uint64_t discard_addend_i;
uint64_t discard_value_i;
uint64_t discard_carry;
uint64_t discard_temp;
unsigned int discard_size;
__asm__ __volatile__ ( "\n1:\n\t"
/* Load addend[i] and value[i] */
"ld.d %3, %0, 0\n\t"
"ld.d %4, %1, 0\n\t"
/* Add carry flag and addend */
"add.d %4, %4, %5\n\t"
"sltu %6, %4, %5\n\t"
"add.d %4, %4, %3\n\t"
"sltu %5, %4, %3\n\t"
"or %5, %5, %6\n\t"
/* Store value[i] */
"st.d %4, %1, 0\n\t"
/* Loop */
__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\n\t"
"bnez %2, 1b"
: "=r" ( discard_addend ),
"=r" ( discard_value ),
"=r" ( discard_size ),
"=r" ( discard_addend_i ),
"=r" ( discard_value_i ),
"=r" ( discard_carry ),
"=r" ( discard_temp ),
"+m" ( *value )
: "0" ( addend0 ), "1" ( value0 ),
"2" ( size ), "5" ( 0 ) );
: "0" ( addend0 ),
"1" ( value0 ),
"2" ( size )
: "t0", "t1" );
}
/**
@ -96,43 +93,35 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
static inline __attribute__ (( always_inline )) void
bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( void * ) value0 );
uint64_t *discard_subtrahend;
uint64_t *discard_value;
uint64_t discard_subtrahend_i;
uint64_t discard_value_i;
uint64_t discard_carry;
uint64_t discard_temp;
unsigned int discard_size;
unsigned int flag = 0;
__asm__ __volatile__ ( "\n1:\n\t"
/* Load subtrahend[i] and value[i] */
"ld.d %3, %0, 0\n\t"
"ld.d %4, %1, 0\n\t"
/* Subtract carry flag and subtrahend */
"sltu %6, %4, %5\n\t"
"sub.d %4, %4, %5\n\t"
"sltu %5, %4, %3\n\t"
"sub.d %4, %4, %3\n\t"
"or %5, %5, %6\n\t"
/* Store value[i] */
"st.d %4, %1, 0\n\t"
/* Loop */
"addi.d %0, %0, 8\n\t"
"addi.d %1, %1, 8\n\t"
"addi.w %2, %2, -1\n\t"
"bnez %2, 1b\n\t"
: "=r" ( discard_subtrahend ),
"=r" ( discard_value ),
"=r" ( discard_size ),
"=r" ( discard_subtrahend_i ),
"=r" ( discard_value_i ),
"=r" ( discard_carry ),
"=r" ( discard_temp ),
"+m" ( *value )
: "0" ( subtrahend0 ), "1" ( value0 ),
"2" ( size ), "5" ( 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);
}
/**
@ -143,37 +132,30 @@ bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
*/
static inline __attribute__ (( always_inline )) void
bigint_rol_raw ( uint64_t *value0, unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( void * ) value0 );
uint64_t *discard_value;
uint64_t discard_value_i;
uint64_t discard_carry;
uint64_t discard_temp;
unsigned int discard_size;
uint64_t current_value_i;
unsigned int flag = 0;
__asm__ __volatile__ ( "\n1:\n\t"
/* Load value[i] */
"ld.d %2, %0, 0\n\t"
/* Shift left */
"rotri.d %2, %2, 63\n\t"
"andi %4, %2, 1\n\t"
"xor %2, %2, %4\n\t"
"or %2, %2, %3\n\t"
"move %3, %4\n\t"
/* Store value[i] */
"st.d %2, %0, 0\n\t"
/* Loop */
"addi.d %0, %0, 8\n\t"
"addi.w %1, %1, -1\n\t"
"bnez %1, 1b\n\t"
: "=r" ( discard_value ),
"=r" ( discard_size ),
"=r" ( discard_value_i ),
"=r" ( discard_carry ),
"=r" ( discard_temp ),
"+m" ( *value )
: "0" ( value0 ), "1" ( size ), "3" ( 0 )
: "cc" );
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 );
}
/**
@ -184,37 +166,27 @@ bigint_rol_raw ( uint64_t *value0, unsigned int size ) {
*/
static inline __attribute__ (( always_inline )) void
bigint_ror_raw ( uint64_t *value0, unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( void * ) value0 );
uint64_t *discard_value;
uint64_t discard_value_i;
uint64_t discard_carry;
uint64_t discard_temp;
uint64_t discard_value_j;
unsigned int discard_size;
__asm__ __volatile__ ( "\n1:\n\t"
/* Load value[i] */
"ld.d %2, %0, -8\n\t"
/* Shift right */
"andi %4, %2, 1\n\t"
"xor %2, %2, %4\n\t"
"or %2, %2, %3\n\t"
"move %3, %4\n\t"
"rotri.d %2, %2, 1\n\t"
/* Store value[i] */
"st.d %2, %0, -8\n\t"
/* Loop */
"addi.d %0, %0, -8\n\t"
"addi.w %1, %1, -1\n\t"
"bnez %1, 1b\n\t"
: "=r" ( discard_value ),
"=r" ( discard_size ),
"=r" ( discard_value_i ),
"=r" ( discard_carry ),
"=r" ( discard_temp ),
"+m" ( *value )
: "0" ( value0 + size ), "1" ( size ), "3" ( 0 )
: "cc" );
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 );
}
/**
@ -358,9 +330,7 @@ bigint_done_raw ( const uint64_t *value0, unsigned int size __unused,
}
extern void bigint_multiply_raw ( const uint64_t *multiplicand0,
unsigned int multiplicand_size,
const uint64_t *multiplier0,
unsigned int multiplier_size,
uint64_t *value0 );
uint64_t *value0, unsigned int size );
#endif /* _BITS_BIGINT_H */

View File

@ -12,6 +12,4 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** Page shift */
#define PAGE_SHIFT 12
#include <ipxe/loong64_io.h>
#endif /* _BITS_IO_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_MP_H
#define _BITS_MP_H
/** @file
*
* LoongArch64-specific multiprocessor API implementation
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_MP_H */

View File

@ -9,6 +9,4 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/efi/efiloong64_nap.h>
#endif /* _BITS_NAP_H */
#endif /* _BITS_MAP_H */

View File

@ -1,18 +0,0 @@
#ifndef _IPXE_EFILOONG64_NAP_H
#define _IPXE_EFILOONG64_NAP_H
/** @file
*
* EFI CPU sleeping
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef NAP_EFILOONG64
#define NAP_PREFIX_efiloong64
#else
#define NAP_PREFIX_efiloong64 __efiloong64_
#endif
#endif /* _IPXE_EFILOONG64_NAP_H */

View File

@ -1,82 +0,0 @@
#ifndef _IPXE_LOONG64_IO_H
#define _IPXE_LOONG64_IO_H
/** @file
*
* iPXE I/O API for LoongArch64
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef IOAPI_LOONG64
#define IOAPI_PREFIX_loong64
#else
#define IOAPI_PREFIX_loong64 __loong64_
#endif
#include <ipxe/dummy_pio.h>
/*
* Memory space mappings
*
*/
/*
* Physical<->Bus address mappings
*
*/
static inline __always_inline unsigned long
IOAPI_INLINE ( loong64, phys_to_bus ) ( unsigned long phys_addr ) {
return phys_addr;
}
static inline __always_inline unsigned long
IOAPI_INLINE ( loong64, bus_to_phys ) ( unsigned long bus_addr ) {
return bus_addr;
}
/*
* MMIO reads and writes up to native word size
*
*/
#define LOONG64_READX( _suffix, _type, _insn_suffix ) \
static inline __always_inline _type \
IOAPI_INLINE ( loong64, read ## _suffix ) ( volatile _type *io_addr ) { \
_type data; \
__asm__ __volatile__ ( "ld." _insn_suffix " %0, %1" \
: "=r" ( data ) : "m" ( *io_addr ) ); \
return data; \
}
LOONG64_READX ( b, uint8_t, "bu");
LOONG64_READX ( w, uint16_t, "hu");
LOONG64_READX ( l, uint32_t, "wu");
LOONG64_READX ( q, uint64_t, "d");
#define LOONG64_WRITEX( _suffix, _type, _insn_suffix ) \
static inline __always_inline void \
IOAPI_INLINE ( loong64, write ## _suffix ) ( _type data, \
volatile _type *io_addr ) { \
__asm__ __volatile__ ( "st." _insn_suffix " %0, %1" \
: : "r" ( data ), "m" ( *io_addr ) ); \
}
LOONG64_WRITEX ( b, uint8_t, "b");
LOONG64_WRITEX ( w, uint16_t, "h");
LOONG64_WRITEX ( l, uint32_t, "w" );
LOONG64_WRITEX ( q, uint64_t, "d");
/*
* Memory barrier
*
*/
static inline __always_inline void
IOAPI_INLINE ( loong64, mb ) ( void ) {
__asm__ __volatile__ ( "dbar 0" );
}
/* Dummy PIO */
DUMMY_PIO ( loong64 );
#endif /* _IPXE_LOONG64_IO_H */

View File

@ -1,57 +0,0 @@
/*
* 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 <ipxe/nap.h>
#include <ipxe/efi/efi.h>
/** @file
*
* iPXE CPU sleeping API for EFI
*
*/
/**
* Sleep until next interrupt
*
*/
static void efiloong64_cpu_nap ( void ) {
/*
* I can't find any EFI API that allows us to put the CPU to
* sleep. The CpuSleep() function is defined in CpuLib.h, but
* isn't part of any exposed protocol so we have no way to
* call it.
*
* The EFI shell doesn't seem to bother sleeping the CPU; it
* just sits there idly burning power.
*
* If a shutdown is in progess, there may be nothing to
* generate an interrupt since the timer is disabled in the
* first step of ExitBootServices().
*/
if ( ! efi_shutdown_in_progress )
__asm__ __volatile__ ( "idle 0" );
}
PROVIDE_NAP ( efiloong64, cpu_nap, efiloong64_cpu_nap );

View File

@ -13,13 +13,6 @@ LDSCRIPT_PREFIX = arch/x86/scripts/prefixonly.lds
#
LDFLAGS += -N --no-check-sections
# Do not warn about RWX segments (required by most prefixes)
#
WRWX_TEST = $(LD) --warn-rwx-segments --version 2>&1 > /dev/null
WRWX_FLAGS := $(shell [ -z "`$(WRWX_TEST)`" ] && \
$(ECHO) '--no-warn-rwx-segments')
LDFLAGS += $(WRWX_FLAGS)
# Media types.
#
MEDIA += rom
@ -61,15 +54,9 @@ LIST_NAME_mrom := ROMS
LIST_NAME_pcirom := ROMS
LIST_NAME_isarom := ROMS
# ISO images
# ISO or FAT filesystem images
NON_AUTO_MEDIA += iso
$(BIN)/%.iso : $(BIN)/%.lkrn util/genfsimg
$(QM)$(ECHO) " [GENFSIMG] $@"
$(Q)util/genfsimg -o $@ $<
# FAT filesystem images (via syslinux)
NON_AUTO_MEDIA += sdsk
$(BIN)/%.sdsk : $(BIN)/%.lkrn util/genfsimg
$(BIN)/%.iso $(BIN)/%.sdsk: $(BIN)/%.lkrn util/genfsimg
$(QM)$(ECHO) " [GENFSIMG] $@"
$(Q)util/genfsimg -o $@ $<

View File

@ -1,197 +0,0 @@
/*
* Copyright (C) 2024 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
*
* Multiprocessor functions
*
*/
.section ".note.GNU-stack", "", @progbits
.text
/* Selectively assemble code for 32-bit/64-bit builds */
#if defined ( __x86_64__ ) && ! defined ( PLATFORM_pcbios )
#define codemp code64
#define DI rdi
#define SP rsp
#define if32 if 0
#define if64 if 1
#else
#define codemp code32
#define DI edi
#define SP esp
#define if32 if 1
#define if64 if 0
#endif
/* Standard features CPUID leaf */
#define CPUID_FEATURES 0x00000001
/* x2APIC is supported */
#define CPUID_FEATURES_ECX_X2APIC 0x00200000
/* Extended topology enumeration CPUID leaf */
#define CPUID_XT_ENUM 0x0000000b
/*
* Call multiprocessor function from C code
*
* Parameters:
* 4(%esp)/%rdi Multiprocessor function
* 8(%esp)/%rsi Opaque data pointer
*/
.section ".text.mp_call", "ax", @progbits
.codemp
.globl mp_call
mp_call:
.if64 /* Preserve registers, load incoming parameters into registers */
pushq %rax
pushq %rcx
pushq %rdx
pushq %rbx
pushq %rsp
pushq %rbp
pushq %rsi
pushq %rdi
pushq %r8
pushq %r9
pushq %r10
pushq %r11
pushq %r12
pushq %r13
pushq %r14
pushq %r15
.else
pushal
movl 36(%esp), %eax
movl 40(%esp), %edx
.endif
/* Call multiprocessor function */
call mp_jump
.if64 /* Restore registers and return */
popq %r15
popq %r14
popq %r13
popq %r12
popq %r11
popq %r10
popq %r9
popq %r8
popq %rdi
popq %rsi
popq %rbp
leaq 8(%rsp), %rsp /* discard */
popq %rbx
popq %rdx
popq %rcx
popq %rax
.else
popal
.endif
ret
.size mp_call, . - mp_call
/*
* Jump to multiprocessor function
*
* Parameters:
* %eax/%rdi Multiprocessor function
* %edx/%rsi Opaque data pointer
* %esp/%rsp Stack, or NULL to halt AP upon completion
*
* Obtain the CPU identifier (i.e. the APIC ID) and perform a tail
* call into the specified multiprocessor function.
*
* This code may run with no stack on an application processor.
*/
.section ".text.mp_jump", "ax", @progbits
.codemp
.globl mp_jump
mp_jump:
.if32 /* Move function parameters to available registers */
movl %eax, %edi
movl %edx, %esi
.endif
/* Get 8-bit APIC ID and x2APIC feature bit */
movl $CPUID_FEATURES, %eax
cpuid
shrl $24, %ebx
movl %ebx, %edx
/* Get 32-bit x2APIC ID if applicable */
testl $CPUID_FEATURES_ECX_X2APIC, %ecx
jz 1f
movl $CPUID_XT_ENUM, %eax
xorl %ecx, %ecx
cpuid
1:
.if64 /* Tail call to function */
movq %rdi, %rax
movq %rsi, %rdi
movl %edx, %esi
jmp *%rax
.else
movl %esi, %eax
jmp *%edi
.endif
.size mp_jump, . - mp_jump
/*
* Update maximum CPU identifier
*
* Parameters:
* %eax/%rdi Pointer to shared maximum APIC ID
* %edx/%rsi CPU identifier (APIC ID)
* %esp/%rsp Stack, or NULL to halt AP upon completion
*
* This code may run with no stack on an application processor.
*/
.section ".text.mp_update_max_cpuid", "ax", @progbits
.codemp
.globl mp_update_max_cpuid
mp_update_max_cpuid:
.if32 /* Move function parameters to available registers */
movl %eax, %edi
movl %edx, %esi
.endif
/* Update maximum APIC ID (atomically) */
movl (%DI), %eax
1: cmpl %esi, %eax
jae 2f
lock cmpxchgl %esi, (%DI)
jnz 1b
2:
/* Return to caller (if stack exists), or halt application processor */
test %SP, %SP
jz 3f
ret
3: cli
hlt
jmp 3b
.size mp_update_max_cpuid, . - mp_update_max_cpuid

View File

@ -22,9 +22,9 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.code16
.text
.arch i386
.code16
/****************************************************************************
* Set/clear CF on the stack as appropriate, assumes stack is as it should

View File

@ -1,6 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.arch i386
#ifdef __x86_64__
#define STACK_SIZE 8192

View File

@ -1,6 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.arch i386
/****************************************************************************
* Internal stack

View File

@ -1,257 +0,0 @@
/*
* Copyright (C) 2024 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
*
* Microcode updates
*
*/
.section ".note.GNU-stack", "", @progbits
.text
/* Selectively assemble code for 32-bit/64-bit builds */
#if defined ( __x86_64__ ) && ! defined ( PLATFORM_pcbios )
#define codemp code64
#define AX rax
#define BX rbx
#define CX rcx
#define DX rdx
#define SI rsi
#define DI rdi
#define BP rbp
#define SP rsp
#define if32 if 0
#define if64 if 1
#else
#define codemp code32
#define AX eax
#define BX ebx
#define CX ecx
#define DX edx
#define SI esi
#define DI edi
#define BP ebp
#define SP esp
#define if32 if 1
#define if64 if 0
#endif
/* Standard features CPUID leaf */
#define CPUID_FEATURES 0x00000001
/* BIOS update signature MSR */
#define MSR_BIOS_SIGN_ID 0x0000008b
/** Microcode update control layout
*
* This must match the layout of struct ucode_control.
*/
.struct 0
CONTROL_DESC:
.space 8
CONTROL_STATUS:
.space 8
CONTROL_TRIGGER_MSR:
.space 4
CONTROL_APIC_MAX:
.space 4
CONTROL_APIC_UNEXPECTED:
.space 4
CONTROL_APIC_MASK:
.space 4
CONTROL_APIC_TEST:
.space 4
CONTROL_VER_CLEAR:
.space 1
CONTROL_VER_HIGH:
.space 1
CONTROL_LEN:
/* We use register %ebp/%rbp to hold the address of the update control */
#define CONTROL BP
/* Microcode update descriptor layout
*
* This must match the layout of struct ucode_descriptor.
*/
.struct 0
DESC_SIGNATURE:
.space 4
DESC_VERSION:
.space 4
DESC_ADDRESS:
.space 8
DESC_LEN:
/* We use register %esi/%rsi to hold the address of the descriptor */
#define DESC SI
/** Microcode update status report layout
*
* This must match the layout of struct ucode_status.
*/
.struct 0
STATUS_SIGNATURE:
.space 4
STATUS_ID:
.space 4
STATUS_BEFORE:
.space 4
STATUS_AFTER:
.space 4
STATUS_LEN:
.equ LOG2_STATUS_LEN, 4
.if ( 1 << LOG2_STATUS_LEN ) - STATUS_LEN
.error "LOG2_STATUS_LEN value is incorrect"
.endif
/* We use register %edi/%rdi to hold the address of the status report */
#define STATUS DI
/*
* Update microcode
*
* Parameters:
* %eax/%rdi Microcode update structure
* %edx/%rsi CPU identifier (APIC ID)
* %esp/%rsp Stack, or NULL to halt AP upon completion
*
* This code may run with no stack on an application processor (AP).
* All values must be held in registers, and no subroutine calls are
* possible. No firmware routines may be called.
*
* Since cpuid/rdmsr/wrmsr require the use of %eax, %ebx, %ecx, and
* %edx, we have essentially only three registers available for
* long-term state.
*/
.text
.globl ucode_update
.codemp
.section ".text.ucode_update", "ax", @progbits
ucode_update:
.if64 /* Get input parameters */
movq %rdi, %CONTROL
movl %esi, %edx
.else
movl %eax, %CONTROL
.endif
/* Check against maximum expected APIC ID */
cmpl CONTROL_APIC_MAX(%CONTROL), %edx
jbe 1f
movl %edx, CONTROL_APIC_UNEXPECTED(%CONTROL)
jmp done
1:
/* Calculate per-CPU status report buffer address */
mov %DX, %STATUS
shl $LOG2_STATUS_LEN, %STATUS
add CONTROL_STATUS(%CONTROL), %STATUS
/* Report APIC ID */
movl %edx, STATUS_ID(%STATUS)
/* Get and report CPU signature */
movl $CPUID_FEATURES, %eax
cpuid
movl %eax, STATUS_SIGNATURE(%STATUS)
/* Check APIC ID mask */
movl STATUS_ID(%STATUS), %eax
andl CONTROL_APIC_MASK(%CONTROL), %eax
cmpl CONTROL_APIC_TEST(%CONTROL), %eax
jne done
/* Clear BIOS_SIGN_ID MSR if applicable */
movl $MSR_BIOS_SIGN_ID, %ecx
xorl %eax, %eax
xorl %edx, %edx
testb $0xff, CONTROL_VER_CLEAR(%CONTROL)
jz 1f
wrmsr
1:
/* Get CPU signature to repopulate BIOS_SIGN_ID MSR (for Intel) */
movl $CPUID_FEATURES, %eax
cpuid
/* Get initial microcode version */
movl $MSR_BIOS_SIGN_ID, %ecx
rdmsr
testb $0xff, CONTROL_VER_HIGH(%CONTROL)
jz 1f
movl %edx, %eax
1: movl %eax, STATUS_BEFORE(%STATUS)
/* Get start of descriptor list */
mov CONTROL_DESC(%CONTROL), %DESC
sub $DESC_LEN, %DESC
1: /* Walk update descriptor list to find a matching CPU signature */
add $DESC_LEN, %DESC
movl DESC_SIGNATURE(%DESC), %eax
testl %eax, %eax
jz noload
cmpl STATUS_SIGNATURE(%STATUS), %eax
jne 1b
/* Compare (signed) microcode versions */
movl STATUS_BEFORE(%STATUS), %eax
cmpl DESC_VERSION(%DESC), %eax
jge noload
/* Load microcode update */
movl CONTROL_TRIGGER_MSR(%CONTROL), %ecx
movl (DESC_ADDRESS + 0)(%DESC), %eax
movl (DESC_ADDRESS + 4)(%DESC), %edx
wrmsr
noload: /* Clear BIOS_SIGN_ID MSR if applicable */
movl $MSR_BIOS_SIGN_ID, %ecx
xorl %eax, %eax
xorl %edx, %edx
testb $0xff, CONTROL_VER_CLEAR(%CONTROL)
jz 1f
wrmsr
1:
/* Get CPU signature to repopulate BIOS_SIGN_ID MSR (for Intel) */
movl $CPUID_FEATURES, %eax
cpuid
/* Get and report final microcode version */
movl $MSR_BIOS_SIGN_ID, %ecx
rdmsr
testb $0xff, CONTROL_VER_HIGH(%CONTROL)
jz 1f
movl %edx, %eax
1: movl %eax, STATUS_AFTER(%STATUS)
done: /* Return to caller (if stack exists), or halt application processor */
test %SP, %SP
jz 1f
ret
1: cli
hlt
jmp 1b
.size ucode_update, . - ucode_update

View File

@ -36,23 +36,19 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* Multiply big integers
*
* @v multiplicand0 Element 0 of big integer to be multiplied
* @v multiplicand_size Number of elements in multiplicand
* @v multiplier0 Element 0 of big integer to be multiplied
* @v multiplier_size Number of elements in multiplier
* @v result0 Element 0 of big integer to hold result
* @v size Number of elements
*/
void bigint_multiply_raw ( const uint32_t *multiplicand0,
unsigned int multiplicand_size,
const uint32_t *multiplier0,
unsigned int multiplier_size,
uint32_t *result0 ) {
unsigned int result_size = ( multiplicand_size + multiplier_size );
const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
*multiplicand = ( ( const void * ) multiplicand0 );
const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
*multiplier = ( ( const void * ) multiplier0 );
bigint_t ( result_size ) __attribute__ (( may_alias ))
*result = ( ( void * ) result0 );
uint32_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;
uint32_t multiplicand_element;
@ -66,9 +62,9 @@ void bigint_multiply_raw ( const uint32_t *multiplicand0,
memset ( result, 0, sizeof ( *result ) );
/* Multiply integers one element at a time */
for ( i = 0 ; i < multiplicand_size ; i++ ) {
for ( i = 0 ; i < size ; i++ ) {
multiplicand_element = multiplicand->element[i];
for ( j = 0 ; j < multiplier_size ; j++ ) {
for ( j = 0 ; j < size ; j++ ) {
multiplier_element = multiplier->element[j];
result_elements = &result->element[ i + j ];
/* Perform a single multiply, and add the
@ -77,7 +73,7 @@ void bigint_multiply_raw ( const uint32_t *multiplicand0,
* never overflow beyond the end of the
* result, since:
*
* a < 2^{n}, b < 2^{m} => ab < 2^{n+m}
* a < 2^{n}, b < 2^{n} => ab < 2^{2n}
*/
__asm__ __volatile__ ( "mull %5\n\t"
"addl %%eax, (%6,%2,4)\n\t"

View File

@ -10,9 +10,9 @@ FILE_LICENCE ( GPL2_OR_LATER )
#define PIC1_ICR 0x20
#define PIC2_ICR 0xa0
.section ".note.GNU-stack", "", @progbits
.code16
.text
.arch i386
.code16
.section ".text16", "ax", @progbits
.globl undiisr

View File

@ -355,10 +355,6 @@ static size_t bzimage_load_initrd ( struct image *image,
size_t offset;
size_t pad_len;
/* Skip hidden images */
if ( initrd->flags & IMAGE_HIDDEN )
return 0;
/* Create cpio header for non-prebuilt images */
offset = cpio_header ( initrd, &cpio );

View File

@ -204,10 +204,6 @@ static int multiboot_add_modules ( struct image *image, physaddr_t start,
break;
}
/* Skip hidden images */
if ( module_image->flags & IMAGE_HIDDEN )
continue;
/* Page-align the module */
start = ( ( start + 0xfff ) & ~0xfff );

View File

@ -1,798 +0,0 @@
/*
* Copyright (C) 2024 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
*
* Microcode updates
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <ipxe/uaccess.h>
#include <ipxe/umalloc.h>
#include <ipxe/image.h>
#include <ipxe/cpuid.h>
#include <ipxe/msr.h>
#include <ipxe/mp.h>
#include <ipxe/timer.h>
#include <ipxe/ucode.h>
/**
* Maximum number of hyperthread siblings
*
* Microcode updates must not be performed on hyperthread siblings at
* the same time, since they share microcode storage.
*
* Hyperthread siblings are always the lowest level of the CPU
* topology and correspond to the least significant bits of the APIC
* ID. We may therefore avoid collisions by performing the microcode
* updates in batches, with each batch targeting just one value for
* the least significant N bits of the APIC ID.
*
* We assume that no CPUs exist with more than this number of
* hyperthread siblings. (This must be a power of two.)
*/
#define UCODE_MAX_HT 8
/** Time to wait for a microcode update to complete */
#define UCODE_WAIT_MS 10
/** A CPU vendor string */
union ucode_vendor_id {
/** CPUID registers */
uint32_t dword[3];
/** Human-readable string */
uint8_t string[12];
};
/** A CPU vendor */
struct ucode_vendor {
/** Vendor string */
union ucode_vendor_id id;
/** Microcode load trigger MSR */
uint32_t trigger_msr;
/** Microcode version requires manual clear */
uint8_t ver_clear;
/** Microcode version is reported via high dword */
uint8_t ver_high;
};
/** A microcode update */
struct ucode_update {
/** CPU vendor, if known */
struct ucode_vendor *vendor;
/** Boot processor CPU signature */
uint32_t signature;
/** Platform ID */
uint32_t platform;
/** Number of potentially relevant signatures found */
unsigned int count;
/** Update descriptors (if being populated) */
struct ucode_descriptor *desc;
};
/** A microcode update summary */
struct ucode_summary {
/** Number of CPUs processed */
unsigned int count;
/** Lowest observed microcode version */
int32_t low;
/** Highest observed microcode version */
int32_t high;
};
/** Intel CPU vendor */
static struct ucode_vendor ucode_intel = {
.id = { .string = "GenuineIntel" },
.ver_clear = 1,
.ver_high = 1,
.trigger_msr = MSR_UCODE_TRIGGER_INTEL,
};
/** AMD CPU vendor */
static struct ucode_vendor ucode_amd = {
.id = { .string = "AuthenticAMD" },
.trigger_msr = MSR_UCODE_TRIGGER_AMD,
};
/** List of known CPU vendors */
static struct ucode_vendor *ucode_vendors[] = {
&ucode_intel,
&ucode_amd,
};
/**
* Get CPU vendor name (for debugging)
*
* @v vendor CPU vendor
* @ret name Name
*/
static const char * ucode_vendor_name ( const union ucode_vendor_id *vendor ) {
static union {
union ucode_vendor_id vendor;
char text[ sizeof ( *vendor ) + 1 /* NUL */ ];
} u;
/* Construct name */
memcpy ( &u.vendor, vendor, sizeof ( u.vendor ) );
u.text[ sizeof ( u.text ) - 1 ] = '\0';
return u.text;
}
/**
* Check status report
*
* @v update Microcode update
* @v control Microcode update control
* @v summary Microcode update summary
* @v id APIC ID
* @v optional Status report is optional
* @ret rc Return status code
*/
static int ucode_status ( struct ucode_update *update,
struct ucode_control *control,
struct ucode_summary *summary,
unsigned int id, int optional ) {
struct ucode_status status;
struct ucode_descriptor *desc;
/* Sanity check */
assert ( id <= control->apic_max );
/* Read status report */
copy_from_user ( &status, phys_to_user ( control->status ),
( id * sizeof ( status ) ), sizeof ( status ) );
/* Ignore empty optional status reports */
if ( optional && ( ! status.signature ) )
return 0;
DBGC ( update, "UCODE %#08x signature %#08x ucode %#08x->%#08x\n",
id, status.signature, status.before, status.after );
/* Check CPU signature */
if ( ! status.signature ) {
DBGC2 ( update, "UCODE %#08x has no signature\n", id );
return -ENOENT;
}
/* Check APIC ID is correct */
if ( status.id != id ) {
DBGC ( update, "UCODE %#08x wrong APIC ID %#08x\n",
id, status.id );
return -EINVAL;
}
/* Check that maximum APIC ID was not exceeded */
if ( control->apic_unexpected ) {
DBGC ( update, "UCODE %#08x saw unexpected APIC ID %#08x\n",
id, control->apic_unexpected );
return -ERANGE;
}
/* Check microcode was not downgraded */
if ( status.after < status.before ) {
DBGC ( update, "UCODE %#08x was downgraded %#08x->%#08x\n",
id, status.before, status.after );
return -ENOTTY;
}
/* Check that expected updates (if any) were applied */
for ( desc = update->desc ; desc->signature ; desc++ ) {
if ( ( desc->signature == status.signature ) &&
( status.after < desc->version ) ) {
DBGC ( update, "UCODE %#08x failed update %#08x->%#08x "
"(wanted %#08x)\n", id, status.before,
status.after, desc->version );
return -EIO;
}
}
/* Update summary */
summary->count++;
if ( status.before < summary->low )
summary->low = status.before;
if ( status.after > summary->high )
summary->high = status.after;
return 0;
}
/**
* Update microcode on all CPUs
*
* @v image Microcode image
* @v update Microcode update
* @v summary Microcode update summary to fill in
* @ret rc Return status code
*/
static int ucode_update_all ( struct image *image,
struct ucode_update *update,
struct ucode_summary *summary ) {
struct ucode_control control;
struct ucode_vendor *vendor;
userptr_t status;
unsigned int max;
unsigned int i;
size_t len;
int rc;
/* Initialise summary */
summary->count = 0;
summary->low = UCODE_VERSION_MAX;
summary->high = UCODE_VERSION_MIN;
/* Allocate status reports */
max = mp_max_cpuid();
len = ( ( max + 1 ) * sizeof ( struct ucode_status ) );
status = umalloc ( len );
if ( ! status ) {
DBGC ( image, "UCODE %s could not allocate %d status reports\n",
image->name, ( max + 1 ) );
rc = -ENOMEM;
goto err_alloc;
}
memset_user ( status, 0, 0, len );
/* Construct control structure */
memset ( &control, 0, sizeof ( control ) );
control.desc = virt_to_phys ( update->desc );
control.status = user_to_phys ( status, 0 );
vendor = update->vendor;
if ( vendor ) {
control.ver_clear = vendor->ver_clear;
control.ver_high = vendor->ver_high;
control.trigger_msr = vendor->trigger_msr;
} else {
assert ( update->count == 0 );
}
control.apic_max = max;
/* Update microcode on boot processor */
mp_exec_boot ( ucode_update, &control );
if ( ( rc = ucode_status ( update, &control, summary,
mp_boot_cpuid(), 0 ) ) != 0 ) {
DBGC ( image, "UCODE %s failed on boot processor: %s\n",
image->name, strerror ( rc ) );
goto err_boot;
}
/* Update microcode on application processors, avoiding
* simultaneous updates on hyperthread siblings.
*/
build_assert ( ( UCODE_MAX_HT & ( UCODE_MAX_HT - 1 ) ) == 0 );
control.apic_mask = ( UCODE_MAX_HT - 1 );
for ( ; control.apic_test <= control.apic_mask ; control.apic_test++ ) {
mp_start_all ( ucode_update, &control );
mdelay ( UCODE_WAIT_MS );
}
/* Check status reports */
summary->count = 0;
for ( i = 0 ; i <= max ; i++ ) {
if ( ( rc = ucode_status ( update, &control, summary,
i, 1 ) ) != 0 ) {
goto err_status;
}
}
/* Success */
rc = 0;
err_status:
err_boot:
ufree ( status );
err_alloc:
return rc;
}
/**
* Add descriptor to list (if applicable)
*
* @v image Microcode image
* @v start Starting offset within image
* @v vendor CPU vendor
* @v desc Microcode descriptor
* @v platforms Supported platforms, or 0 for all platforms
* @v update Microcode update
*/
static void ucode_describe ( struct image *image, size_t start,
const struct ucode_vendor *vendor,
const struct ucode_descriptor *desc,
uint32_t platforms, struct ucode_update *update ) {
/* Dump descriptor information */
DBGC2 ( image, "UCODE %s+%#04zx %s %#08x", image->name, start,
ucode_vendor_name ( &vendor->id ), desc->signature );
if ( platforms )
DBGC2 ( image, " (%#02x)", platforms );
DBGC2 ( image, " version %#08x\n", desc->version );
/* Check applicability */
if ( vendor != update->vendor )
return;
if ( ( desc->signature ^ update->signature ) & UCODE_SIGNATURE_MASK )
return;
if ( platforms && ( ! ( platforms & update->platform ) ) )
return;
/* Add descriptor, if applicable */
if ( update->desc ) {
memcpy ( &update->desc[update->count], desc, sizeof ( *desc ) );
DBGC ( image, "UCODE %s+%#04zx found %s %#08x version %#08x\n",
image->name, start, ucode_vendor_name ( &vendor->id ),
desc->signature, desc->version );
}
update->count++;
}
/**
* Verify checksum
*
* @v image Microcode image
* @v start Starting offset
* @v len Length
* @ret rc Return status code
*/
static int ucode_verify ( struct image *image, size_t start, size_t len ) {
uint32_t checksum = 0;
uint32_t dword;
size_t offset;
/* Check length is a multiple of dwords */
if ( ( len % sizeof ( dword ) ) != 0 ) {
DBGC ( image, "UCODE %s+%#04zx invalid length %#zx\n",
image->name, start, len );
return -EINVAL;
}
/* Calculate checksum */
for ( offset = start ; len ;
offset += sizeof ( dword ), len -= sizeof ( dword ) ) {
copy_from_user ( &dword, image->data, offset,
sizeof ( dword ) );
checksum += dword;
}
if ( checksum != 0 ) {
DBGC ( image, "UCODE %s+%#04zx bad checksum %#08x\n",
image->name, start, checksum );
return -EINVAL;
}
return 0;
}
/**
* Parse Intel microcode image
*
* @v image Microcode image
* @v start Starting offset within image
* @v update Microcode update
* @ret len Length consumed, or negative error
*/
static int ucode_parse_intel ( struct image *image, size_t start,
struct ucode_update *update ) {
struct intel_ucode_header hdr;
struct intel_ucode_ext_header exthdr;
struct intel_ucode_ext ext;
struct ucode_descriptor desc;
size_t remaining;
size_t offset;
size_t data_len;
size_t len;
unsigned int i;
int rc;
/* Read header */
remaining = ( image->len - start );
if ( remaining < sizeof ( hdr ) ) {
DBGC ( image, "UCODE %s+%#04zx too small for Intel header\n",
image->name, start );
return -ENOEXEC;
}
copy_from_user ( &hdr, image->data, start, sizeof ( hdr ) );
/* Determine lengths */
data_len = hdr.data_len;
if ( ! data_len )
data_len = INTEL_UCODE_DATA_LEN;
len = hdr.len;
if ( ! len )
len = ( sizeof ( hdr ) + data_len );
/* Verify a selection of fields */
if ( ( hdr.hver != INTEL_UCODE_HVER ) ||
( hdr.lver != INTEL_UCODE_LVER ) ||
( len < sizeof ( hdr ) ) ||
( len > remaining ) ||
( data_len > ( len - sizeof ( hdr ) ) ) ||
( ( data_len % sizeof ( uint32_t ) ) != 0 ) ||
( ( len % INTEL_UCODE_ALIGN ) != 0 ) ) {
DBGC2 ( image, "UCODE %s+%#04zx is not an Intel update\n",
image->name, start );
return -EINVAL;
}
DBGC2 ( image, "UCODE %s+%#04zx is an Intel update\n",
image->name, start );
/* Verify checksum */
if ( ( rc = ucode_verify ( image, start, len ) ) != 0 )
return rc;
/* Populate descriptor */
desc.signature = hdr.signature;
desc.version = hdr.version;
desc.address = user_to_phys ( image->data,
( start + sizeof ( hdr ) ) );
/* Add non-extended descriptor, if applicable */
ucode_describe ( image, start, &ucode_intel, &desc, hdr.platforms,
update );
/* Construct extended descriptors, if applicable */
offset = ( sizeof ( hdr ) + data_len );
if ( offset <= ( len - sizeof ( exthdr ) ) ) {
/* Read extended header */
copy_from_user ( &exthdr, image->data, ( start + offset ),
sizeof ( exthdr ) );
offset += sizeof ( exthdr );
/* Read extended signatures */
for ( i = 0 ; i < exthdr.count ; i++ ) {
/* Read extended signature */
if ( offset > ( len - sizeof ( ext ) ) ) {
DBGC ( image, "UCODE %s+%#04zx extended "
"signature overrun\n",
image->name, start );
return -EINVAL;
}
copy_from_user ( &ext, image->data, ( start + offset ),
sizeof ( ext ) );
offset += sizeof ( ext );
/* Avoid duplicating non-extended descriptor */
if ( ( ext.signature == hdr.signature ) &&
( ext.platforms == hdr.platforms ) ) {
continue;
}
/* Construct descriptor, if applicable */
desc.signature = ext.signature;
ucode_describe ( image, start, &ucode_intel, &desc,
ext.platforms, update );
}
}
return len;
}
/**
* Parse AMD microcode image
*
* @v image Microcode image
* @v start Starting offset within image
* @v update Microcode update
* @ret len Length consumed, or negative error
*/
static int ucode_parse_amd ( struct image *image, size_t start,
struct ucode_update *update ) {
struct amd_ucode_header hdr;
struct amd_ucode_equivalence equiv;
struct amd_ucode_patch_header phdr;
struct amd_ucode_patch patch;
struct ucode_descriptor desc;
size_t remaining;
size_t offset;
unsigned int count;
unsigned int used;
unsigned int i;
/* Read header */
remaining = ( image->len - start );
if ( remaining < sizeof ( hdr ) ) {
DBGC ( image, "UCODE %s+%#04zx too small for AMD header\n",
image->name, start );
return -ENOEXEC;
}
copy_from_user ( &hdr, image->data, start, sizeof ( hdr ) );
/* Check header */
if ( hdr.magic != AMD_UCODE_MAGIC ) {
DBGC2 ( image, "UCODE %s+%#04zx is not an AMD update\n",
image->name, start );
return -ENOEXEC;
}
DBGC2 ( image, "UCODE %s+%#04zx is an AMD update\n",
image->name, start );
if ( hdr.type != AMD_UCODE_EQUIV_TYPE ) {
DBGC ( image, "UCODE %s+%#04zx unsupported equivalence table "
"type %d\n", image->name, start, hdr.type );
return -ENOTSUP;
}
if ( hdr.len > ( remaining - sizeof ( hdr ) ) ) {
DBGC ( image, "UCODE %s+%#04zx truncated equivalence table\n",
image->name, start );
return -EINVAL;
}
/* Count number of equivalence table entries */
offset = sizeof ( hdr );
for ( count = 0 ; offset < ( sizeof ( hdr ) + hdr.len ) ;
count++, offset += sizeof ( equiv ) ) {
copy_from_user ( &equiv, image->data, ( start + offset ),
sizeof ( equiv ) );
if ( ! equiv.signature )
break;
}
DBGC2 ( image, "UCODE %s+%#04zx has %d equivalence table entries\n",
image->name, start, count );
/* Parse available updates */
offset = ( sizeof ( hdr ) + hdr.len );
used = 0;
while ( used < count ) {
/* Read patch header */
if ( ( offset + sizeof ( phdr ) ) > remaining ) {
DBGC ( image, "UCODE %s+%#04zx truncated patch "
"header\n", image->name, start );
return -EINVAL;
}
copy_from_user ( &phdr, image->data, ( start + offset ),
sizeof ( phdr ) );
offset += sizeof ( phdr );
/* Validate patch header */
if ( phdr.type != AMD_UCODE_PATCH_TYPE ) {
DBGC ( image, "UCODE %s+%#04zx unsupported patch type "
"%d\n", image->name, start, phdr.type );
return -ENOTSUP;
}
if ( phdr.len < sizeof ( patch ) ) {
DBGC ( image, "UCODE %s+%#04zx underlength patch\n",
image->name, start );
return -EINVAL;
}
if ( phdr.len > ( remaining - offset ) ) {
DBGC ( image, "UCODE %s+%#04zx truncated patch\n",
image->name, start );
return -EINVAL;
}
/* Read patch and construct descriptor */
copy_from_user ( &patch, image->data, ( start + offset ),
sizeof ( patch ) );
desc.version = patch.version;
desc.address = user_to_phys ( image->data, ( start + offset ) );
offset += phdr.len;
/* Parse equivalence table to find matching signatures */
for ( i = 0 ; i < count ; i++ ) {
copy_from_user ( &equiv, image->data,
( start + sizeof ( hdr ) +
( i * ( sizeof ( equiv ) ) ) ),
sizeof ( equiv ) );
if ( patch.id == equiv.id ) {
desc.signature = equiv.signature;
ucode_describe ( image, start, &ucode_amd,
&desc, 0, update );
used++;
}
}
}
return offset;
}
/**
* Parse microcode image
*
* @v image Microcode image
* @v update Microcode update
* @ret rc Return status code
*/
static int ucode_parse ( struct image *image, struct ucode_update *update ) {
size_t start;
int len;
/* Attempt to parse concatenated microcode updates */
for ( start = 0 ; start < image->len ; start += len ) {
/* Attempt to parse as Intel microcode */
len = ucode_parse_intel ( image, start, update );
if ( len > 0 )
continue;
/* Attempt to parse as AMD microcode */
len = ucode_parse_amd ( image, start, update );
if ( len > 0 )
continue;
/* Not a recognised microcode format */
DBGC ( image, "UCODE %s+%zx not recognised\n",
image->name, start );
return -ENOEXEC;
}
return 0;
}
/**
* Execute microcode update
*
* @v image Microcode image
* @ret rc Return status code
*/
static int ucode_exec ( struct image *image ) {
struct ucode_update update;
struct ucode_vendor *vendor;
struct ucode_summary summary;
union ucode_vendor_id id;
uint64_t platform_id;
uint32_t discard_a;
uint32_t discard_b;
uint32_t discard_c;
uint32_t discard_d;
unsigned int check;
unsigned int i;
size_t len;
int rc;
/* Initialise update */
memset ( &update, 0, sizeof ( update ) );
cpuid ( CPUID_VENDOR_ID, 0, &discard_a, &id.dword[0], &id.dword[2],
&id.dword[1] );
cpuid ( CPUID_FEATURES, 0, &update.signature, &discard_b,
&discard_c, &discard_d );
/* Identify CPU vendor, if recognised */
for ( i = 0 ; i < ( sizeof ( ucode_vendors ) /
sizeof ( ucode_vendors[0] ) ) ; i++ ) {
vendor = ucode_vendors[i];
if ( memcmp ( &id, &vendor->id, sizeof ( id ) ) == 0 )
update.vendor = vendor;
}
/* Identify platform, if applicable */
if ( update.vendor == &ucode_intel ) {
platform_id = rdmsr ( MSR_PLATFORM_ID );
update.platform =
( 1 << MSR_PLATFORM_ID_VALUE ( platform_id ) );
}
/* Count number of matching update descriptors */
DBGC ( image, "UCODE %s applying to %s %#08x",
image->name, ucode_vendor_name ( &id ), update.signature );
if ( update.platform )
DBGC ( image, " (%#02x)", update.platform );
DBGC ( image, "\n" );
if ( ( rc = ucode_parse ( image, &update ) ) != 0 )
goto err_count;
DBGC ( image, "UCODE %s found %d matching update(s)\n",
image->name, update.count );
/* Allocate descriptors */
len = ( ( update.count + 1 /* terminator */ ) *
sizeof ( update.desc[0] ) );
update.desc = zalloc ( len );
if ( ! update.desc ) {
rc = -ENOMEM;
goto err_alloc;
}
/* Populate descriptors */
check = update.count;
update.count = 0;
if ( ( rc = ucode_parse ( image, &update ) ) != 0 )
goto err_parse;
assert ( check == update.count );
/* Perform update */
if ( ( rc = ucode_update_all ( image, &update, &summary ) ) != 0 )
goto err_update;
/* Print summary if directed to do so */
if ( image->cmdline && ( strstr ( image->cmdline, "-v" ) ) ) {
printf ( "Microcode: " );
if ( summary.low == summary.high ) {
printf ( "already version %#x", summary.low );
} else {
printf ( "updated version %#x->%#x",
summary.low, summary.high );
}
printf ( " (x%d)\n", summary.count );
}
err_update:
err_parse:
free ( update.desc );
err_alloc:
err_count:
return rc;
}
/**
* Probe microcode update image
*
* @v image Microcode image
* @ret rc Return status code
*/
static int ucode_probe ( struct image *image ) {
union {
struct intel_ucode_header intel;
struct amd_ucode_header amd;
} header;
/* Sanity check */
if ( image->len < sizeof ( header ) ) {
DBGC ( image, "UCODE %s too short\n", image->name );
return -ENOEXEC;
}
/* Read first microcode image header */
copy_from_user ( &header, image->data, 0, sizeof ( header ) );
/* Check for something that looks like an Intel update
*
* Intel updates unfortunately have no magic signatures or
* other easily verifiable fields. We check a small selection
* of header fields that can be easily verified.
*
* We do not attempt to fully parse the update, since we want
* errors to be reported at the point of attempting to execute
* the image, and do not want to have a microcode image
* erroneously treated as a PXE boot executable.
*/
if ( ( header.intel.hver == INTEL_UCODE_HVER ) &&
( header.intel.lver == INTEL_UCODE_LVER ) &&
( ( header.intel.date.century == 0x19 ) ||
( ( header.intel.date.century >= 0x20 ) &&
( header.intel.date.century <= 0x29 ) ) ) ) {
DBGC ( image, "UCODE %s+%#04zx looks like an Intel update\n",
image->name, ( ( size_t ) 0 ) );
return 0;
}
/* Check for AMD update signature */
if ( ( header.amd.magic == AMD_UCODE_MAGIC ) &&
( header.amd.type == AMD_UCODE_EQUIV_TYPE ) ) {
DBGC ( image, "UCODE %s+%#04zx looks like an AMD update\n",
image->name, ( ( size_t ) 0 ) );
return 0;
}
return -ENOEXEC;
}
/** Microcode update image type */
struct image_type ucode_image_type __image_type ( PROBE_NORMAL ) = {
.name = "ucode",
.probe = ucode_probe,
.exec = ucode_exec,
};

View File

@ -323,9 +323,7 @@ bigint_done_raw ( const uint32_t *value0, unsigned int size __unused,
}
extern void bigint_multiply_raw ( const uint32_t *multiplicand0,
unsigned int multiplicand_size,
const uint32_t *multiplier0,
unsigned int multiplier_size,
uint32_t *value0 );
uint32_t *value0, unsigned int size );
#endif /* _BITS_BIGINT_H */

View File

@ -44,7 +44,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define ERRFILE_sdi ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000b0000 )
#define ERRFILE_initrd ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000c0000 )
#define ERRFILE_pxe_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000d0000 )
#define ERRFILE_ucode ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000e0000 )
#define ERRFILE_undi ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 )
#define ERRFILE_undiload ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 )

View File

@ -1,14 +0,0 @@
#ifndef _BITS_MP_H
#define _BITS_MP_H
/** @file
*
* x86-specific multiprocessor API implementation
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/bios_mp.h>
#endif /* _BITS_MP_H */

View File

@ -1,32 +0,0 @@
#ifndef _IPXE_BIOS_MP_H
#define _IPXE_BIOS_MP_H
/** @file
*
* BIOS multiprocessor API implementation
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/io.h>
#ifdef MPAPI_PCBIOS
#define MPAPI_PREFIX_pcbios
#else
#define MPAPI_PREFIX_pcbios __pcbios_
#endif
/**
* Calculate address as seen by a multiprocessor function
*
* @v address Address in boot processor address space
* @ret address Address in application processor address space
*/
static inline __attribute__ (( always_inline )) mp_addr_t
MPAPI_INLINE ( pcbios, mp_address ) ( void *address ) {
return virt_to_phys ( address );
}
#endif /* _IPXE_BIOS_MP_H */

View File

@ -1,223 +0,0 @@
#ifndef _IPXE_UCODE_H
#define _IPXE_UCODE_H
/** @file
*
* Microcode updates
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/mp.h>
/** Platform ID MSR */
#define MSR_PLATFORM_ID 0x00000017UL
/** Extract platform ID from MSR value */
#define MSR_PLATFORM_ID_VALUE( value ) ( ( (value) >> 50 ) & 0x7 )
/** Intel microcode load trigger MSR */
#define MSR_UCODE_TRIGGER_INTEL 0x00000079UL
/** AMD microcode load trigger MSR */
#define MSR_UCODE_TRIGGER_AMD 0xc0010020UL
/** CPUID signature applicability mask
*
* We assume that only steppings may vary between the boot CPU and any
* application processors.
*/
#define UCODE_SIGNATURE_MASK 0xfffffff0UL
/** Minimum possible microcode version */
#define UCODE_VERSION_MIN -0x80000000L
/** Maximum possible microcode version */
#define UCODE_VERSION_MAX 0x7fffffffL
/** A microcode update control
*
* This must match the layout as used by the assembly code in
* ucode_mp.S.
*/
struct ucode_control {
/** Microcode descriptor list physical address */
uint64_t desc;
/** Microcode status array physical address */
uint64_t status;
/** Microcode load trigger MSR */
uint32_t trigger_msr;
/** Maximum expected APIC ID */
uint32_t apic_max;
/** Unexpected APIC ID
*
* Any application processor may set this to indicate that its
* APIC ID was higher than the maximum expected APIC ID.
*/
uint32_t apic_unexpected;
/** APIC ID eligibility mask bits */
uint32_t apic_mask;
/** APIC ID eligibility test bits */
uint32_t apic_test;
/** Microcode version requires manual clear */
uint8_t ver_clear;
/** Microcode version is reported via high dword */
uint8_t ver_high;
} __attribute__ (( packed ));
/** A microcode update descriptor
*
* This must match the layout as used by the assembly code in
* ucode_mp.S.
*/
struct ucode_descriptor {
/** CPUID signature (or 0 to terminate list) */
uint32_t signature;
/** Microcode version */
int32_t version;
/** Microcode physical address */
uint64_t address;
} __attribute__ (( packed ));
/** A microcode update status report
*
* This must match the layout as used by the assembly code in
* ucode_mp.S.
*/
struct ucode_status {
/** CPU signature */
uint32_t signature;
/** APIC ID (for sanity checking) */
uint32_t id;
/** Initial microcode version */
int32_t before;
/** Final microcode version */
int32_t after;
} __attribute__ (( packed ));
/** A microcode date */
struct ucode_date {
/** Year (BCD) */
uint8_t year;
/** Century (BCD) */
uint8_t century;
/** Day (BCD) */
uint8_t day;
/** Month (BCD) */
uint8_t month;
} __attribute__ (( packed ));
/** An Intel microcode update file header */
struct intel_ucode_header {
/** Header version number */
uint32_t hver;
/** Microcode version */
int32_t version;
/** Date */
struct ucode_date date;
/** CPUID signature */
uint32_t signature;
/** Checksum */
uint32_t checksum;
/** Loader version */
uint32_t lver;
/** Supported platforms */
uint32_t platforms;
/** Microcode data size (or 0 to indicate 2000 bytes) */
uint32_t data_len;
/** Total size (or 0 to indicate 2048 bytes) */
uint32_t len;
/** Reserved */
uint8_t reserved[12];
} __attribute__ (( packed ));
/** Intel microcode header version number */
#define INTEL_UCODE_HVER 0x00000001UL
/** Intel microcode loader version number */
#define INTEL_UCODE_LVER 0x00000001UL
/** Intel microcode default data length */
#define INTEL_UCODE_DATA_LEN 2000
/** Intel microcode file alignment */
#define INTEL_UCODE_ALIGN 1024
/** An Intel microcode update file extended header */
struct intel_ucode_ext_header {
/** Extended signature count */
uint32_t count;
/** Extended checksum */
uint32_t checksum;
/** Reserved */
uint8_t reserved[12];
} __attribute__ (( packed ));
/** An Intel microcode extended signature */
struct intel_ucode_ext {
/** CPUID signature */
uint32_t signature;
/** Supported platforms */
uint32_t platforms;
/** Checksum */
uint32_t checksum;
} __attribute__ (( packed ));
/** An AMD microcode update file header */
struct amd_ucode_header {
/** Magic signature */
uint32_t magic;
/** Equivalence table type */
uint32_t type;
/** Equivalence table length */
uint32_t len;
} __attribute__ (( packed ));
/** AMD microcode magic signature */
#define AMD_UCODE_MAGIC ( ( 'A' << 16 ) | ( 'M' << 8 ) | ( 'D' << 0 ) )
/** AMD microcode equivalence table type */
#define AMD_UCODE_EQUIV_TYPE 0x00000000UL
/** An AMD microcode equivalence table entry */
struct amd_ucode_equivalence {
/** CPU signature */
uint32_t signature;
/** Reserved */
uint8_t reserved_a[8];
/** Equivalence ID */
uint16_t id;
/** Reserved */
uint8_t reserved_b[2];
} __attribute__ (( packed ));
/** An AMD microcode patch header */
struct amd_ucode_patch_header {
/** Patch type */
uint32_t type;
/** Patch length */
uint32_t len;
} __attribute__ (( packed ));
/** An AMD microcode patch */
struct amd_ucode_patch {
/** Date */
struct ucode_date date;
/** Microcode version */
int32_t version;
/** Reserved */
uint8_t reserved_a[16];
/** Equivalence ID */
uint16_t id;
/** Reserved */
uint8_t reserved_b[14];
} __attribute__ (( packed ));
/** AMD patch type */
#define AMD_UCODE_PATCH_TYPE 0x00000001UL
extern mp_func_t ucode_update;
#endif /* _IPXE_UCODE_H */

View File

@ -250,10 +250,8 @@ extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
/* CODE_DEFAULT: restore default .code32/.code64 directive */
#ifdef __x86_64__
#define CODE_DEFAULT ".code64"
#define STACK_DEFAULT "q"
#else
#define CODE_DEFAULT ".code32"
#define STACK_DEFAULT "l"
#endif
/* LINE_SYMBOL: declare a symbol for the current source code line */
@ -270,7 +268,7 @@ extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
/* REAL_CODE: declare a fragment of code that executes in real mode */
#define REAL_CODE( asm_code_str ) \
"push" STACK_DEFAULT " $1f\n\t" \
"push $1f\n\t" \
"call real_call\n\t" \
TEXT16_CODE ( "\n1:\n\t" \
asm_code_str \
@ -279,7 +277,7 @@ extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
/* PHYS_CODE: declare a fragment of code that executes in flat physical mode */
#define PHYS_CODE( asm_code_str ) \
"push" STACK_DEFAULT " $1f\n\t" \
"push $1f\n\t" \
"call phys_call\n\t" \
".section \".text.phys\", \"ax\", @progbits\n\t"\
"\n" LINE_SYMBOL "\n\t" \
@ -474,26 +472,6 @@ extern struct page_table io_pages;
*/
#define IO_BASE ( ( void * ) 0x100000000ULL )
/** Startup IPI real-mode handler */
extern char __text16_array ( sipi, [] );
#define sipi __use_text16 ( sipi )
/** Length of startup IPI real-mode handler */
extern char sipi_len[];
/** Startup IPI real-mode handler copy of real-mode data segment */
extern uint16_t __text16 ( sipi_ds );
#define sipi_ds __use_text16 ( sipi_ds )
/** Startup IPI protected-mode handler (physical address) */
extern uint32_t sipi_handler;
/** Startup IPI register state */
extern struct i386_regs sipi_regs;
extern void setup_sipi ( unsigned int vector, uint32_t handler,
struct i386_regs *regs );
#endif /* ASSEMBLY */
#endif /* LIBRM_H */

View File

@ -46,12 +46,8 @@ static void efix86_cpu_nap ( void ) {
* The EFI shell doesn't seem to bother sleeping the CPU; it
* just sits there idly burning power.
*
* If a shutdown is in progess, there may be nothing to
* generate an interrupt since the timer is disabled in the
* first step of ExitBootServices().
*/
if ( ! efi_shutdown_in_progress )
__asm__ __volatile__ ( "hlt" );
__asm__ __volatile__ ( "hlt" );
}
PROVIDE_NAP ( efix86, cpu_nap, efix86_cpu_nap );

View File

@ -290,38 +290,29 @@ static const char *bios_ansi_input = "";
struct bios_key {
/** Scancode */
uint8_t scancode;
/** Relative key value */
uint16_t rkey;
/** Key code */
uint16_t key;
} __attribute__ (( packed ));
/**
* Define a BIOS key mapping
*
* @v scancode Scancode
* @v key iPXE key code
* @v bioskey BIOS key mapping
*/
#define BIOS_KEY( scancode, key ) { scancode, KEY_REL ( key ) }
/** Mapping from BIOS scan codes to iPXE key codes */
static const struct bios_key bios_keys[] = {
BIOS_KEY ( 0x53, KEY_DC ),
BIOS_KEY ( 0x48, KEY_UP ),
BIOS_KEY ( 0x50, KEY_DOWN ),
BIOS_KEY ( 0x4b, KEY_LEFT ),
BIOS_KEY ( 0x4d, KEY_RIGHT ),
BIOS_KEY ( 0x47, KEY_HOME ),
BIOS_KEY ( 0x4f, KEY_END ),
BIOS_KEY ( 0x49, KEY_PPAGE ),
BIOS_KEY ( 0x51, KEY_NPAGE ),
BIOS_KEY ( 0x3f, KEY_F5 ),
BIOS_KEY ( 0x40, KEY_F6 ),
BIOS_KEY ( 0x41, KEY_F7 ),
BIOS_KEY ( 0x42, KEY_F8 ),
BIOS_KEY ( 0x43, KEY_F9 ),
BIOS_KEY ( 0x44, KEY_F10 ),
BIOS_KEY ( 0x85, KEY_F11 ),
BIOS_KEY ( 0x86, KEY_F12 ),
{ 0x53, KEY_DC },
{ 0x48, KEY_UP },
{ 0x50, KEY_DOWN },
{ 0x4b, KEY_LEFT },
{ 0x4d, KEY_RIGHT },
{ 0x47, KEY_HOME },
{ 0x4f, KEY_END },
{ 0x49, KEY_PPAGE },
{ 0x51, KEY_NPAGE },
{ 0x3f, KEY_F5 },
{ 0x40, KEY_F6 },
{ 0x41, KEY_F7 },
{ 0x42, KEY_F8 },
{ 0x43, KEY_F9 },
{ 0x44, KEY_F10 },
{ 0x85, KEY_F11 },
{ 0x86, KEY_F12 },
};
/**
@ -332,7 +323,7 @@ static const struct bios_key bios_keys[] = {
*/
static const char * bios_ansi_seq ( unsigned int scancode ) {
static char buf[ 5 /* "[" + two digits + terminator + NUL */ ];
unsigned int rkey;
unsigned int key;
unsigned int terminator;
unsigned int n;
unsigned int i;
@ -347,9 +338,9 @@ static const char * bios_ansi_seq ( unsigned int scancode ) {
continue;
/* Construct escape sequence */
rkey = bios_keys[i].rkey;
n = KEY_ANSI_N ( rkey );
terminator = KEY_ANSI_TERMINATOR ( rkey );
key = bios_keys[i].key;
n = KEY_ANSI_N ( key );
terminator = KEY_ANSI_TERMINATOR ( key );
*(tmp++) = '[';
if ( n )
tmp += sprintf ( tmp, "%d", n );
@ -488,7 +479,6 @@ struct console_driver bios_console __console_driver = {
static __asmcall __used void bios_inject ( struct i386_all_regs *ix86 ) {
unsigned int discard_a;
unsigned int scancode;
unsigned int rkey;
unsigned int i;
uint16_t keypress;
int key;
@ -531,10 +521,9 @@ static __asmcall __used void bios_inject ( struct i386_all_regs *ix86 ) {
/* Handle special keys */
if ( key >= KEY_MIN ) {
rkey = KEY_REL ( key );
for ( i = 0 ; i < ( sizeof ( bios_keys ) /
sizeof ( bios_keys[0] ) ) ; i++ ) {
if ( bios_keys[i].rkey == rkey ) {
if ( bios_keys[i].key == key ) {
scancode = bios_keys[i].scancode;
keypress = ( scancode << 8 );
break;

View File

@ -1,173 +0,0 @@
/*
* Copyright (C) 2024 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
*
* BIOS multiprocessor API implementation
*
*/
#include <registers.h>
#include <ipxe/uaccess.h>
#include <ipxe/timer.h>
#include <ipxe/msr.h>
#include <ipxe/mp.h>
/** Local APIC base address MSR */
#define MSR_APIC_BASE 0x0000001b
/** Local APIC is in x2APIC mode */
#define MSR_APIC_BASE_X2APIC 0x400
/** Local APIC base address mask */
#define MSR_APIC_BASE_MASK ( ~0xfffULL )
/** Interrupt command register */
#define APIC_ICR 0x0300
/** Interrupt command register (x2APIC) */
#define MSR_X2APIC_ICR 0x830
/** Interrupt command register: send to all excluding self */
#define APIC_ICR_ALL_NOT_SELF 0x000c0000
/** Interrupt command register: level mode */
#define APIC_ICR_LEVEL 0x00008000
/** Interrupt command register: level asserted */
#define APIC_ICR_LEVEL_ASSERT 0x00004000
/** Interrupt command register: INIT */
#define APIC_ICR_INIT 0x00000500
/** Interrupt command register: SIPI */
#define APIC_ICR_SIPI( vector ) ( 0x00000600 | (vector) )
/** Time to wait for an IPI to complete */
#define IPI_WAIT_MS 10
/**
* Startup IPI vector
*
* The real-mode startup IPI code must be copied to a page boundary in
* base memory. We fairly arbitrarily choose to place this at 0x8000.
*/
#define SIPI_VECTOR 0x08
/** Protected-mode startup IPI handler */
extern void __asmcall mp_jump ( mp_addr_t func, mp_addr_t opaque );
/**
* Execute a multiprocessor function on the boot processor
*
* @v func Multiprocessor function
* @v opaque Opaque data pointer
*/
static void bios_mp_exec_boot ( mp_func_t func, void *opaque ) {
/* Call multiprocessor function with physical addressing */
__asm__ __volatile__ ( PHYS_CODE ( "pushl %k2\n\t"
"pushl %k1\n\t"
"call *%k0\n\t"
"addl $8, %%esp\n\t" )
: : "r" ( mp_address ( mp_call ) ),
"r" ( mp_address ( func ) ),
"r" ( mp_address ( opaque ) ) );
}
/**
* Send an interprocessor interrupt
*
* @v apic APIC base address
* @v x2apic x2APIC mode enabled
* @v icr Interrupt control register value
*/
static void bios_mp_ipi ( void *apic, int x2apic, uint32_t icr ) {
/* Write ICR according to APIC/x2APIC mode */
DBGC ( MSR_APIC_BASE, "BIOSMP sending IPI %#08x\n", icr );
if ( x2apic ) {
wrmsr ( MSR_X2APIC_ICR, icr );
} else {
writel ( icr, ( apic + APIC_ICR ) );
}
/* Allow plenty of time for delivery to complete */
mdelay ( IPI_WAIT_MS );
}
/**
* Start a multiprocessor function on all application processors
*
* @v func Multiprocessor function
* @v opaque Opaque data pointer
*/
static void bios_mp_start_all ( mp_func_t func, void *opaque ) {
struct i386_regs regs;
uint64_t base;
uint32_t ipi;
void *apic;
int x2apic;
/* Prepare SIPI handler */
regs.eax = mp_address ( func );
regs.edx = mp_address ( opaque );
setup_sipi ( SIPI_VECTOR, virt_to_phys ( mp_jump ), &regs );
/* Get local APIC base address and mode */
base = rdmsr ( MSR_APIC_BASE );
x2apic = ( base & MSR_APIC_BASE_X2APIC );
DBGC ( MSR_APIC_BASE, "BIOSMP local %sAPIC base %#llx\n",
( x2apic ? "x2" : "" ), ( ( unsigned long long ) base ) );
/* Map local APIC */
apic = ioremap ( ( base & MSR_APIC_BASE_MASK ), PAGE_SIZE );
if ( ! apic )
goto err_ioremap;
/* Assert INIT IPI */
ipi = ( APIC_ICR_ALL_NOT_SELF | APIC_ICR_LEVEL |
APIC_ICR_LEVEL_ASSERT | APIC_ICR_INIT );
bios_mp_ipi ( apic, x2apic, ipi );
/* Clear INIT IPI */
ipi &= ~APIC_ICR_LEVEL_ASSERT;
bios_mp_ipi ( apic, x2apic, ipi );
/* Send SIPI */
ipi = ( APIC_ICR_ALL_NOT_SELF | APIC_ICR_SIPI ( SIPI_VECTOR ) );
bios_mp_ipi ( apic, x2apic, ipi );
iounmap ( apic );
err_ioremap:
/* No way to handle errors: caller must check that
* multiprocessor function executed as expected.
*/
return;
}
PROVIDE_MPAPI_INLINE ( pcbios, mp_address );
PROVIDE_MPAPI ( pcbios, mp_exec_boot, bios_mp_exec_boot );
PROVIDE_MPAPI ( pcbios, mp_start_all, bios_mp_start_all );

View File

@ -44,11 +44,11 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* @v smbios SMBIOS entry point descriptor structure to fill in
* @ret rc Return status code
*/
static int bios_find_smbios2 ( struct smbios *smbios ) {
static int bios_find_smbios ( struct smbios *smbios ) {
struct smbios_entry entry;
int rc;
/* Scan through BIOS segment to find SMBIOS 32-bit entry point */
/* Scan through BIOS segment to find SMBIOS entry point */
if ( ( rc = find_smbios_entry ( real_to_user ( BIOS_SEG, 0 ), 0x10000,
&entry ) ) != 0 )
return rc;
@ -62,55 +62,4 @@ static int bios_find_smbios2 ( struct smbios *smbios ) {
return 0;
}
/**
* Find SMBIOS
*
* @v smbios SMBIOS entry point descriptor structure to fill in
* @ret rc Return status code
*/
static int bios_find_smbios3 ( struct smbios *smbios ) {
struct smbios3_entry entry;
int rc;
/* Scan through BIOS segment to find SMBIOS 64-bit entry point */
if ( ( rc = find_smbios3_entry ( real_to_user ( BIOS_SEG, 0 ), 0x10000,
&entry ) ) != 0 )
return rc;
/* Check that address is accessible */
if ( entry.smbios_address > ~( ( physaddr_t ) 0 ) ) {
DBG ( "SMBIOS3 at %08llx is inaccessible\n",
( ( unsigned long long ) entry.smbios_address ) );
return -ENOTSUP;
}
/* Fill in entry point descriptor structure */
smbios->address = phys_to_user ( entry.smbios_address );
smbios->len = entry.smbios_len;
smbios->count = 0;
smbios->version = SMBIOS_VERSION ( entry.major, entry.minor );
return 0;
}
/**
* Find SMBIOS
*
* @v smbios SMBIOS entry point descriptor structure to fill in
* @ret rc Return status code
*/
static int bios_find_smbios ( struct smbios *smbios ) {
int rc;
/* Use 32-bit table if present */
if ( ( rc = bios_find_smbios2 ( smbios ) ) == 0 )
return 0;
/* Otherwise, use 64-bit table if present and accessible */
if ( ( rc = bios_find_smbios3 ( smbios ) ) == 0 )
return 0;
return rc;
}
PROVIDE_SMBIOS ( pcbios, find_smbios, bios_find_smbios );

View File

@ -23,9 +23,9 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.code16
.text
.arch i386
.code16
#define SMAP 0x534d4150

View File

@ -183,8 +183,8 @@ static int int13_parse_eltorito ( struct san_device *sandev, void *scratch ) {
/* Read boot record volume descriptor */
if ( ( rc = sandev_read ( sandev, ELTORITO_LBA, 1,
virt_to_user ( boot ) ) ) != 0 ) {
DBGC ( sandev->drive, "INT13 drive %02x could not read El "
"Torito boot record volume descriptor: %s\n",
DBGC ( sandev, "INT13 drive %02x could not read El Torito boot "
"record volume descriptor: %s\n",
sandev->drive, strerror ( rc ) );
return rc;
}
@ -192,11 +192,10 @@ static int int13_parse_eltorito ( struct san_device *sandev, void *scratch ) {
/* Check for an El Torito boot catalog */
if ( memcmp ( boot, &boot_check, sizeof ( boot_check ) ) == 0 ) {
int13->boot_catalog = boot->sector;
DBGC ( sandev->drive, "INT13 drive %02x has an El Torito boot "
"catalog at LBA %08x\n", sandev->drive,
int13->boot_catalog );
DBGC ( sandev, "INT13 drive %02x has an El Torito boot catalog "
"at LBA %08x\n", sandev->drive, int13->boot_catalog );
} else {
DBGC ( sandev->drive, "INT13 drive %02x has no El Torito boot "
DBGC ( sandev, "INT13 drive %02x has no El Torito boot "
"catalog\n", sandev->drive );
}
@ -229,14 +228,14 @@ static int int13_guess_geometry_hdd ( struct san_device *sandev, void *scratch,
/* Read partition table */
if ( ( rc = sandev_read ( sandev, 0, 1, virt_to_user ( mbr ) ) ) != 0 ) {
DBGC ( sandev->drive, "INT13 drive %02x could not read "
DBGC ( sandev, "INT13 drive %02x could not read "
"partition table to guess geometry: %s\n",
sandev->drive, strerror ( rc ) );
return rc;
}
DBGC2 ( sandev->drive, "INT13 drive %02x has MBR:\n", sandev->drive );
DBGC2_HDA ( sandev->drive, 0, mbr, sizeof ( *mbr ) );
DBGC ( sandev->drive, "INT13 drive %02x has signature %08x\n",
DBGC2 ( sandev, "INT13 drive %02x has MBR:\n", sandev->drive );
DBGC2_HDA ( sandev, 0, mbr, sizeof ( *mbr ) );
DBGC ( sandev, "INT13 drive %02x has signature %08x\n",
sandev->drive, mbr->signature );
/* Scan through partition table and modify guesses for
@ -261,8 +260,8 @@ static int int13_guess_geometry_hdd ( struct san_device *sandev, void *scratch,
if ( ( start_cylinder == 0 ) && ( start_head != 0 ) ) {
*sectors = ( ( partition->start + 1 - start_sector ) /
start_head );
DBGC ( sandev->drive, "INT13 drive %02x guessing "
"C/H/S xx/xx/%d based on partition %d\n",
DBGC ( sandev, "INT13 drive %02x guessing C/H/S "
"xx/xx/%d based on partition %d\n",
sandev->drive, *sectors, ( i + 1 ) );
}
@ -273,14 +272,14 @@ static int int13_guess_geometry_hdd ( struct san_device *sandev, void *scratch,
end_sector = PART_SECTOR ( partition->chs_end );
if ( ( end_head + 1 ) > *heads ) {
*heads = ( end_head + 1 );
DBGC ( sandev->drive, "INT13 drive %02x guessing "
"C/H/S xx/%d/xx based on partition %d\n",
DBGC ( sandev, "INT13 drive %02x guessing C/H/S "
"xx/%d/xx based on partition %d\n",
sandev->drive, *heads, ( i + 1 ) );
}
if ( end_sector > *sectors ) {
*sectors = end_sector;
DBGC ( sandev->drive, "INT13 drive %02x guessing "
"C/H/S xx/xx/%d based on partition %d\n",
DBGC ( sandev, "INT13 drive %02x guessing C/H/S "
"xx/xx/%d based on partition %d\n",
sandev->drive, *sectors, ( i + 1 ) );
}
}
@ -344,10 +343,9 @@ static int int13_guess_geometry_fdd ( struct san_device *sandev,
*heads = INT13_FDD_HEADS ( geometry );
*sectors = INT13_FDD_SECTORS ( geometry );
if ( ( cylinders * (*heads) * (*sectors) ) == blocks ) {
DBGC ( sandev->drive, "INT13 drive %02x guessing "
"C/H/S %d/%d/%d based on size %dK\n",
sandev->drive, cylinders, *heads, *sectors,
( blocks / 2 ) );
DBGC ( sandev, "INT13 drive %02x guessing C/H/S "
"%d/%d/%d based on size %dK\n", sandev->drive,
cylinders, *heads, *sectors, ( blocks / 2 ) );
return 0;
}
}
@ -357,9 +355,8 @@ static int int13_guess_geometry_fdd ( struct san_device *sandev,
*/
*heads = 2;
*sectors = 18;
DBGC ( sandev->drive, "INT13 drive %02x guessing C/H/S xx/%d/%d "
"based on size %dK\n", sandev->drive, *heads, *sectors,
( blocks / 2 ) );
DBGC ( sandev, "INT13 drive %02x guessing C/H/S xx/%d/%d based on size "
"%dK\n", sandev->drive, *heads, *sectors, ( blocks / 2 ) );
return 0;
}
@ -434,8 +431,8 @@ static void int13_sync_num_drives ( void ) {
required = ( ( max_drive & 0x7f ) + 1 );
if ( *counter < required ) {
*counter = required;
DBGC ( sandev->drive, "INT13 drive %02x added to "
"drive count: %d HDDs, %d FDDs\n",
DBGC ( sandev, "INT13 drive %02x added to drive count: "
"%d HDDs, %d FDDs\n",
sandev->drive, num_drives, num_fdds );
}
}
@ -475,7 +472,7 @@ static int int13_reset ( struct san_device *sandev,
struct i386_all_regs *ix86 __unused ) {
int rc;
DBGC2 ( sandev->drive, "Reset drive\n" );
DBGC2 ( sandev, "Reset drive\n" );
/* Reset SAN device */
if ( ( rc = sandev_reset ( sandev ) ) != 0 )
@ -494,7 +491,7 @@ static int int13_get_last_status ( struct san_device *sandev,
struct i386_all_regs *ix86 __unused ) {
struct int13_data *int13 = sandev->priv;
DBGC2 ( sandev->drive, "Get status of last operation\n" );
DBGC2 ( sandev, "Get status of last operation\n" );
return int13->last_status;
}
@ -527,8 +524,8 @@ static int int13_rw_sectors ( struct san_device *sandev,
/* Validate blocksize */
if ( sandev_blksize ( sandev ) != INT13_BLKSIZE ) {
DBGC ( sandev->drive, "\nINT 13 drive %02x invalid blocksize "
"(%zd) for non-extended read/write\n",
DBGC ( sandev, "\nINT 13 drive %02x invalid blocksize (%zd) "
"for non-extended read/write\n",
sandev->drive, sandev_blksize ( sandev ) );
return -INT13_STATUS_INVALID;
}
@ -540,10 +537,9 @@ static int int13_rw_sectors ( struct san_device *sandev,
if ( ( cylinder >= int13->cylinders ) ||
( head >= int13->heads ) ||
( sector < 1 ) || ( sector > int13->sectors_per_track ) ) {
DBGC ( sandev->drive, "C/H/S %d/%d/%d out of range for "
"geometry %d/%d/%d\n", cylinder, head, sector,
int13->cylinders, int13->heads,
int13->sectors_per_track );
DBGC ( sandev, "C/H/S %d/%d/%d out of range for geometry "
"%d/%d/%d\n", cylinder, head, sector, int13->cylinders,
int13->heads, int13->sectors_per_track );
return -INT13_STATUS_INVALID;
}
lba = ( ( ( ( cylinder * int13->heads ) + head )
@ -551,13 +547,13 @@ static int int13_rw_sectors ( struct san_device *sandev,
count = ix86->regs.al;
buffer = real_to_user ( ix86->segs.es, ix86->regs.bx );
DBGC2 ( sandev->drive, "C/H/S %d/%d/%d = LBA %08lx <-> %04x:%04x "
"(count %d)\n", cylinder, head, sector, lba, ix86->segs.es,
ix86->regs.bx, count );
DBGC2 ( sandev, "C/H/S %d/%d/%d = LBA %08lx <-> %04x:%04x (count %d)\n",
cylinder, head, sector, lba, ix86->segs.es, ix86->regs.bx,
count );
/* Read from / write to block device */
if ( ( rc = sandev_rw ( sandev, lba, count, buffer ) ) != 0 ){
DBGC ( sandev->drive, "INT13 drive %02x I/O failed: %s\n",
DBGC ( sandev, "INT13 drive %02x I/O failed: %s\n",
sandev->drive, strerror ( rc ) );
return -INT13_STATUS_READ_ERROR;
}
@ -581,7 +577,7 @@ static int int13_rw_sectors ( struct san_device *sandev,
static int int13_read_sectors ( struct san_device *sandev,
struct i386_all_regs *ix86 ) {
DBGC2 ( sandev->drive, "Read: " );
DBGC2 ( sandev, "Read: " );
return int13_rw_sectors ( sandev, ix86, sandev_read );
}
@ -601,7 +597,7 @@ static int int13_read_sectors ( struct san_device *sandev,
static int int13_write_sectors ( struct san_device *sandev,
struct i386_all_regs *ix86 ) {
DBGC2 ( sandev->drive, "Write: " );
DBGC2 ( sandev, "Write: " );
return int13_rw_sectors ( sandev, ix86, sandev_write );
}
@ -623,12 +619,12 @@ static int int13_get_parameters ( struct san_device *sandev,
unsigned int max_head = int13->heads - 1;
unsigned int max_sector = int13->sectors_per_track; /* sic */
DBGC2 ( sandev->drive, "Get drive parameters\n" );
DBGC2 ( sandev, "Get drive parameters\n" );
/* Validate blocksize */
if ( sandev_blksize ( sandev ) != INT13_BLKSIZE ) {
DBGC ( sandev->drive, "\nINT 13 drive %02x invalid blocksize "
"(%zd) for non-extended parameters\n",
DBGC ( sandev, "\nINT 13 drive %02x invalid blocksize (%zd) "
"for non-extended parameters\n",
sandev->drive, sandev_blksize ( sandev ) );
return -INT13_STATUS_INVALID;
}
@ -661,7 +657,7 @@ static int int13_get_disk_type ( struct san_device *sandev,
struct i386_all_regs *ix86 ) {
uint32_t blocks;
DBGC2 ( sandev->drive, "Get disk type\n" );
DBGC2 ( sandev, "Get disk type\n" );
if ( int13_is_fdd ( sandev ) ) {
return INT13_DISK_TYPE_FDD;
@ -686,7 +682,7 @@ static int int13_extension_check ( struct san_device *sandev,
struct i386_all_regs *ix86 ) {
if ( ( ix86->regs.bx == 0x55aa ) && ! int13_is_fdd ( sandev ) ) {
DBGC2 ( sandev->drive, "INT13 extensions check\n" );
DBGC2 ( sandev, "INT13 extensions installation check\n" );
ix86->regs.bx = 0xaa55;
ix86->regs.cx = ( INT13_EXTENSION_LINEAR |
INT13_EXTENSION_EDD |
@ -729,8 +725,7 @@ static int int13_extended_rw ( struct san_device *sandev,
get_real ( bufsize, ix86->segs.ds,
( ix86->regs.si + offsetof ( typeof ( addr ), bufsize ) ) );
if ( bufsize < offsetof ( typeof ( addr ), buffer_phys ) ) {
DBGC2 ( sandev->drive, "<invalid buffer size %#02x\n>\n",
bufsize );
DBGC2 ( sandev, "<invalid buffer size %#02x\n>\n", bufsize );
return -INT13_STATUS_INVALID;
}
@ -738,18 +733,17 @@ static int int13_extended_rw ( struct san_device *sandev,
memset ( &addr, 0, sizeof ( addr ) );
copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si, bufsize );
lba = addr.lba;
DBGC2 ( sandev->drive, "LBA %08llx <-> ",
( ( unsigned long long ) lba ) );
DBGC2 ( sandev, "LBA %08llx <-> ", ( ( unsigned long long ) lba ) );
if ( ( addr.count == 0xff ) ||
( ( addr.buffer.segment == 0xffff ) &&
( addr.buffer.offset == 0xffff ) ) ) {
buffer = phys_to_user ( addr.buffer_phys );
DBGC2 ( sandev->drive, "%08llx",
DBGC2 ( sandev, "%08llx",
( ( unsigned long long ) addr.buffer_phys ) );
} else {
buffer = real_to_user ( addr.buffer.segment,
addr.buffer.offset );
DBGC2 ( sandev->drive, "%04x:%04x", addr.buffer.segment,
DBGC2 ( sandev, "%04x:%04x", addr.buffer.segment,
addr.buffer.offset );
}
if ( addr.count <= 0x7f ) {
@ -757,15 +751,15 @@ static int int13_extended_rw ( struct san_device *sandev,
} else if ( addr.count == 0xff ) {
count = addr.long_count;
} else {
DBGC2 ( sandev->drive, " <invalid count %#02x>\n", addr.count );
DBGC2 ( sandev, " <invalid count %#02x>\n", addr.count );
return -INT13_STATUS_INVALID;
}
DBGC2 ( sandev->drive, " (count %ld)\n", count );
DBGC2 ( sandev, " (count %ld)\n", count );
/* Read from / write to block device */
if ( ( rc = sandev_rw ( sandev, lba, count, buffer ) ) != 0 ) {
DBGC ( sandev->drive, "INT13 drive %02x extended I/O failed: "
"%s\n", sandev->drive, strerror ( rc ) );
DBGC ( sandev, "INT13 drive %02x extended I/O failed: %s\n",
sandev->drive, strerror ( rc ) );
/* Record that no blocks were transferred successfully */
addr.count = 0;
put_real ( addr.count, ix86->segs.ds,
@ -787,7 +781,7 @@ static int int13_extended_rw ( struct san_device *sandev,
static int int13_extended_read ( struct san_device *sandev,
struct i386_all_regs *ix86 ) {
DBGC2 ( sandev->drive, "Extended read: " );
DBGC2 ( sandev, "Extended read: " );
return int13_extended_rw ( sandev, ix86, sandev_read );
}
@ -801,7 +795,7 @@ static int int13_extended_read ( struct san_device *sandev,
static int int13_extended_write ( struct san_device *sandev,
struct i386_all_regs *ix86 ) {
DBGC2 ( sandev->drive, "Extended write: " );
DBGC2 ( sandev, "Extended write: " );
return int13_extended_rw ( sandev, ix86, sandev_write );
}
@ -824,7 +818,7 @@ static int int13_extended_verify ( struct san_device *sandev,
sizeof ( addr ));
lba = addr.lba;
count = addr.count;
DBGC2 ( sandev->drive, "Verify: LBA %08llx (count %ld)\n",
DBGC2 ( sandev, "Verify: LBA %08llx (count %ld)\n",
( ( unsigned long long ) lba ), count );
}
@ -851,7 +845,7 @@ static int int13_extended_seek ( struct san_device *sandev,
sizeof ( addr ));
lba = addr.lba;
count = addr.count;
DBGC2 ( sandev->drive, "Seek: LBA %08llx (count %ld)\n",
DBGC2 ( sandev, "Seek: LBA %08llx (count %ld)\n",
( ( unsigned long long ) lba ), count );
}
@ -885,8 +879,8 @@ static int int13_device_path_info ( struct san_device *sandev,
/* Get underlying hardware device */
device = identify_device ( &sanpath->block );
if ( ! device ) {
DBGC ( sandev->drive, "INT13 drive %02x cannot identify "
"hardware device\n", sandev->drive );
DBGC ( sandev, "INT13 drive %02x cannot identify hardware "
"device\n", sandev->drive );
return -ENODEV;
}
@ -901,16 +895,16 @@ static int int13_device_path_info ( struct san_device *sandev,
dpi->interface_path.pci.channel = 0xff; /* unused */
break;
default:
DBGC ( sandev->drive, "INT13 drive %02x unrecognised bus "
"type %d\n", sandev->drive, desc->bus_type );
DBGC ( sandev, "INT13 drive %02x unrecognised bus type %d\n",
sandev->drive, desc->bus_type );
return -ENOTSUP;
}
/* Get EDD block device description */
if ( ( rc = edd_describe ( &sanpath->block, &dpi->interface_type,
&dpi->device_path ) ) != 0 ) {
DBGC ( sandev->drive, "INT13 drive %02x cannot identify "
"block device: %s\n", sandev->drive, strerror ( rc ) );
DBGC ( sandev, "INT13 drive %02x cannot identify block device: "
"%s\n", sandev->drive, strerror ( rc ) );
return rc;
}
@ -944,8 +938,8 @@ static int int13_get_extended_parameters ( struct san_device *sandev,
get_real ( bufsize, ix86->segs.ds,
( ix86->regs.si + offsetof ( typeof ( params ), bufsize )));
DBGC2 ( sandev->drive, "Get extended drive parameters to "
"%04x:%04x+%02x\n", ix86->segs.ds, ix86->regs.si, bufsize );
DBGC2 ( sandev, "Get extended drive parameters to %04x:%04x+%02x\n",
ix86->segs.ds, ix86->regs.si, bufsize );
/* Build drive parameters */
memset ( &params, 0, sizeof ( params ) );
@ -961,8 +955,8 @@ static int int13_get_extended_parameters ( struct san_device *sandev,
params.sector_size = sandev_blksize ( sandev );
memset ( &params.dpte, 0xff, sizeof ( params.dpte ) );
if ( ( rc = int13_device_path_info ( sandev, &params.dpi ) ) != 0 ) {
DBGC ( sandev->drive, "INT13 drive %02x could not provide "
"device path information: %s\n",
DBGC ( sandev, "INT13 drive %02x could not provide device "
"path information: %s\n",
sandev->drive, strerror ( rc ) );
len = offsetof ( typeof ( params ), dpi );
}
@ -979,11 +973,11 @@ static int int13_get_extended_parameters ( struct san_device *sandev,
params.bufsize = offsetof ( typeof ( params ), dpi );
}
DBGC ( sandev->drive, "INT 13 drive %02x described using extended "
DBGC ( sandev, "INT 13 drive %02x described using extended "
"parameters:\n", sandev->drive );
address.segment = ix86->segs.ds;
address.offset = ix86->regs.si;
DBGC_HDA ( sandev->drive, address, &params, len );
DBGC_HDA ( sandev, address, &params, len );
/* Return drive parameters */
if ( len > bufsize )
@ -1004,13 +998,13 @@ static int int13_cdrom_status_terminate ( struct san_device *sandev,
struct i386_all_regs *ix86 ) {
struct int13_cdrom_specification specification;
DBGC2 ( sandev->drive, "Get CD-ROM emulation status to %04x:%04x%s\n",
DBGC2 ( sandev, "Get CD-ROM emulation status to %04x:%04x%s\n",
ix86->segs.ds, ix86->regs.si,
( ix86->regs.al ? "" : " and terminate" ) );
/* Fail if we are not a CD-ROM */
if ( ! sandev->is_cdrom ) {
DBGC ( sandev->drive, "INT13 drive %02x is not a CD-ROM\n",
DBGC ( sandev, "INT13 drive %02x is not a CD-ROM\n",
sandev->drive );
return -INT13_STATUS_INVALID;
}
@ -1045,12 +1039,11 @@ static int int13_cdrom_read_boot_catalog ( struct san_device *sandev,
/* Read parameters from command packet */
copy_from_real ( &command, ix86->segs.ds, ix86->regs.si,
sizeof ( command ) );
DBGC2 ( sandev->drive, "Read CD-ROM boot catalog to %08x\n",
command.buffer );
DBGC2 ( sandev, "Read CD-ROM boot catalog to %08x\n", command.buffer );
/* Fail if we have no boot catalog */
if ( ! int13->boot_catalog ) {
DBGC ( sandev->drive, "INT13 drive %02x has no boot catalog\n",
DBGC ( sandev, "INT13 drive %02x has no boot catalog\n",
sandev->drive );
return -INT13_STATUS_INVALID;
}
@ -1059,8 +1052,8 @@ static int int13_cdrom_read_boot_catalog ( struct san_device *sandev,
/* Read from boot catalog */
if ( ( rc = sandev_read ( sandev, start, command.count,
phys_to_user ( command.buffer ) ) ) != 0 ) {
DBGC ( sandev->drive, "INT13 drive %02x could not read boot "
"catalog: %s\n", sandev->drive, strerror ( rc ) );
DBGC ( sandev, "INT13 drive %02x could not read boot catalog: "
"%s\n", sandev->drive, strerror ( rc ) );
return -INT13_STATUS_READ_ERROR;
}
@ -1087,8 +1080,8 @@ static __asmcall __used void int13 ( struct i386_all_regs *ix86 ) {
if ( bios_drive != sandev->drive ) {
/* Remap any accesses to this drive's natural number */
if ( bios_drive == int13->natural_drive ) {
DBGC2 ( sandev->drive, "INT13,%02x (%02x) "
"remapped to (%02x)\n", ix86->regs.ah,
DBGC2 ( sandev, "INT13,%02x (%02x) remapped to "
"(%02x)\n", ix86->regs.ah,
bios_drive, sandev->drive );
ix86->regs.dl = sandev->drive;
return;
@ -1101,7 +1094,7 @@ static __asmcall __used void int13 ( struct i386_all_regs *ix86 ) {
}
}
DBGC2 ( sandev->drive, "INT13,%02x (%02x): ",
DBGC2 ( sandev, "INT13,%02x (%02x): ",
ix86->regs.ah, bios_drive );
switch ( command ) {
@ -1148,7 +1141,7 @@ static __asmcall __used void int13 ( struct i386_all_regs *ix86 ) {
status = int13_cdrom_read_boot_catalog ( sandev, ix86 );
break;
default:
DBGC2 ( sandev->drive, "*** Unrecognised INT13 ***\n" );
DBGC2 ( sandev, "*** Unrecognised INT13 ***\n" );
status = -INT13_STATUS_INVALID;
break;
}
@ -1159,9 +1152,8 @@ static __asmcall __used void int13 ( struct i386_all_regs *ix86 ) {
/* Negative status indicates an error */
if ( status < 0 ) {
status = -status;
DBGC ( sandev->drive, "INT13,%02x (%02x) failed with "
"status %02x\n", ix86->regs.ah, sandev->drive,
status );
DBGC ( sandev, "INT13,%02x (%02x) failed with status "
"%02x\n", ix86->regs.ah, sandev->drive, status );
} else {
ix86->flags &= ~CF;
}
@ -1277,7 +1269,7 @@ static int int13_hook ( unsigned int drive, struct uri **uris,
/* Register SAN device */
if ( ( rc = register_sandev ( sandev, drive, flags ) ) != 0 ) {
DBGC ( drive, "INT13 drive %02x could not register: %s\n",
DBGC ( sandev, "INT13 drive %02x could not register: %s\n",
drive, strerror ( rc ) );
goto err_register;
}
@ -1297,9 +1289,10 @@ static int int13_hook ( unsigned int drive, struct uri **uris,
( ( rc = int13_guess_geometry ( sandev, scratch ) ) != 0 ) )
goto err_guess_geometry;
DBGC ( drive, "INT13 drive %02x (naturally %02x) registered with "
"C/H/S geometry %d/%d/%d\n", drive, int13->natural_drive,
int13->cylinders, int13->heads, int13->sectors_per_track );
DBGC ( sandev, "INT13 drive %02x (naturally %02x) registered with "
"C/H/S geometry %d/%d/%d\n",
sandev->drive, int13->natural_drive, int13->cylinders,
int13->heads, int13->sectors_per_track );
/* Hook INT 13 vector if not already hooked */
if ( need_hook ) {
@ -1339,7 +1332,7 @@ static void int13_unhook ( unsigned int drive ) {
/* Find drive */
sandev = sandev_find ( drive );
if ( ! sandev ) {
DBGC ( drive, "INT13 drive %02x is not a SAN drive\n", drive );
DBG ( "INT13 cannot find drive %02x\n", drive );
return;
}
@ -1350,7 +1343,7 @@ static void int13_unhook ( unsigned int drive ) {
* to do so reliably.
*/
DBGC ( drive, "INT13 drive %02x unregistered\n", drive );
DBGC ( sandev, "INT13 drive %02x unregistered\n", sandev->drive );
/* Unhook INT 13 vector if no more drives */
if ( ! have_sandevs() ) {
@ -1394,8 +1387,8 @@ static int int13_load_mbr ( unsigned int drive, struct segoff *address ) {
: "a" ( 0x0201 ), "b" ( *address ),
"c" ( 1 ), "d" ( drive ) );
if ( status ) {
DBGC ( drive, "INT13 drive %02x could not read MBR (status "
"%04x)\n", drive, status );
DBG ( "INT13 drive %02x could not read MBR (status %04x)\n",
drive, status );
return -EIO;
}
@ -1404,8 +1397,8 @@ static int int13_load_mbr ( unsigned int drive, struct segoff *address ) {
( address->offset +
offsetof ( struct master_boot_record, magic ) ) );
if ( magic != INT13_MBR_MAGIC ) {
DBGC ( drive, "INT13 drive %02x does not contain a valid MBR\n",
drive );
DBG ( "INT13 drive %02x does not contain a valid MBR\n",
drive );
return -ENOEXEC;
}
@ -1451,8 +1444,8 @@ static int int13_load_eltorito ( unsigned int drive, struct segoff *address ) {
: "a" ( 0x4d00 ), "d" ( drive ),
"S" ( __from_data16 ( &eltorito_cmd ) ) );
if ( status ) {
DBGC ( drive, "INT13 drive %02x could not read El Torito boot "
"catalog (status %04x)\n", drive, status );
DBG ( "INT13 drive %02x could not read El Torito boot catalog "
"(status %04x)\n", drive, status );
return -EIO;
}
copy_from_user ( &catalog, phys_to_user ( eltorito_cmd.buffer ), 0,
@ -1460,27 +1453,26 @@ static int int13_load_eltorito ( unsigned int drive, struct segoff *address ) {
/* Sanity checks */
if ( catalog.valid.platform_id != ELTORITO_PLATFORM_X86 ) {
DBGC ( drive, "INT13 drive %02x El Torito specifies unknown "
"platform %02x\n", drive, catalog.valid.platform_id );
DBG ( "INT13 drive %02x El Torito specifies unknown platform "
"%02x\n", drive, catalog.valid.platform_id );
return -ENOEXEC;
}
if ( catalog.boot.indicator != ELTORITO_BOOTABLE ) {
DBGC ( drive, "INT13 drive %02x El Torito is not bootable\n",
drive );
DBG ( "INT13 drive %02x El Torito is not bootable\n", drive );
return -ENOEXEC;
}
if ( catalog.boot.media_type != ELTORITO_NO_EMULATION ) {
DBGC ( drive, "INT13 drive %02x El Torito requires emulation "
DBG ( "INT13 drive %02x El Torito requires emulation "
"type %02x\n", drive, catalog.boot.media_type );
return -ENOTSUP;
}
DBGC ( drive, "INT13 drive %02x El Torito boot image at LBA %08x "
"(count %d)\n", drive, catalog.boot.start, catalog.boot.length );
DBG ( "INT13 drive %02x El Torito boot image at LBA %08x (count %d)\n",
drive, catalog.boot.start, catalog.boot.length );
address->segment = ( catalog.boot.load_segment ?
catalog.boot.load_segment : 0x7c0 );
address->offset = 0;
DBGC ( drive, "INT13 drive %02x El Torito boot image loads at "
"%04x:%04x\n", drive, address->segment, address->offset );
DBG ( "INT13 drive %02x El Torito boot image loads at %04x:%04x\n",
drive, address->segment, address->offset );
/* Use INT 13, 42 to read the boot image */
eltorito_address.bufsize =
@ -1499,8 +1491,8 @@ static int int13_load_eltorito ( unsigned int drive, struct segoff *address ) {
: "a" ( 0x4200 ), "d" ( drive ),
"S" ( __from_data16 ( &eltorito_address ) ) );
if ( status ) {
DBGC ( drive, "INT13 drive %02x could not read El Torito boot "
"image (status %04x)\n", drive, status );
DBG ( "INT13 drive %02x could not read El Torito boot image "
"(status %04x)\n", drive, status );
return -EIO;
}
@ -1511,7 +1503,7 @@ static int int13_load_eltorito ( unsigned int drive, struct segoff *address ) {
* Attempt to boot from an INT 13 drive
*
* @v drive Drive number
* @v config Boot configuration parameters
* @v filename Filename (or NULL to use default)
* @ret rc Return status code
*
* This boots from the specified INT 13 drive by loading the Master
@ -1521,8 +1513,7 @@ static int int13_load_eltorito ( unsigned int drive, struct segoff *address ) {
*
* Note that this function can never return success, by definition.
*/
static int int13_boot ( unsigned int drive,
struct san_boot_config *config __unused ) {
static int int13_boot ( unsigned int drive, const char *filename __unused ) {
struct memory_map memmap;
struct segoff address;
int rc;
@ -1542,8 +1533,8 @@ static int int13_boot ( unsigned int drive,
/* Jump to boot sector */
if ( ( rc = call_bootsector ( address.segment, address.offset,
drive ) ) != 0 ) {
DBGC ( drive, "INT13 drive %02x boot returned: %s\n",
drive, strerror ( rc ) );
DBG ( "INT13 drive %02x boot returned: %s\n",
drive, strerror ( rc ) );
return rc;
}

View File

@ -165,27 +165,24 @@ static void pcicloud_init ( void ) {
static struct pci_api *apis[] = {
&ecam_api, &pcibios_api, &pcidirect_api
};
struct pci_device pci;
uint32_t busdevfn;
struct pci_range range;
unsigned int i;
int rc;
/* Select first API that successfully discovers a PCI device */
/* Select first API that successfully discovers an address range */
for ( i = 0 ; i < ( sizeof ( apis ) / sizeof ( apis[0] ) ) ; i++ ) {
pcicloud = apis[i];
busdevfn = 0;
if ( ( rc = pci_find_next ( &pci, &busdevfn ) ) == 0 ) {
DBGC ( pcicloud, "PCICLOUD selected %s API (found "
PCI_FMT ")\n", pcicloud->name,
PCI_ARGS ( &pci ) );
return;
pcicloud_discover ( 0, &range );
if ( range.count != 0 ) {
DBGC ( pcicloud, "PCICLOUD selected %s API\n",
pcicloud->name );
break;
}
}
/* Fall back to using final attempted API if no devices found */
pcicloud = apis[ i - 1 ];
DBGC ( pcicloud, "PCICLOUD selected %s API (nothing detected)\n",
pcicloud->name );
/* The PCI direct API can never fail discovery since the range
* is hardcoded.
*/
assert ( range.count != 0 );
}
/** Cloud VM PCI configuration space access initialisation function */

View File

@ -375,10 +375,9 @@ int pxe_start_nbp ( void ) {
* Notify BIOS of existence of network device
*
* @v netdev Network device
* @v priv Private data
* @ret rc Return status code
*/
static int pxe_notify ( struct net_device *netdev, void *priv __unused ) {
static int pxe_notify ( struct net_device *netdev ) {
/* Do nothing if we already have a network device */
if ( pxe_netdev )

View File

@ -26,8 +26,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
.section ".note.GNU-stack", "", @progbits
.code16
.arch i386
/****************************************************************************

View File

@ -21,7 +21,6 @@ FILE_LICENCE ( GPL2_OR_LATER )
#include "librm.h"
.section ".note.GNU-stack", "", @progbits
.text
.code32

View File

@ -207,35 +207,65 @@ struct init_fn guestinfo_init_fn __init_fn ( INIT_NORMAL ) = {
* Create per-netdevice GuestInfo settings
*
* @v netdev Network device
* @v priv Private data
* @ret rc Return status code
*/
static int guestinfo_net_probe ( struct net_device *netdev, void *priv ) {
struct settings *settings = priv;
static int guestinfo_net_probe ( struct net_device *netdev ) {
struct settings *settings;
int rc;
/* Do nothing unless we have a GuestInfo channel available */
if ( guestinfo_channel < 0 )
return 0;
/* Initialise and register settings */
settings_init ( settings, &guestinfo_settings_operations,
&netdev->refcnt, NULL );
/* Allocate and initialise settings block */
settings = zalloc ( sizeof ( *settings ) );
if ( ! settings ) {
rc = -ENOMEM;
goto err_alloc;
}
settings_init ( settings, &guestinfo_settings_operations, NULL, NULL );
/* Register settings */
if ( ( rc = register_settings ( settings, netdev_settings ( netdev ),
"vmware" ) ) != 0 ) {
DBGC ( settings, "GuestInfo %p could not register for %s: %s\n",
settings, netdev->name, strerror ( rc ) );
return rc;
goto err_register;
}
DBGC ( settings, "GuestInfo %p registered for %s\n",
settings, netdev->name );
return 0;
err_register:
free ( settings );
err_alloc:
return rc;
}
/**
* Remove per-netdevice GuestInfo settings
*
* @v netdev Network device
*/
static void guestinfo_net_remove ( struct net_device *netdev ) {
struct settings *parent = netdev_settings ( netdev );
struct settings *settings;
list_for_each_entry ( settings, &parent->children, siblings ) {
if ( settings->op == &guestinfo_settings_operations ) {
DBGC ( settings, "GuestInfo %p unregistered for %s\n",
settings, netdev->name );
unregister_settings ( settings );
free ( settings );
return;
}
}
}
/** GuestInfo per-netdevice driver */
struct net_driver guestinfo_net_driver __net_driver = {
.name = "GuestInfo",
.priv_len = sizeof ( struct settings ),
.probe = guestinfo_net_probe,
.remove = guestinfo_net_remove,
};

View File

@ -5,10 +5,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define STACK_SEG 0x0200
#define STACK_SIZE 0x2000
.section ".note.GNU-stack", "", @progbits
.code16
.text
.arch i386
.section ".prefix", "awx", @progbits
.code16
/*
* Find active partition

View File

@ -24,11 +24,11 @@ FILE_LICENCE ( GPL2_ONLY )
.equ SYSSEG, 0x1000 /* system loaded at SYSSEG<<4 */
.section ".note.GNU-stack", "", @progbits
.org 0
.code16
.arch i386
.text
.section ".prefix", "ax", @progbits
.code16
.globl _dsk_start
_dsk_start:

View File

@ -36,10 +36,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define PSP_CMDLINE_LEN 0x80
#define PSP_CMDLINE_START 0x81
.section ".note.GNU-stack", "", @progbits
.code16
.text
.arch i386
.org 0
.code16
.section ".prefix", "awx", @progbits
signature:

View File

@ -2,10 +2,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
.section ".note.GNU-stack", "", @progbits
.code16
.text
.arch i386
.section ".prefix", "awx", @progbits
.code16
.org 0
.globl _hd_start
_hd_start:

View File

@ -26,8 +26,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
.section ".note.GNU-stack", "", @progbits
.code16
.arch i386
/* Image compression enabled */

View File

@ -4,9 +4,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define BZI_LOAD_HIGH_ADDR 0x100000
.section ".note.GNU-stack", "", @progbits
.code16
.text
.arch i386
.code16
.section ".prefix", "ax", @progbits
.globl _lkrn_start
_lkrn_start:

View File

@ -1,9 +1,9 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.code16
.text
.arch i386
.section ".prefix", "awx", @progbits
.code16
.org 0
.globl mbr

View File

@ -41,9 +41,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define _pcirom_start _mrom_start
#include "pciromprefix.S"
.section ".note.GNU-stack", "", @progbits
.code16
.text
.arch i386
.code16
/* Obtain access to payload by exposing the expansion ROM BAR at the
* address currently used by a suitably large memory BAR on the same

View File

@ -2,9 +2,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
.section ".note.GNU-stack", "", @progbits
.code16
.text
.arch i386
.code16
.section ".prefix", "ax", @progbits
.org 0

View File

@ -1,11 +1,11 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.org 0
.code16
.text
.arch i386
.section ".prefix", "ax", @progbits
.code16
_prefix:
.section ".text16", "ax", @progbits

View File

@ -11,10 +11,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define PXE_HACK_EB54 0x0001
.section ".note.GNU-stack", "", @progbits
.code16
.text
.arch i386
.org 0
.code16
#include <librm.h>
#include <undi.h>

View File

@ -8,10 +8,10 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.code16
.text
.arch i386
.org 0
.code16
#include <librm.h>

View File

@ -54,7 +54,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define BUSTYPE "PCIR"
#endif
.section ".note.GNU-stack", "", @progbits
.text
.code16
.arch i386
.section ".prefix", "ax", @progbits

View File

@ -2,7 +2,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
.section ".note.GNU-stack", "", @progbits
.text
.code16
.arch i386
.section ".prefix", "ax", @progbits

View File

@ -43,8 +43,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
****************************************************************************
*/
.section ".note.GNU-stack", "", @progbits
.code32
.text
.arch i486
.section ".prefix.lib", "ax", @progbits

View File

@ -2,10 +2,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <config/console.h>
.section ".note.GNU-stack", "", @progbits
.code16
.text
.arch i386
.section ".prefix", "awx", @progbits
.code16
.org 0
#include "mbr.S"

View File

@ -24,8 +24,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.code16
.arch i386
/****************************************************************************

View File

@ -31,10 +31,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
/* Breakpoint for when debugging under bochs */
#define BOCHSBP xchgw %bx, %bx
.section ".note.GNU-stack", "", @progbits
.code16
.text
.arch i386
.section ".text16", "awx", @progbits
.code16
/****************************************************************************
* init_libkir (real-mode or 16:xx protected-mode far call)

View File

@ -83,8 +83,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define if64 if 0
#endif
.section ".note.GNU-stack", "", @progbits
/****************************************************************************
* Global descriptor table
*
@ -1632,70 +1630,3 @@ init_pages:
/* Return */
ret
/****************************************************************************
* sipi (real-mode jump)
*
* Handle Startup IPI
*
* This code must be copied to a page-aligned boundary in base memory.
* It will be entered with %cs:0000 pointing to the start of the code.
* The stack pointer is undefined and so no stack space can be used.
*
****************************************************************************
*/
.section ".text16.sipi", "ax", @progbits
.code16
.globl sipi
sipi:
/* Retrieve rm_ds from copy */
movw %cs:( sipi_ds - sipi ), %ax
movw %ax, %ds
/* Load GDT and switch to protected mode */
data32 lgdt gdtr
movl %cr0, %eax
orb $CR0_PE, %al
movl %eax, %cr0
data32 ljmp $VIRTUAL_CS, $VIRTUAL(1f)
/* Copy of rm_ds required to access GDT */
.globl sipi_ds
sipi_ds:
.word 0
/* Length of real-mode SIPI handler to be copied */
.globl sipi_len
.equ sipi_len, . - sipi
.section ".text.sipi", "ax", @progbits
.code32
1: /* Set up protected-mode segment registers (with no stack) */
movw $VIRTUAL_DS, %ax
movw %ax, %ds
movw %ax, %ss
movw $PHYSICAL_DS, %ax
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
/* Load register state and clear stack pointer */
movl $VIRTUAL(sipi_regs), %esp
popal
/* Switch to flat physical addressing */
movw $PHYSICAL_DS, %sp
movw %sp, %ds
movw %sp, %ss
/* Clear stack pointer */
xorl %esp, %esp
/* Jump to protected-mode SIPI handler */
ljmp %cs:*VIRTUAL(sipi_handler)
/* Protected-mode SIPI handler vector */
.section ".data.sipi_handler", "aw", @progbits
.globl sipi_handler
sipi_handler:
.long 0, PHYSICAL_CS

View File

@ -45,9 +45,6 @@ struct idtr64 idtr64 = {
.limit = ( sizeof ( idt64 ) - 1 ),
};
/** Startup IPI register state */
struct i386_regs sipi_regs;
/** Length of stack dump */
#define STACK_DUMP_LEN 128
@ -405,29 +402,6 @@ __asmcall void check_fxsr ( struct i386_all_regs *regs ) {
( ( regs->flags & CF ) ? " not" : "" ) );
}
/**
* Set up startup IPI handler
*
* @v vector Startup IPI vector
* @v handler Protected-mode startup IPI handler physical address
* @v regs Initial register state
*/
void setup_sipi ( unsigned int vector, uint32_t handler,
struct i386_regs *regs ) {
/* Record protected-mode handler */
sipi_handler = handler;
/* Update copy of rm_ds */
sipi_ds = rm_ds;
/* Save register state */
memcpy ( &sipi_regs, regs, sizeof ( sipi_regs ) );
/* Copy real-mode handler */
copy_to_real ( ( vector << 8 ), 0, sipi, ( ( size_t ) sipi_len ) );
}
PROVIDE_UACCESS_INLINE ( librm, phys_to_user );
PROVIDE_UACCESS_INLINE ( librm, user_to_phys );
PROVIDE_UACCESS_INLINE ( librm, virt_to_user );

View File

@ -38,7 +38,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define SIGFPE 8
#define SIGSTKFLT 16
.section ".note.GNU-stack", "", @progbits
.section ".text.gdbmach_interrupt", "ax", @progbits
.code64

View File

@ -1,6 +1,5 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.text
.code64

1
src/bin/.gitignore vendored
View File

@ -1,2 +1 @@
*
!.gitignore

View File

@ -188,9 +188,6 @@ REQUIRE_OBJECT ( zlib );
#ifdef IMAGE_GZIP
REQUIRE_OBJECT ( gzip );
#endif
#ifdef IMAGE_UCODE
REQUIRE_OBJECT ( ucode );
#endif
/*
* Drag in all requested commands
@ -293,9 +290,6 @@ 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
@ -358,9 +352,6 @@ REQUIRE_OBJECT ( vram_settings );
#ifdef ACPI_SETTINGS
REQUIRE_OBJECT ( acpi_settings );
#endif
#ifdef EFI_SETTINGS
REQUIRE_OBJECT ( efi_settings );
#endif
/*
* Drag in selected keyboard map

View File

@ -83,11 +83,6 @@ REQUIRE_OBJECT ( oid_sha512_224 );
REQUIRE_OBJECT ( oid_sha512_256 );
#endif
/* X25519 */
#if defined ( CRYPTO_CURVE_X25519 )
REQUIRE_OBJECT ( oid_x25519 );
#endif
/* RSA and MD5 */
#if defined ( CRYPTO_PUBKEY_RSA ) && defined ( CRYPTO_DIGEST_MD5 )
REQUIRE_OBJECT ( rsa_md5 );
@ -119,79 +114,25 @@ REQUIRE_OBJECT ( rsa_sha512 );
#endif
/* RSA, AES-CBC, and SHA-1 */
#if defined ( CRYPTO_EXCHANGE_PUBKEY ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_CBC ) && defined ( CRYPTO_DIGEST_SHA1 )
#if defined ( CRYPTO_PUBKEY_RSA ) && defined ( CRYPTO_CIPHER_AES_CBC ) && \
defined ( CRYPTO_DIGEST_SHA1 )
REQUIRE_OBJECT ( rsa_aes_cbc_sha1 );
#endif
/* RSA, AES-CBC, and SHA-256 */
#if defined ( CRYPTO_EXCHANGE_PUBKEY ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_CBC ) && defined ( CRYPTO_DIGEST_SHA256 )
#if defined ( CRYPTO_PUBKEY_RSA ) && defined ( CRYPTO_CIPHER_AES_CBC ) && \
defined ( CRYPTO_DIGEST_SHA256 )
REQUIRE_OBJECT ( rsa_aes_cbc_sha256 );
#endif
/* RSA, AES-GCM, and SHA-256 */
#if defined ( CRYPTO_EXCHANGE_PUBKEY ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_GCM ) && defined ( CRYPTO_DIGEST_SHA256 )
#if defined ( CRYPTO_PUBKEY_RSA ) && defined ( CRYPTO_CIPHER_AES_GCM ) && \
defined ( CRYPTO_DIGEST_SHA256 )
REQUIRE_OBJECT ( rsa_aes_gcm_sha256 );
#endif
/* RSA, AES-GCM, and SHA-384 */
#if defined ( CRYPTO_EXCHANGE_PUBKEY ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_GCM ) && defined ( CRYPTO_DIGEST_SHA384 )
#if defined ( CRYPTO_PUBKEY_RSA ) && defined ( CRYPTO_CIPHER_AES_GCM ) && \
defined ( CRYPTO_DIGEST_SHA384 )
REQUIRE_OBJECT ( rsa_aes_gcm_sha384 );
#endif
/* DHE, RSA, AES-CBC, and SHA-1 */
#if defined ( CRYPTO_EXCHANGE_DHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_CBC ) && defined ( CRYPTO_DIGEST_SHA1 )
REQUIRE_OBJECT ( dhe_rsa_aes_cbc_sha1 );
#endif
/* DHE, RSA, AES-CBC, and SHA-256 */
#if defined ( CRYPTO_EXCHANGE_DHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_CBC ) && defined ( CRYPTO_DIGEST_SHA256 )
REQUIRE_OBJECT ( dhe_rsa_aes_cbc_sha256 );
#endif
/* DHE, RSA, AES-GCM, and SHA-256 */
#if defined ( CRYPTO_EXCHANGE_DHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_GCM ) && defined ( CRYPTO_DIGEST_SHA256 )
REQUIRE_OBJECT ( dhe_rsa_aes_gcm_sha256 );
#endif
/* DHE, RSA, AES-GCM, and SHA-384 */
#if defined ( CRYPTO_EXCHANGE_DHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_GCM ) && defined ( CRYPTO_DIGEST_SHA384 )
REQUIRE_OBJECT ( dhe_rsa_aes_gcm_sha384 );
#endif
/* ECDHE, RSA, AES-CBC, and SHA-1 */
#if defined ( CRYPTO_EXCHANGE_ECDHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_CBC ) && defined ( CRYPTO_DIGEST_SHA1 )
REQUIRE_OBJECT ( ecdhe_rsa_aes_cbc_sha1 );
#endif
/* ECDHE, RSA, AES-CBC, and SHA-256 */
#if defined ( CRYPTO_EXCHANGE_ECDHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_CBC ) && defined ( CRYPTO_DIGEST_SHA256 )
REQUIRE_OBJECT ( ecdhe_rsa_aes_cbc_sha256 );
#endif
/* ECDHE, RSA, AES-CBC, and SHA-384 */
#if defined ( CRYPTO_EXCHANGE_ECDHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_CBC ) && defined ( CRYPTO_DIGEST_SHA384 )
REQUIRE_OBJECT ( ecdhe_rsa_aes_cbc_sha384 );
#endif
/* ECDHE, RSA, AES-GCM, and SHA-256 */
#if defined ( CRYPTO_EXCHANGE_ECDHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_GCM ) && defined ( CRYPTO_DIGEST_SHA256 )
REQUIRE_OBJECT ( ecdhe_rsa_aes_gcm_sha256 );
#endif
/* ECDHE, RSA, AES-GCM, and SHA-384 */
#if defined ( CRYPTO_EXCHANGE_ECDHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_GCM ) && defined ( CRYPTO_DIGEST_SHA384 )
REQUIRE_OBJECT ( ecdhe_rsa_aes_gcm_sha384 );
#endif

View File

@ -1,42 +0,0 @@
/*
* 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.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <config/general.h>
/** @file
*
* EAP configuration options
*
*/
PROVIDE_REQUIRING_SYMBOL();
/*
* Drag in EAP authentication methods
*/
#ifdef EAP_METHOD_MD5
REQUIRE_OBJECT ( eap_md5 );
#endif
#ifdef EAP_METHOD_MSCHAPV2
REQUIRE_OBJECT ( eap_mschapv2 );
#endif

View File

@ -12,15 +12,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** Minimum TLS version */
#define TLS_VERSION_MIN TLS_VERSION_TLS_1_1
/** Public-key exchange algorithm */
#define CRYPTO_EXCHANGE_PUBKEY
/** DHE key exchange algorithm */
#define CRYPTO_EXCHANGE_DHE
/** ECDHE key exchange algorithm */
#define CRYPTO_EXCHANGE_ECDHE
/** RSA public-key algorithm */
#define CRYPTO_PUBKEY_RSA
@ -57,9 +48,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** SHA-512/256 digest algorithm */
//#define CRYPTO_DIGEST_SHA512_256
/** X25519 elliptic curve */
#define CRYPTO_CURVE_X25519
/** Margin of error (in seconds) allowed in signed timestamps
*
* We default to allowing a reasonable margin of error: 12 hours to

View File

@ -25,7 +25,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define REBOOT_EFI
#define ACPI_EFI
#define FDT_EFI
#define MPAPI_EFI
#define NET_PROTO_IPV6 /* IPv6 protocol */
#define NET_PROTO_LLDP /* Link Layer Discovery protocol */
@ -49,8 +48,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define REBOOT_CMD /* Reboot command */
#define EFI_SETTINGS /* EFI variable settings */
#if defined ( __i386__ ) || defined ( __x86_64__ )
#define IOAPI_X86
#define NAP_EFIX86
@ -68,9 +65,4 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define IMAGE_GZIP /* GZIP image support */
#endif
#if defined ( __loongarch__ )
#define IOAPI_LOONG64
#define NAP_EFILOONG64
#endif
#endif /* CONFIG_DEFAULTS_EFI_H */

View File

@ -22,7 +22,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define PCIAPI_LINUX
#define DMAAPI_FLAT
#define ACPI_LINUX
#define MPAPI_NULL
#define DRIVERS_LINUX

View File

@ -24,7 +24,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define TIME_RTC
#define REBOOT_PCBIOS
#define ACPI_RSDP
#define MPAPI_PCBIOS
#ifdef __x86_64__
#define IOMAP_PAGES

View File

@ -91,13 +91,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define CRYPTO_80211_WPA /* WPA Personal, authenticating with passphrase */
#define CRYPTO_80211_WPA2 /* Add support for stronger WPA cryptography */
/*
* 802.1x EAP authentication methods
*
*/
#define EAP_METHOD_MD5 /* MD5-Challenge port authentication */
//#define EAP_METHOD_MSCHAPV2 /* MS-CHAPv2 port authentication */
/*
* Name resolution modules
*
@ -127,7 +120,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define IMAGE_PEM /* PEM image support */
//#define IMAGE_ZLIB /* ZLIB image support */
//#define IMAGE_GZIP /* GZIP image support */
//#define IMAGE_UCODE /* Microcode update image support */
/*
* Command-line commands to include
@ -168,7 +160,6 @@ 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

View File

@ -1,2 +1 @@
*
!.gitignore

View File

@ -9,8 +9,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <config/defaults.h>
#define PCI_SETTINGS /* PCI device settings */
//#define CPUID_SETTINGS /* CPUID settings */
//#define MEMMAP_SETTINGS /* Memory map settings */

View File

@ -78,23 +78,12 @@ int hex_decode ( char separator, const char *encoded, void *data, size_t len ) {
unsigned int count = 0;
unsigned int sixteens;
unsigned int units;
int optional;
/* Strip out optionality flag from separator character */
optional = ( separator & HEX_DECODE_OPTIONAL );
separator &= ~HEX_DECODE_OPTIONAL;
/* Decode string */
while ( *encoded ) {
/* Check separator, if applicable */
if ( count && separator ) {
if ( *encoded == separator ) {
encoded++;
} else if ( ! optional ) {
return -EINVAL;
}
}
if ( count && separator && ( ( *(encoded++) != separator ) ) )
return -EINVAL;
/* Extract digits. Note that either digit may be NUL,
* which would be interpreted as an invalid value by

View File

@ -46,20 +46,11 @@ struct cached_dhcp_packet {
struct dhcp_packet *dhcppkt;
/** VLAN tag (if applicable) */
unsigned int vlan;
/** Flags */
unsigned int flags;
};
/** Cached DHCP packet should be retained */
#define CACHEDHCP_RETAIN 0x0001
/** Cached DHCP packet has been used */
#define CACHEDHCP_USED 0x0002
/** Cached DHCPACK */
struct cached_dhcp_packet cached_dhcpack = {
.name = DHCP_SETTINGS_NAME,
.flags = CACHEDHCP_RETAIN,
};
/** Cached ProxyDHCPOFFER */
@ -110,8 +101,8 @@ static int cachedhcp_apply ( struct cached_dhcp_packet *cache,
size_t ll_addr_len;
int rc;
/* Do nothing if cache is empty or already in use */
if ( ( ! cache->dhcppkt ) || ( cache->flags & CACHEDHCP_USED ) )
/* Do nothing if cache is empty */
if ( ! cache->dhcppkt )
return 0;
chaddr = cache->dhcppkt->dhcphdr->chaddr;
@ -178,12 +169,8 @@ static int cachedhcp_apply ( struct cached_dhcp_packet *cache,
return rc;
}
/* Mark as used */
cache->flags |= CACHEDHCP_USED;
/* Free cached DHCP packet, if applicable */
if ( ! ( cache->flags & CACHEDHCP_RETAIN ) )
cachedhcp_free ( cache );
/* Free cached DHCP packet */
cachedhcp_free ( cache );
return 0;
}
@ -259,10 +246,10 @@ int cachedhcp_record ( struct cached_dhcp_packet *cache, unsigned int vlan,
}
/**
* Cached DHCP packet early startup function
* Cached DHCP packet startup function
*
*/
static void cachedhcp_startup_early ( void ) {
static void cachedhcp_startup ( void ) {
/* Apply cached ProxyDHCPOFFER, if any */
cachedhcp_apply ( &cached_proxydhcp, NULL );
@ -271,20 +258,6 @@ static void cachedhcp_startup_early ( void ) {
/* Apply cached PXEBSACK, if any */
cachedhcp_apply ( &cached_pxebs, NULL );
cachedhcp_free ( &cached_pxebs );
}
/**
* Cache DHCP packet late startup function
*
*/
static void cachedhcp_startup_late ( void ) {
/* Clear retention flag */
cached_dhcpack.flags &= ~CACHEDHCP_RETAIN;
/* Free cached DHCPACK, if used by a network device */
if ( cached_dhcpack.flags & CACHEDHCP_USED )
cachedhcp_free ( &cached_dhcpack );
/* Report unclaimed DHCPACK, if any. Do not free yet, since
* it may still be claimed by a dynamically created device
@ -311,16 +284,10 @@ static void cachedhcp_shutdown ( int booting __unused ) {
cachedhcp_free ( &cached_dhcpack );
}
/** Cached DHCP packet early startup function */
struct startup_fn cachedhcp_early_fn __startup_fn ( STARTUP_EARLY ) = {
.name = "cachedhcp1",
.startup = cachedhcp_startup_early,
};
/** Cached DHCP packet late startup function */
struct startup_fn cachedhcp_late_fn __startup_fn ( STARTUP_LATE ) = {
.name = "cachedhcp2",
.startup = cachedhcp_startup_late,
/** Cached DHCPACK startup function */
struct startup_fn cachedhcp_startup_fn __startup_fn ( STARTUP_LATE ) = {
.name = "cachedhcp",
.startup = cachedhcp_startup,
.shutdown = cachedhcp_shutdown,
};
@ -328,10 +295,9 @@ struct startup_fn cachedhcp_late_fn __startup_fn ( STARTUP_LATE ) = {
* Apply cached DHCPACK to network device, if applicable
*
* @v netdev Network device
* @v priv Private data
* @ret rc Return status code
*/
static int cachedhcp_probe ( struct net_device *netdev, void *priv __unused ) {
static int cachedhcp_probe ( struct net_device *netdev ) {
/* Apply cached DHCPACK to network device, if applicable */
return cachedhcp_apply ( &cached_dhcpack, netdev );
@ -342,25 +308,3 @@ struct net_driver cachedhcp_driver __net_driver = {
.name = "cachedhcp",
.probe = cachedhcp_probe,
};
/**
* Recycle cached DHCPACK
*
* @v netdev Network device
* @v priv Private data
*/
void cachedhcp_recycle ( struct net_device *netdev ) {
struct cached_dhcp_packet *cache = &cached_dhcpack;
struct settings *settings;
/* Return DHCPACK to cache, if applicable */
settings = find_child_settings ( netdev_settings ( netdev ),
cache->name );
if ( cache->dhcppkt && ( settings == &cache->dhcppkt->settings ) ) {
DBGC ( colour, "CACHEDHCP %s recycled from %s\n",
cache->name, netdev->name );
assert ( cache->flags & CACHEDHCP_USED );
unregister_settings ( settings );
cache->flags &= ~CACHEDHCP_USED;
}
}

View File

@ -55,7 +55,7 @@ static int dummy_san_hook ( unsigned int drive, struct uri **uris,
/* Register SAN device */
if ( ( rc = register_sandev ( sandev, drive, flags ) ) != 0 ) {
DBGC ( sandev->drive, "SAN %#02x could not register: %s\n",
DBGC ( sandev, "SAN %#02x could not register: %s\n",
sandev->drive, strerror ( rc ) );
goto err_register;
}
@ -80,7 +80,7 @@ static void dummy_san_unhook ( unsigned int drive ) {
/* Find drive */
sandev = sandev_find ( drive );
if ( ! sandev ) {
DBGC ( drive, "SAN %#02x does not exist\n", drive );
DBG ( "SAN %#02x does not exist\n", drive );
return;
}
@ -95,11 +95,11 @@ static void dummy_san_unhook ( unsigned int drive ) {
* Boot from dummy SAN device
*
* @v drive Drive number
* @v config Boot configuration parameters
* @v filename Filename (or NULL to use default)
* @ret rc Return status code
*/
static int dummy_san_boot ( unsigned int drive __unused,
struct san_boot_config *config __unused ) {
const char *filename __unused ) {
return -EOPNOTSUPP;
}

View File

@ -56,15 +56,8 @@ 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_tag current_image __image_tag = {
.name = "CURRENT",
};
struct image *current_image;
/** Current image trust requirement */
static int require_trusted_images = 0;
@ -79,13 +72,8 @@ 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 );
@ -134,13 +122,10 @@ int image_set_uri ( struct image *image, struct uri *uri ) {
int rc;
/* Set name, if image does not already have one */
if ( ! ( image->name && image->name[0] ) ) {
name = ( uri->path ? uri->path : uri->opaque );
if ( name ) {
name = basename ( ( char * ) name );
if ( ( rc = image_set_name ( image, name ) ) != 0 )
return rc;
}
if ( uri->path && ( ! ( image->name && image->name[0] ) ) ) {
name = basename ( ( char * ) uri->path );
if ( ( rc = image_set_name ( image, name ) ) != 0 )
return rc;
}
/* Update image URI */
@ -276,6 +261,12 @@ 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;
@ -329,23 +320,6 @@ 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
*
@ -372,13 +346,13 @@ int image_exec ( struct image *image ) {
if ( image->uri )
churi ( image->uri );
/* Set as currently running image */
saved_current_image = image_tag ( image, &current_image );
/* Preserve record of any currently-running image */
saved_current_image = current_image;
/* Take out a temporary reference to the image, so that it
* does not get freed when temporarily unregistered.
*/
image_get ( image );
current_image = image_get ( image );
/* Check that this image can be executed */
if ( ! ( image->type && image->type->exec ) ) {
@ -445,7 +419,7 @@ int image_exec ( struct image *image ) {
image_put ( image );
/* Restore previous currently-running image */
image_tag ( saved_current_image, &current_image );
current_image = saved_current_image;
/* Reset current working directory */
churi ( old_cwuri );
@ -468,7 +442,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.image;
struct image *image = current_image;
int rc;
/* Sanity check */
@ -504,17 +478,37 @@ 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_tag ( image, &selected_image );
image->flags |= IMAGE_SELECTED;
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
*

View File

@ -285,7 +285,6 @@ void intf_shutdown ( struct interface *intf, int rc ) {
intf_nullify ( intf );
/* Transfer destination to temporary interface */
intf_temp_init ( &tmp, intf );
tmp.dest = intf->dest;
intf->dest = &null_intf;

Some files were not shown because too many files have changed in this diff Show More