Compare commits

..

1 Commits

Author SHA1 Message Date
dd68e283f8 [build] Allow for building EFI ISOs without syslinux
The isohybrid tool (that creates a partition table to describe the ESP
embedded within the ISO image) relies upon the existence of the
x86-only isolinux.bin file.  This file may not be available on non-x86
build hosts.

We already allow for the possibility that isohybrid may not be present
on the build host, in which case we fall back to creating a non-hybrid
ISO image.  Make a similar allowance for the possibility that the
isolinux.bin file may not be present: require its existence only if we
are attempting to build a BIOS-bootable image, or if we will be
attempting to use isohybrid to create a hybrid ISO image.

Reported-by: Xiaotian Wu <wuxiaotian@loongson.cn>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-07-10 13:51:33 +01:00
275 changed files with 2815 additions and 15500 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 }}
@ -68,14 +68,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 +97,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
#

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

@ -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

@ -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

@ -2,8 +2,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,4 @@
.section ".note.GNU-stack", "", @progbits
.code32
.arch i386
.section ".data", "aw", @progbits

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

@ -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

@ -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

@ -46,12 +46,8 @@ static void efiloong64_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__ ( "idle 0" );
__asm__ __volatile__ ( "idle 0" );
}
PROVIDE_NAP ( efiloong64, cpu_nap, efiloong64_cpu_nap );

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

@ -23,8 +23,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,7 @@
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,7 @@
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

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

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

@ -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

@ -24,8 +24,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

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

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

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

View File

@ -26,9 +26,10 @@ FILE_LICENCE ( GPL2_ONLY )
.section ".note.GNU-stack", "", @progbits
.org 0
.code16
.arch i386
.text
.section ".prefix", "ax", @progbits
.code16
.globl _dsk_start
_dsk_start:

View File

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

View File

@ -3,9 +3,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

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

View File

@ -5,8 +5,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,10 @@
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

@ -42,8 +42,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#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

@ -3,8 +3,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

@ -2,10 +2,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

@ -12,9 +12,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

@ -9,9 +9,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

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

View File

@ -3,6 +3,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

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

View File

@ -3,9 +3,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

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

View File

@ -32,9 +32,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#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

@ -1632,70 +1632,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 );

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

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 */

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

View File

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

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

@ -134,13 +134,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 */

View File

@ -32,8 +32,9 @@ __asmcall int main ( void ) {
initialise();
/* Some devices take an unreasonably long time to initialise */
printf ( "%s initialising devices...\n", product_short_name );
printf ( "%s initialising devices...", product_short_name );
startup();
printf ( "ok\n" );
/* Attempt to boot */
if ( ( rc = ipxe ( NULL ) ) != 0 )

View File

@ -1,67 +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
*
*/
#include <ipxe/timer.h>
#include <ipxe/mp.h>
/** Time to wait for application processors */
#define MP_MAX_CPUID_WAIT_MS 10
/**
* Get boot CPU identifier
*
* @ret id Boot CPU identifier
*/
unsigned int mp_boot_cpuid ( void ) {
unsigned int max = 0;
/* Update maximum to accommodate boot processor */
mp_exec_boot ( mp_update_max_cpuid, &max );
DBGC ( &mp_call, "MP boot processor ID is %#x\n", max );
return max;
}
/**
* Get maximum CPU identifier
*
* @ret max Maximum CPU identifier
*/
unsigned int mp_max_cpuid ( void ) {
unsigned int max = mp_boot_cpuid();
/* Update maximum to accommodate application processors */
mp_start_all ( mp_update_max_cpuid, &max );
mdelay ( MP_MAX_CPUID_WAIT_MS );
DBGC ( &mp_call, "MP observed maximum CPU ID is %#x\n", max );
return max;
}

View File

@ -1,37 +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
*
* Null multiprocessor API
*
*/
#include <ipxe/mp.h>
PROVIDE_MPAPI_INLINE ( null, mp_address );
PROVIDE_MPAPI_INLINE ( null, mp_exec_boot );
PROVIDE_MPAPI_INLINE ( null, mp_start_all );

View File

@ -38,7 +38,7 @@ static void null_san_unhook ( unsigned int drive __unused ) {
}
static int null_san_boot ( unsigned int drive __unused,
struct san_boot_config *config __unused ) {
const char *filename __unused ) {
return -EOPNOTSUPP;
}

View File

@ -31,7 +31,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <ipxe/uuid.h>
#include <ipxe/netdevice.h>
#include <ipxe/menu.h>
#include <ipxe/settings.h>
@ -125,29 +124,6 @@ int parse_timeout ( char *text, unsigned long *value ) {
return 0;
}
/**
* Parse UUID
*
* @v text Text
* @ret uuid UUID value
* @ret rc Return status code
*/
int parse_uuid ( char *text, struct uuid_option *uuid ) {
int rc;
/* Sanity check */
assert ( text != NULL );
/* Parse UUID */
if ( ( rc = uuid_aton ( text, &uuid->buf ) ) != 0 ) {
printf ( "\"%s\": invalid UUID\n", text );
return rc;
}
uuid->value = &uuid->buf;
return 0;
}
/**
* Parse network device name
*

View File

@ -6,9 +6,8 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stddef.h>
#include <stdlib.h>
#include <time.h>
#include <ipxe/timer.h>
static int32_t rnd_seed = 0;
@ -31,9 +30,8 @@ void srandom ( unsigned int seed ) {
long int random ( void ) {
int32_t q;
/* Initialize linear congruential generator */
if ( ! rnd_seed )
srandom ( time ( NULL ) );
if ( ! rnd_seed ) /* Initialize linear congruential generator */
srandom ( currticks() );
/* simplified version of the LCG given in Bruce Schneier's
"Applied Cryptography" */

View File

@ -44,6 +44,16 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/quiesce.h>
#include <ipxe/sanboot.h>
/**
* Default SAN drive number
*
* The drive number is a meaningful concept only in a BIOS
* environment, where it represents the INT13 drive number (0x80 for
* the first hard disk). We retain it in other environments to allow
* for a simple way for iPXE commands to refer to SAN drives.
*/
#define SAN_DEFAULT_DRIVE 0x80
/**
* Timeout for block device commands (in ticks)
*
@ -97,22 +107,6 @@ struct san_device * sandev_find ( unsigned int drive ) {
return NULL;
}
/**
* Find next SAN device by drive number
*
* @v drive Minimum drive number
* @ret sandev SAN device, or NULL
*/
struct san_device * sandev_next ( unsigned int drive ) {
struct san_device *sandev;
list_for_each_entry ( sandev, &san_devices, list ) {
if ( sandev->drive >= drive )
return sandev;
}
return NULL;
}
/**
* Free SAN device
*
@ -203,7 +197,7 @@ static int sanpath_open ( struct san_path *sanpath ) {
/* Open interface */
if ( ( rc = xfer_open_uri ( &sanpath->block, sanpath->uri ) ) != 0 ) {
DBGC ( sandev->drive, "SAN %#02x.%d could not (re)open URI: "
DBGC ( sandev, "SAN %#02x.%d could not (re)open URI: "
"%s\n", sandev->drive, sanpath->index, strerror ( rc ) );
return rc;
}
@ -271,7 +265,7 @@ static void sanpath_block_close ( struct san_path *sanpath, int rc ) {
/* Any closure is an error from our point of view */
if ( rc == 0 )
rc = -ENOTCONN;
DBGC ( sandev->drive, "SAN %#02x.%d closed: %s\n",
DBGC ( sandev, "SAN %#02x.%d closed: %s\n",
sandev->drive, sanpath->index, strerror ( rc ) );
/* Close path */
@ -313,11 +307,11 @@ static void sanpath_step ( struct san_path *sanpath ) {
/* Mark as active path or close as applicable */
if ( ! sandev->active ) {
DBGC ( sandev->drive, "SAN %#02x.%d is active\n",
DBGC ( sandev, "SAN %#02x.%d is active\n",
sandev->drive, sanpath->index );
sandev->active = sanpath;
} else {
DBGC ( sandev->drive, "SAN %#02x.%d is available\n",
DBGC ( sandev, "SAN %#02x.%d is available\n",
sandev->drive, sanpath->index );
sanpath_close ( sanpath, 0 );
}
@ -404,9 +398,8 @@ int sandev_reopen ( struct san_device *sandev ) {
rc = sanpath->path_rc;
break;
}
DBGC ( sandev->drive, "SAN %#02x never became "
"available: %s\n", sandev->drive,
strerror ( rc ) );
DBGC ( sandev, "SAN %#02x never became available: %s\n",
sandev->drive, strerror ( rc ) );
goto err_none;
}
}
@ -460,9 +453,8 @@ static int sandev_command_rw ( struct san_device *sandev,
if ( ( rc = params->rw.block_rw ( &sanpath->block, &sandev->command,
params->rw.lba, params->rw.count,
params->rw.buffer, len ) ) != 0 ) {
DBGC ( sandev->drive, "SAN %#02x.%d could not initiate "
"read/write: %s\n", sandev->drive, sanpath->index,
strerror ( rc ) );
DBGC ( sandev, "SAN %#02x.%d could not initiate read/write: "
"%s\n", sandev->drive, sanpath->index, strerror ( rc ) );
return rc;
}
@ -488,9 +480,8 @@ sandev_command_read_capacity ( struct san_device *sandev,
/* Initiate read capacity command */
if ( ( rc = block_read_capacity ( &sanpath->block,
&sandev->command ) ) != 0 ) {
DBGC ( sandev->drive, "SAN %#02x.%d could not initiate read "
"capacity: %s\n", sandev->drive, sanpath->index,
strerror ( rc ) );
DBGC ( sandev, "SAN %#02x.%d could not initiate read capacity: "
"%s\n", sandev->drive, sanpath->index, strerror ( rc ) );
return rc;
}
@ -574,7 +565,7 @@ sandev_command ( struct san_device *sandev,
int sandev_reset ( struct san_device *sandev ) {
int rc;
DBGC ( sandev->drive, "SAN %#02x reset\n", sandev->drive );
DBGC ( sandev, "SAN %#02x reset\n", sandev->drive );
/* Close and reopen underlying block device */
if ( ( rc = sandev_reopen ( sandev ) ) != 0 )
@ -707,8 +698,8 @@ static int sandev_describe ( struct san_device *sandev ) {
if ( ! desc )
continue;
if ( ( rc = desc->model->complete ( desc ) ) != 0 ) {
DBGC ( sandev->drive, "SAN %#02x.%d could not "
"be described: %s\n", sandev->drive,
DBGC ( sandev, "SAN %#02x.%d could not be "
"described: %s\n", sandev->drive,
sanpath->index, strerror ( rc ) );
return rc;
}
@ -801,8 +792,8 @@ static int sandev_parse_iso9660 ( struct san_device *sandev ) {
/* Read primary volume descriptor */
if ( ( rc = sandev_read ( sandev, lba, count,
virt_to_user ( scratch ) ) ) != 0 ) {
DBGC ( sandev->drive, "SAN %#02x could not read ISO9660 "
"primary volume descriptor: %s\n",
DBGC ( sandev, "SAN %#02x could not read ISO9660 primary"
"volume descriptor: %s\n",
sandev->drive, strerror ( rc ) );
goto err_rw;
}
@ -810,8 +801,8 @@ static int sandev_parse_iso9660 ( struct san_device *sandev ) {
/* Configure as CD-ROM if applicable */
if ( memcmp ( &scratch->primary.fixed, &primary_check,
sizeof ( primary_check ) ) == 0 ) {
DBGC ( sandev->drive, "SAN %#02x contains an ISO9660 "
"filesystem; treating as CD-ROM\n", sandev->drive );
DBGC ( sandev, "SAN %#02x contains an ISO9660 filesystem; "
"treating as CD-ROM\n", sandev->drive );
sandev->blksize_shift = blksize_shift;
sandev->is_cdrom = 1;
}
@ -876,12 +867,11 @@ struct san_device * alloc_sandev ( struct uri **uris, unsigned int count,
*/
int register_sandev ( struct san_device *sandev, unsigned int drive,
unsigned int flags ) {
struct san_device *before;
int rc;
/* Check that drive number is not in use */
if ( sandev_find ( drive ) != NULL ) {
DBGC ( sandev->drive, "SAN %#02x is already in use\n", drive );
DBGC ( sandev, "SAN %#02x is already in use\n", drive );
rc = -EADDRINUSE;
goto err_in_use;
}
@ -910,13 +900,9 @@ int register_sandev ( struct san_device *sandev, unsigned int drive,
if ( ( rc = sandev_parse_iso9660 ( sandev ) ) != 0 )
goto err_iso9660;
/* Add to list of SAN devices, in drive order */
for_each_sandev ( before ) {
if ( before->drive > sandev->drive )
break;
}
list_add_tail ( &sandev->list, &before->list );
DBGC ( sandev->drive, "SAN %#02x registered\n", sandev->drive );
/* Add to list of SAN devices */
list_add_tail ( &sandev->list, &san_devices );
DBGC ( sandev, "SAN %#02x registered\n", sandev->drive );
return 0;
@ -950,7 +936,7 @@ void unregister_sandev ( struct san_device *sandev ) {
/* Remove ACPI descriptors */
sandev_undescribe ( sandev );
DBGC ( sandev->drive, "SAN %#02x unregistered\n", sandev->drive );
DBGC ( sandev, "SAN %#02x unregistered\n", sandev->drive );
}
/** The "san-drive" setting */

View File

@ -2194,37 +2194,6 @@ const struct setting_type setting_type_base64 __setting_type = {
.format = format_base64_setting,
};
/**
* Parse UUID/GUID setting value
*
* @v type Setting type
* @v value Formatted setting value
* @v buf Buffer to contain raw value
* @v len Length of buffer
* @v size Integer size, in bytes
* @ret len Length of raw value, or negative error
*/
static int parse_uuid_setting ( const struct setting_type *type,
const char *value, void *buf, size_t len ) {
union uuid uuid;
int rc;
/* Parse UUID */
if ( ( rc = uuid_aton ( value, &uuid ) ) != 0 )
return rc;
/* Mangle GUID byte ordering */
if ( type == &setting_type_guid )
uuid_mangle ( &uuid );
/* Copy value */
if ( len > sizeof ( uuid ) )
len = sizeof ( uuid );
memcpy ( buf, uuid.raw, len );
return ( sizeof ( uuid ) );
}
/**
* Format UUID/GUID setting value
*
@ -2258,14 +2227,12 @@ static int format_uuid_setting ( const struct setting_type *type,
/** UUID setting type */
const struct setting_type setting_type_uuid __setting_type = {
.name = "uuid",
.parse = parse_uuid_setting,
.format = format_uuid_setting,
};
/** GUID setting type */
const struct setting_type setting_type_guid __setting_type = {
.name = "guid",
.parse = parse_uuid_setting,
.format = format_uuid_setting,
};
@ -2650,113 +2617,6 @@ struct builtin_setting unixtime_builtin_setting __builtin_setting = {
.fetch = unixtime_fetch,
};
/**
* Fetch current working URI-related setting
*
* @v data Buffer to fill with setting data
* @v len Length of buffer
* @v rel Relative URI string
* @ret len Length of setting data, or negative error
*/
static int cwuri_fetch_uri ( void *data, size_t len, const char *rel ) {
struct uri *reluri;
struct uri *uri;
char *uristring;
int ret;
/* Check that current working URI is set */
if ( ! cwuri ) {
ret = -ENOENT;
goto err_unset;
}
/* Construct relative URI */
reluri = parse_uri ( rel );
if ( ! reluri ) {
ret = -ENOMEM;
goto err_parse;
}
/* Construct resolved URI */
uri = resolve_uri ( cwuri, reluri );
if ( ! uri ) {
ret = -ENOMEM;
goto err_resolve;
}
/* Format URI string into allocated buffer (with NUL) */
uristring = format_uri_alloc ( uri );
if ( ! uristring ) {
ret = -ENOMEM;
goto err_format;
}
/* Copy URI string to buffer */
strncpy ( data, uristring, len );
ret = strlen ( uristring );
free ( uristring );
err_format:
uri_put ( uri );
err_resolve:
uri_put ( reluri );
err_parse:
err_unset:
return ret;
}
/**
* Fetch current working URI setting
*
* @v data Buffer to fill with setting data
* @v len Length of buffer
* @ret len Length of setting data, or negative error
*/
static int cwuri_fetch ( void *data, size_t len ) {
return cwuri_fetch_uri ( data, len, "" );
}
/**
* Fetch current working directory URI setting
*
* @v data Buffer to fill with setting data
* @v len Length of buffer
* @ret len Length of setting data, or negative error
*/
static int cwduri_fetch ( void *data, size_t len ) {
return cwuri_fetch_uri ( data, len, "." );
}
/** Current working URI setting */
const struct setting cwuri_setting __setting ( SETTING_MISC, cwuri ) = {
.name = "cwuri",
.description = "Current working URI",
.type = &setting_type_string,
.scope = &builtin_scope,
};
/** Current working directory URI setting */
const struct setting cwduri_setting __setting ( SETTING_MISC, cwduri ) = {
.name = "cwduri",
.description = "Current working directory URI",
.type = &setting_type_string,
.scope = &builtin_scope,
};
/** Current working URI built-in setting */
struct builtin_setting cwuri_builtin_setting __builtin_setting = {
.setting = &cwuri_setting,
.fetch = cwuri_fetch,
};
/** Current working directory URI built-in setting */
struct builtin_setting cwduri_builtin_setting __builtin_setting = {
.setting = &cwduri_setting,
.fetch = cwduri_fetch,
};
/**
* Fetch built-in setting
*

View File

@ -25,9 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/base16.h>
#include <ipxe/uuid.h>
/** @file
@ -55,29 +53,3 @@ const char * uuid_ntoa ( const union uuid *uuid ) {
uuid->canonical.e[4], uuid->canonical.e[5] );
return buf;
}
/**
* Parse UUID
*
* @v string UUID string
* @v uuid UUID to fill in
* @ret rc Return status code
*/
int uuid_aton ( const char *string, union uuid *uuid ) {
int len;
int rc;
/* Decode as hex string with optional '-' separator */
len = hex_decode ( ( '-' | HEX_DECODE_OPTIONAL ), string, uuid->raw,
sizeof ( *uuid ) );
if ( len < 0 ) {
rc = len;
return rc;
}
/* Check length */
if ( len != sizeof ( *uuid ) )
return -EINVAL;
return 0;
}

View File

@ -50,31 +50,6 @@ static struct profiler bigint_mod_multiply_rescale_profiler __profiler =
static struct profiler bigint_mod_multiply_subtract_profiler __profiler =
{ .name = "bigint_mod_multiply.subtract" };
/**
* Conditionally swap big integers (in constant time)
*
* @v first0 Element 0 of big integer to be conditionally swapped
* @v second0 Element 0 of big integer to be conditionally swapped
* @v size Number of elements in big integers
* @v swap Swap first and second big integers
*/
void bigint_swap_raw ( bigint_element_t *first0, bigint_element_t *second0,
unsigned int size, int swap ) {
bigint_element_t mask;
bigint_element_t xor;
unsigned int i;
/* Construct mask */
mask = ( ( bigint_element_t ) ( ! swap ) - 1 );
/* Conditionally swap elements */
for ( i = 0 ; i < size ; i++ ) {
xor = ( mask & ( first0[i] ^ second0[i] ) );
first0[i] ^= xor;
second0[i] ^= xor;
}
}
/**
* Perform modular multiplication of big integers
*

View File

@ -1,695 +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
*
* DES algorithm
*
* DES was not designed to be implemented in software, and therefore
* contains a large number of bit permutation operations that are
* essentially free in hardware (requiring only wires, no gates) but
* expensive in software.
*
* Since DES is no longer used as a practical block cipher for large
* volumes of data, we optimise for code size, and do not attempt to
* obtain fast throughput.
*
* The algorithm is specified in NIST SP 800-67, downloadable from
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf
*/
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/rotate.h>
#include <ipxe/crypto.h>
#include <ipxe/ecb.h>
#include <ipxe/cbc.h>
#include <ipxe/init.h>
#include <ipxe/des.h>
/**
* DES shift schedule
*
* The DES shift schedule (ordered from round 16 down to round 1) is
* {1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,1}. In binary, this may be
* represented as {1,10,10,10,10,10,10,1,10,10,10,10,10,10,1,1} and
* concatenated (without padding) to produce a single binary integer
* 1101010101010110101010101011 (equal to 0x0d556aab in hexadecimal).
*
* This integer may then be consumed LSB-first, where a 1 bit
* indicates a shift and the generation of a round key, and a 0 bit
* indicates a shift without the generation of a round key.
*/
#define DES_SCHEDULE 0x0d556aab
/**
* Define an element pair in a DES S-box
*
* @v x Upper element of element pair
* @v y Lower element of element pair
*
* DES S-box elements are 4-bit values. We encode two values per
* byte, ordering the elements so that the six-bit input value may be
* used directly as a lookup index.
*
* Specifically, if the input value is {r1,c3,c2,c1,c0,r0}, where
* {r1,r0} is the table row index and {c3,c2,c1,c0} is the table
* column index (as used in the DES specification), then:
*
* - {r1,c3,c2,c1,c0} is the byte index into the table
*
* - (4*r0) is the required bit shift to extract the 4-bit value
*/
#define SBYTE( x, y ) ( ( (y) << 4 ) | (x) )
/**
* Define a row pair in a DES S-box
*
* @v x0..xf Upper row of row pair
* @v y0..yf Lower row of row pair
*/
#define SBOX( x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf, \
y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, ya, yb, yc, yd, ye, yf ) \
SBYTE ( x0, y0 ), SBYTE ( x1, y1 ), SBYTE ( x2, y2 ), SBYTE ( x3, y3 ),\
SBYTE ( x4, y4 ), SBYTE ( x5, y5 ), SBYTE ( x6, y6 ), SBYTE ( x7, y7 ),\
SBYTE ( x8, y8 ), SBYTE ( x9, y9 ), SBYTE ( xa, ya ), SBYTE ( xb, yb ),\
SBYTE ( xc, yc ), SBYTE ( xd, yd ), SBYTE ( xe, ye ), SBYTE ( xf, yf )
/** DES S-boxes S1..S8 */
static const uint8_t des_s[8][32] = { {
/* S1 */
SBOX ( 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 ),
SBOX ( 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 )
}, {
/* S2 */
SBOX ( 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 ),
SBOX ( 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 )
}, {
/* S3 */
SBOX ( 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 ),
SBOX ( 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 )
}, {
/* S4 */
SBOX ( 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 ),
SBOX ( 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 )
}, {
/* S5 */
SBOX ( 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 ),
SBOX ( 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 )
}, {
/* S6 */
SBOX ( 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 ),
SBOX ( 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 )
}, {
/* S7 */
SBOX ( 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 ),
SBOX ( 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 )
}, {
/* S8 */
SBOX ( 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 ),
SBOX ( 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 )
} };
/**
* Define a bit index within permuted choice 2 (PC2)
*
* @v bit Bit index
*
* Permuted choice 2 (PC2) is used to select bits from a concatenated
* pair of 28-bit registers ("C" and "D") as part of the key schedule.
* We store these as 32-bit registers and so must add 4 to indexes
* above 28.
*/
#define DES_PC2( x ) ( (x) + ( ( (x) > 28 ) ? 4 : 0 ) )
/**
* Define six bits of permuted choice 2 (PC2)
*
* @v r1:r0 Bits corresponding to S-box row index
* @v c3:c0 Bits corresponding to S-box column index
*
* There are 8 steps within a DES round (one step per S-box). Each
* step requires six bits of the round key, corresponding to the S-box
* input value {r1,c3,c2,c1,c0,r0}, where {r1,r0} is the table row
* index and {c3,c2,c1,c0} is the table column index.
*
* As an optimisation, we store the least significant of the 6 bits in
* the sign bit of a signed 8-bit value, and the remaining 5 bits in
* the least significant 5 bits of the 8-bit value. See the comments
* in des_sbox() for further details.
*/
#define DES_PC2R( r1, c3, c2, c1, c0, r0 ) \
DES_PC2 ( r0 ), /* LSB stored in sign bit */ \
DES_PC2 ( r0 ), /* Unused bit */ \
DES_PC2 ( r0 ), /* Unused bit */ \
DES_PC2 ( r1 ), /* Remaining 5 bits */ \
DES_PC2 ( c3 ), /* ... */ \
DES_PC2 ( c2 ), /* ... */ \
DES_PC2 ( c1 ), /* ... */ \
DES_PC2 ( c0 ) /* ... */
/**
* A DES systematic permutation generator
*
* Many of the permutations used in DES comprise systematic bit
* patterns. We generate these permutations at runtime to save on
* code size.
*/
struct des_generator {
/** Permutation */
uint8_t *permutation;
/** Seed value */
uint32_t seed;
};
/**
* Define a DES permutation generator
*
* @v PERMUTATION Permutation
* @v OFFSET Fixed input bit offset (0 or 1)
* @v INV<n> Input bit index bit <n> should be inverted
* @v BIT<n> Source bit for input bit index bit <n>
* @ret generator Permutation generator
*/
#define DES_GENERATOR( PERMUTATION, OFFSET, INV5, BIT5, INV4, BIT4, \
INV3, BIT3, INV2, BIT2, INV1, BIT1, INV0, BIT0 ) \
{ \
.permutation = (PERMUTATION), \
.seed = ( ( (INV0) << 31 ) | ( (BIT0) << 28 ) | \
( (INV1) << 27 ) | ( (BIT1) << 24 ) | \
( (INV2) << 23 ) | ( (BIT2) << 20 ) | \
( (INV3) << 19 ) | ( (BIT3) << 16 ) | \
( (INV4) << 15 ) | ( (BIT4) << 12 ) | \
( (INV5) << 11 ) | ( (BIT5) << 8 ) | \
( ( uint32_t ) sizeof (PERMUTATION) - 1 ) | \
(OFFSET) ), \
}
/** DES permuted choice 1 (PC1) "C" register */
static uint8_t des_pc1c[29];
/** DES permuted choice 1 (PC1) "D" register */
static uint8_t des_pc1d[33];
/** DES permuted choice 2 (PC2) */
static const uint8_t des_pc2[65] = {
DES_PC2R ( 14, 17, 11, 24, 1, 5 ),
DES_PC2R ( 3, 28, 15, 6, 21, 10 ),
DES_PC2R ( 23, 19, 12, 4, 26, 8 ),
DES_PC2R ( 16, 7, 27, 20, 13, 2 ),
DES_PC2R ( 41, 52, 31, 37, 47, 55 ),
DES_PC2R ( 30, 40, 51, 45, 33, 48 ),
DES_PC2R ( 44, 49, 39, 56, 34, 53 ),
DES_PC2R ( 46, 42, 50, 36, 29, 32 ),
0 /* terminator */
};
/** DES initial permutation (IP) */
static uint8_t des_ip[65];
/** DES data permutation (P) */
static const uint8_t des_p[33] = {
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25,
0 /* terminator */
};
/** DES final / inverse initial permutation (FP / IP^-1) */
static uint8_t des_fp[65];
/** DES permutation generators */
static struct des_generator des_generators[] = {
/* The DES initial permutation transforms the bit index
* {x5,x4,x3,x2,x1,x0}+1 into {~x2,~x1,~x0,x4,x3,~x5}+1
*/
DES_GENERATOR ( des_ip, 1, 1, 2, 1, 1, 1, 0, 0, 4, 0, 3, 1, 5 ),
/* The DES final permutation transforms the bit index
* {x5,x4,x3,x2,x1,x0}+1 into {~x0,x2,x1,~x5,~x4,~x3}+1
*
* There is an asymmetry in the DES block diagram for the last
* of the 16 rounds, which is functionally equivalent to
* performing 16 identical rounds and then swapping the left
* and right halves before applying the final permutation. We
* may therefore account for this asymmetry by inverting the
* MSB in each bit index, to point to the corresponding bit in
* the other half.
*
* This is equivalent to using a permutation that transforms
* {x5,x4,x3,x2,x1,x0}+1 into {x0,x2,x1,~x5,~x4,~x3}+1
*/
DES_GENERATOR ( des_fp, 1, 0, 0, 0, 2, 0, 1, 1, 5, 1, 4, 1, 3 ),
/* The "C" half of DES permuted choice 1 (PC1) transforms the
* bit index {x5,x4,x3,x2,x1,x0}+1 into {~x2,~x1,~x0,x5,x4,x3}+1
*/
DES_GENERATOR ( des_pc1c, 1, 1, 2, 1, 1, 1, 0, 0, 5, 0, 4, 0, 3 ),
/* The "D" half of DES permuted choice 1 (PC1) transforms the
* bit index {x5,x4,x3,x2,x1,x0}+1 into {~x2,~x1,~x0,~x5,~x4,~x3}+0
*
* Due to the idosyncratic design choice of using 28-bit
* registers in the DES key expansion schedule, the final four
* permutation values appear at indices [28:31] instead of
* [24:27]. This is adjusted for in @c des_setkey().
*/
DES_GENERATOR ( des_pc1d, 0, 1, 2, 1, 1, 1, 0, 1, 5, 1, 4, 1, 3 ),
};
/**
* Generate DES permutation
*
* @v generator Generator
*/
static __attribute__ (( noinline )) void
des_generate ( struct des_generator *generator ) {
uint8_t *permutation = generator->permutation;
uint32_t seed = generator->seed;
unsigned int index = 0;
uint8_t accum;
uint8_t bit;
/* Generate permutations
*
* This loop is optimised for code size on a
* register-constrained architecture such as i386.
*/
do {
/* Rotate seed to access MSB's bit descriptor */
seed = ror32 ( seed, 8 );
/* Initialise accumulator with six flag bits */
accum = 0xfc;
/* Accumulate bits until all six flag bits are cleared */
do {
/* Extract specified bit from index. Use a
* rotation instead of a shift, since this
* will allow the mask to be elided.
*/
bit = ror8 ( index, ( seed & 0x07 ) );
seed = ror32 ( seed, 3 );
/* Toggle bit if applicable */
bit ^= seed;
seed = ror32 ( seed, 1 );
/* Add bit to accumulator and clear one flag bit */
accum <<= 1;
accum |= ( bit & 0x01 );
} while ( accum & 0x80 );
/* Add constant offset if applicable */
accum += ( seed & 0x01 );
/* Store permutation */
permutation[index] = accum;
/* Loop until reaching length (which is always even) */
} while ( ++index < ( seed & 0xfe ) );
DBGC2 ( permutation, "DES generated permutation %p:\n", permutation );
DBGC2_HDA ( permutation, 0, permutation,
( ( seed & 0xfe ) + 1 /* zero terminator */ ) );
}
/**
* Initialise permutations
*/
static void des_init ( void ) {
unsigned int i;
/* Generate all generated permutations */
for ( i = 0 ; i < ( sizeof ( des_generators ) /
sizeof ( des_generators[0] ) ) ; i++ ) {
des_generate ( &des_generators[i] );
}
}
/** Initialisation function */
struct init_fn des_init_fn __init_fn ( INIT_NORMAL ) = {
.initialise = des_init,
};
/**
* Perform bit permutation
*
* @v permutation Bit permutation (zero-terminated)
* @v in Input value
* @v out Output value
*/
static void des_permute ( const uint8_t *permutation, const uint8_t *in,
uint8_t *out ) {
uint8_t mask = 0x80;
uint8_t accum = 0;
unsigned int bit;
/* Extract individual input bits to construct output value */
while ( ( bit = *(permutation++) ) ) {
bit--;
if ( in[ bit / 8 ] & ( 0x80 >> ( bit % 8 ) ) )
accum |= mask;
*out = accum;
mask = ror8 ( mask, 1 );
if ( mask == 0x80 ) {
out++;
accum = 0;
}
}
}
/**
* Perform DES S-box substitution
*
* @v in 32-bit input value (native endian)
* @v rkey 48-bit round key
* @ret out 32-bit output value (native endian)
*/
static uint32_t des_sbox ( uint32_t in, const union des_round_key *rkey ) {
uint32_t out = 0;
uint32_t lookup;
int32_t key;
uint8_t sub;
unsigned int i;
/* Perform input expansion, key addition, and S-box substitution */
for ( i = 0 ; i < 8 ; i++ ) {
/* Rotate input and output */
out = rol32 ( out, 4 );
in = rol32 ( in, 4 );
/* Extract step key from relevant 6 bits of round key
*
* The least significant of the 6 bits (corresponding
* to bit r0 in the S-box lookup index) is stored in
* the sign bit of the step key byte. It will
* therefore be propagated via sign extension to the
* MSB of the 32-bit step key.
*
* The remaining 5 of the 6 bits (corresponding to
* bits {r1,c3,c2,c1,c0} in the S-box lookup index)
* are stored in the least significant 5 bits of the
* step key byte and will end up in the least
* significant 5 bits of the 32-bit step key.
*/
key = rkey->step[i];
/* Add step key to input to produce S-box lookup index
*
* We do not ever perform an explicit expansion of the
* input value from 32 to 48 bits. Instead, we rotate
* the 32-bit input value by 4 bits on each step, and
* extract the relevant 6 bits.
*
* The least significant of the 6 bits (corresponding
* to bit r0 in the S-box lookup index) is currently
* in the MSB of the 32-bit (rotated) input value.
*
* The remaining 5 of the 6 bits (corresponding to
* bits {r1,c3,c2,c1,c0} in the S-box lookup index)
* are currently in the least significant 5 bits of
* the 32-bit (rotated) input value.
*
* This aligns with the placement of the bits in the
* step key (see above), and we can therefore perform
* a single XOR to add the 6-bit step key to the
* relevant 6 bits of the input value.
*/
lookup = ( in ^ key );
/* Look up S[i][in ^ key] from S-box
*
* We have bits {r1,c3,c2,c1,c0} in the least
* significant 5 bits of the lookup index, and so can
* use the masked lookup index directly as a byte
* index into the relevant S-box to extract the byte
* containing both {r1,c3,c2,c1,c0,'0'} and
* {r1,c3,c2,c1,c0,'1'}.
*
* We then use the MSB of the 32-bit lookup index to
* extract the relevant nibble for the full lookup
* index {r1,c3,c2,c1,c0,r0}.
*/
sub = des_s[i][ lookup & 0x1f ];
sub >>= ( ( lookup >> 29 ) & 4 );
sub &= 0x0f;
/* Substitute S[i][input ^ key] into output */
out |= sub;
}
return out;
}
/**
* Perform a single DES round
*
* @v block DES block
* @v rkey 48-bit round key
*/
static void des_round ( union des_block *block,
const union des_round_key *rkey ) {
union des_dword sbox;
uint32_t left;
uint32_t right;
/* Extract left and right halves L[n-1] and R[n-1] */
left = block->left.dword;
right = block->right.dword;
DBGC2 ( block, "DES L=%08x R=%08x K=%08x%08x", be32_to_cpu ( left ),
be32_to_cpu ( right ), be32_to_cpu ( rkey->dword[0] ),
be32_to_cpu ( rkey->dword[1] ) );
/* L[n] = R[n-1] */
block->left.dword = right;
/* Calculate Feistel function f(R[n-1], K[n]) */
sbox.dword = cpu_to_be32 ( des_sbox ( be32_to_cpu ( right ), rkey ) );
des_permute ( des_p, sbox.byte, block->right.byte );
/* R[n] = L[n-1] + f(R[n-1], K[n]) */
block->right.dword ^= left;
DBGC2 ( block, " => L=%08x R=%08x\n",
be32_to_cpu ( block->left.dword ),
be32_to_cpu ( block->right.dword ) );
}
/**
* Perform all DES rounds
*
* @v in Input DES block
* @v out Output DES block
* @v rkey Starting 48-bit round key
* @v offset Byte offset between round keys
*/
static void des_rounds ( const union des_block *in, union des_block *out,
const union des_round_key *rkey,
ssize_t offset ) {
union des_block tmp;
unsigned int i;
/* Apply initial permutation */
des_permute ( des_ip, in->byte, tmp.byte );
/* Perform all DES rounds, consuming keys in the specified order */
for ( i = 0 ; i < DES_ROUNDS ; i++ ) {
des_round ( &tmp, rkey );
rkey = ( ( ( void * ) rkey ) + offset );
}
/* Apply final permutation */
DBGC ( &tmp, "DES %scrypted %08x%08x => ",
( ( offset > 0 ) ? "en" : "de" ), be32_to_cpu ( in->dword[0] ),
be32_to_cpu ( in->dword[1] ) );
des_permute ( des_fp, tmp.byte, out->byte );
DBGC ( &tmp, "%08x%08x\n", be32_to_cpu ( out->dword[0] ),
be32_to_cpu ( out->dword[1] ) );
}
/**
* Rotate 28-bit word
*
* @v dword 28-bit dword value
* @ret dword Rotated 28-bit dword value
*/
static uint32_t des_rol28 ( uint32_t dword ) {
int32_t sdword;
/* Convert to native-endian */
sdword = be32_to_cpu ( dword );
/* Signed shift right by 4 places to copy bit 31 to bits 27:31 */
sdword >>= 4;
/* Rotate left */
sdword = rol32 ( sdword, 1 );
/* Shift left by 4 places to restore bit positions */
sdword <<= 4;
/* Convert back to big-endian */
dword = cpu_to_be32 ( sdword );
return dword;
}
/**
* Set key
*
* @v ctx Context
* @v key Key
* @v keylen Key length
* @ret rc Return status code
*/
static int des_setkey ( void *ctx, const void *key, size_t keylen ) {
struct des_context *des = ctx;
union des_round_key *rkey = des->rkey;
union des_block reg;
uint32_t schedule;
/* Validate key length */
if ( keylen != DES_BLOCKSIZE )
return -EINVAL;
DBGC ( des, "DES %p new key:\n", des );
DBGC_HDA ( des, 0, key, keylen );
/* Apply permuted choice 1 */
des_permute ( des_pc1c, key, reg.c.byte );
des_permute ( des_pc1d, key, reg.d.byte );
reg.d.byte[3] <<= 4; /* see comment for @c des_pc1d */
DBGC2 ( des, "DES %p C[ 0]=%07x D[ 0]=%07x\n",
des, ( be32_to_cpu ( reg.c.dword ) >> 4 ),
( be32_to_cpu ( reg.d.dword ) >> 4 ) );
/* Generate round keys */
for ( schedule = DES_SCHEDULE ; schedule ; schedule >>= 1 ) {
/* Shift 28-bit words */
reg.c.dword = des_rol28 ( reg.c.dword );
reg.d.dword = des_rol28 ( reg.d.dword );
/* Skip rounds according to shift schedule */
if ( ! ( schedule & 1 ) )
continue;
/* Apply permuted choice 2 */
des_permute ( des_pc2, reg.byte, rkey->byte );
DBGC2 ( des, "DES %p C[%2zd]=%07x D[%2zd]=%07x K[%2zd]="
"%08x%08x\n", des, ( ( rkey - des->rkey ) + 1 ),
( be32_to_cpu ( reg.c.dword ) >> 4 ),
( ( rkey - des->rkey ) + 1 ),
( be32_to_cpu ( reg.d.dword ) >> 4 ),
( ( rkey - des->rkey ) + 1 ),
be32_to_cpu ( rkey->dword[0] ),
be32_to_cpu ( rkey->dword[1] ) );
/* Move to next key */
rkey++;
}
/* Sanity check */
assert ( rkey == &des->rkey[DES_ROUNDS] );
return 0;
}
/**
* Encrypt data
*
* @v ctx Context
* @v src Data to encrypt
* @v dst Buffer for encrypted data
* @v len Length of data
*/
static void des_encrypt ( void *ctx, const void *src, void *dst, size_t len ) {
struct des_context *des = ctx;
/* Sanity check */
assert ( len == DES_BLOCKSIZE );
/* Cipher using keys in forward direction */
des_rounds ( src, dst, &des->rkey[0], sizeof ( des->rkey[0] ) );
}
/**
* Decrypt data
*
* @v ctx Context
* @v src Data to decrypt
* @v dst Buffer for decrypted data
* @v len Length of data
*/
static void des_decrypt ( void *ctx, const void *src, void *dst, size_t len ) {
struct des_context *des = ctx;
/* Sanity check */
assert ( len == DES_BLOCKSIZE );
/* Cipher using keys in reverse direction */
des_rounds ( src, dst, &des->rkey[ DES_ROUNDS - 1 ],
-sizeof ( des->rkey[0] ) );
}
/** Basic DES algorithm */
struct cipher_algorithm des_algorithm = {
.name = "des",
.ctxsize = sizeof ( struct des_context ),
.blocksize = DES_BLOCKSIZE,
.alignsize = 0,
.authsize = 0,
.setkey = des_setkey,
.setiv = cipher_null_setiv,
.encrypt = des_encrypt,
.decrypt = des_decrypt,
.auth = cipher_null_auth,
};
/* DES in Electronic Codebook mode */
ECB_CIPHER ( des_ecb, des_ecb_algorithm,
des_algorithm, struct des_context, DES_BLOCKSIZE );
/* DES in Cipher Block Chaining mode */
CBC_CIPHER ( des_cbc, des_cbc_algorithm,
des_algorithm, struct des_context, DES_BLOCKSIZE );

View File

@ -109,9 +109,6 @@ static union gcm_block gcm_cached_mult[256];
*/
static uint16_t gcm_cached_reduce[256];
/** Offset of a field within GCM context */
#define gcm_offset( field ) offsetof ( struct gcm_context, field )
/**
* Reverse bits in a byte
*
@ -472,14 +469,16 @@ int gcm_setkey ( struct gcm_context *context, const void *key, size_t keylen,
* @v ivlen Initialisation vector length
*/
void gcm_setiv ( struct gcm_context *context, const void *iv, size_t ivlen ) {
union gcm_block *check = ( ( void * ) context );
/* Sanity checks */
linker_assert ( &context->hash == check, gcm_bad_layout );
linker_assert ( &context->len == check + 1, gcm_bad_layout );
linker_assert ( &context->ctr == check + 2, gcm_bad_layout );
linker_assert ( &context->key == check + 3, gcm_bad_layout );
/* Reset non-key state */
memset ( context, 0, gcm_offset ( key ) );
build_assert ( gcm_offset ( key ) > gcm_offset ( hash ) );
build_assert ( gcm_offset ( key ) > gcm_offset ( len ) );
build_assert ( gcm_offset ( key ) > gcm_offset ( ctr ) );
build_assert ( gcm_offset ( key ) < gcm_offset ( raw_cipher ) );
build_assert ( gcm_offset ( key ) < gcm_offset ( raw_ctx ) );
memset ( context, 0, offsetof ( typeof ( *context ), key ) );
/* Reset counter */
context->ctr.ctr.value = cpu_to_be32 ( 1 );
@ -498,12 +497,7 @@ void gcm_setiv ( struct gcm_context *context, const void *iv, size_t ivlen ) {
assert ( context->len.len.add == 0 );
/* Reset non-key, non-counter state */
memset ( context, 0, gcm_offset ( ctr ) );
build_assert ( gcm_offset ( ctr ) > gcm_offset ( hash ) );
build_assert ( gcm_offset ( ctr ) > gcm_offset ( len ) );
build_assert ( gcm_offset ( ctr ) < gcm_offset ( key ) );
build_assert ( gcm_offset ( ctr ) < gcm_offset ( raw_cipher ) );
build_assert ( gcm_offset ( ctr ) < gcm_offset ( raw_ctx ) );
memset ( context, 0, offsetof ( typeof ( *context ), ctr ) );
}
DBGC2 ( context, "GCM %p Y[0]:\n", context );

View File

@ -155,11 +155,11 @@ static void md4_digest ( struct md4_context *context ) {
/* Sanity checks */
assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 );
build_assert ( &u.ddd.dd.digest.h[0] == a );
build_assert ( &u.ddd.dd.digest.h[1] == b );
build_assert ( &u.ddd.dd.digest.h[2] == c );
build_assert ( &u.ddd.dd.digest.h[3] == d );
build_assert ( &u.ddd.dd.data.dword[0] == w );
linker_assert ( &u.ddd.dd.digest.h[0] == a, md4_bad_layout );
linker_assert ( &u.ddd.dd.digest.h[1] == b, md4_bad_layout );
linker_assert ( &u.ddd.dd.digest.h[2] == c, md4_bad_layout );
linker_assert ( &u.ddd.dd.digest.h[3] == d, md4_bad_layout );
linker_assert ( &u.ddd.dd.data.dword[0] == w, md4_bad_layout );
DBGC ( context, "MD4 digesting:\n" );
DBGC_HDA ( context, 0, &context->ddd.dd.digest,

View File

@ -178,11 +178,11 @@ static void md5_digest ( struct md5_context *context ) {
/* Sanity checks */
assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 );
build_assert ( &u.ddd.dd.digest.h[0] == a );
build_assert ( &u.ddd.dd.digest.h[1] == b );
build_assert ( &u.ddd.dd.digest.h[2] == c );
build_assert ( &u.ddd.dd.digest.h[3] == d );
build_assert ( &u.ddd.dd.data.dword[0] == w );
linker_assert ( &u.ddd.dd.digest.h[0] == a, md5_bad_layout );
linker_assert ( &u.ddd.dd.digest.h[1] == b, md5_bad_layout );
linker_assert ( &u.ddd.dd.digest.h[2] == c, md5_bad_layout );
linker_assert ( &u.ddd.dd.digest.h[3] == d, md5_bad_layout );
linker_assert ( &u.ddd.dd.data.dword[0] == w, md5_bad_layout );
DBGC ( context, "MD5 digesting:\n" );
DBGC_HDA ( context, 0, &context->ddd.dd.digest,

View File

@ -1,61 +0,0 @@
/*
* Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <byteswap.h>
#include <ipxe/rsa.h>
#include <ipxe/aes.h>
#include <ipxe/sha1.h>
#include <ipxe/sha256.h>
#include <ipxe/tls.h>
/** TLS_DHE_RSA_WITH_AES_128_CBC_SHA cipher suite */
struct tls_cipher_suite
tls_dhe_rsa_with_aes_128_cbc_sha __tls_cipher_suite ( 15 ) = {
.code = htons ( TLS_DHE_RSA_WITH_AES_128_CBC_SHA ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA1_DIGEST_SIZE,
.exchange = &tls_dhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha1_algorithm,
.handshake = &sha256_algorithm,
};
/** TLS_DHE_RSA_WITH_AES_256_CBC_SHA cipher suite */
struct tls_cipher_suite
tls_dhe_rsa_with_aes_256_cbc_sha __tls_cipher_suite ( 16 ) = {
.code = htons ( TLS_DHE_RSA_WITH_AES_256_CBC_SHA ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA1_DIGEST_SIZE,
.exchange = &tls_dhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha1_algorithm,
.handshake = &sha256_algorithm,
};

View File

@ -1,60 +0,0 @@
/*
* Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <byteswap.h>
#include <ipxe/rsa.h>
#include <ipxe/aes.h>
#include <ipxe/sha256.h>
#include <ipxe/tls.h>
/** TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 cipher suite */
struct tls_cipher_suite
tls_dhe_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite ( 13 ) = {
.code = htons ( TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA256_DIGEST_SIZE,
.exchange = &tls_dhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha256_algorithm,
.handshake = &sha256_algorithm,
};
/** TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 cipher suite */
struct tls_cipher_suite
tls_dhe_rsa_with_aes_256_cbc_sha256 __tls_cipher_suite ( 14 ) = {
.code = htons ( TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA256_DIGEST_SIZE,
.exchange = &tls_dhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha256_algorithm,
.handshake = &sha256_algorithm,
};

View File

@ -1,45 +0,0 @@
/*
* Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <byteswap.h>
#include <ipxe/rsa.h>
#include <ipxe/aes.h>
#include <ipxe/sha256.h>
#include <ipxe/tls.h>
/** TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 cipher suite */
struct tls_cipher_suite
tls_dhe_rsa_with_aes_128_gcm_sha256 __tls_cipher_suite ( 11 ) = {
.code = htons ( TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 4,
.record_iv_len = 8,
.mac_len = 0,
.exchange = &tls_dhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_gcm_algorithm,
.digest = &sha256_algorithm,
.handshake = &sha256_algorithm,
};

View File

@ -1,45 +0,0 @@
/*
* Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <byteswap.h>
#include <ipxe/rsa.h>
#include <ipxe/aes.h>
#include <ipxe/sha512.h>
#include <ipxe/tls.h>
/** TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 cipher suite */
struct tls_cipher_suite
tls_dhe_rsa_with_aes_256_gcm_sha384 __tls_cipher_suite ( 12 ) = {
.code = htons ( TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 4,
.record_iv_len = 8,
.mac_len = 0,
.exchange = &tls_dhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_gcm_algorithm,
.digest = &sha384_algorithm,
.handshake = &sha384_algorithm,
};

View File

@ -1,61 +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 (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 <byteswap.h>
#include <ipxe/rsa.h>
#include <ipxe/aes.h>
#include <ipxe/sha1.h>
#include <ipxe/sha256.h>
#include <ipxe/tls.h>
/** TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA cipher suite */
struct tls_cipher_suite
tls_ecdhe_rsa_with_aes_128_cbc_sha __tls_cipher_suite ( 05 ) = {
.code = htons ( TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA1_DIGEST_SIZE,
.exchange = &tls_ecdhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha1_algorithm,
.handshake = &sha256_algorithm,
};
/** TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA cipher suite */
struct tls_cipher_suite
tls_ecdhe_rsa_with_aes_256_cbc_sha __tls_cipher_suite ( 06 ) = {
.code = htons ( TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA1_DIGEST_SIZE,
.exchange = &tls_ecdhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha1_algorithm,
.handshake = &sha256_algorithm,
};

View File

@ -1,45 +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 (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 <byteswap.h>
#include <ipxe/rsa.h>
#include <ipxe/aes.h>
#include <ipxe/sha256.h>
#include <ipxe/tls.h>
/** TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 cipher suite */
struct tls_cipher_suite
tls_ecdhe_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite ( 03 ) = {
.code = htons ( TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA256_DIGEST_SIZE,
.exchange = &tls_ecdhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha256_algorithm,
.handshake = &sha256_algorithm,
};

View File

@ -1,45 +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 (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 <byteswap.h>
#include <ipxe/rsa.h>
#include <ipxe/aes.h>
#include <ipxe/sha512.h>
#include <ipxe/tls.h>
/** TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 cipher suite */
struct tls_cipher_suite
tls_ecdhe_rsa_with_aes_256_cbc_sha384 __tls_cipher_suite ( 04 ) = {
.code = htons ( TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA384_DIGEST_SIZE,
.exchange = &tls_ecdhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha384_algorithm,
.handshake = &sha384_algorithm,
};

View File

@ -1,45 +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 (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 <byteswap.h>
#include <ipxe/rsa.h>
#include <ipxe/aes.h>
#include <ipxe/sha256.h>
#include <ipxe/tls.h>
/** TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 cipher suite */
struct tls_cipher_suite
tls_ecdhe_rsa_with_aes_128_gcm_sha256 __tls_cipher_suite ( 01 ) = {
.code = htons ( TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 4,
.record_iv_len = 8,
.mac_len = 0,
.exchange = &tls_ecdhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_gcm_algorithm,
.digest = &sha256_algorithm,
.handshake = &sha256_algorithm,
};

View File

@ -1,45 +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 (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 <byteswap.h>
#include <ipxe/rsa.h>
#include <ipxe/aes.h>
#include <ipxe/sha512.h>
#include <ipxe/tls.h>
/** TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 cipher suite */
struct tls_cipher_suite
tls_ecdhe_rsa_with_aes_256_gcm_sha384 __tls_cipher_suite ( 02 ) = {
.code = htons ( TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 4,
.record_iv_len = 8,
.mac_len = 0,
.exchange = &tls_ecdhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_gcm_algorithm,
.digest = &sha384_algorithm,
.handshake = &sha384_algorithm,
};

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