Compare commits

..

No commits in common. "main" and "v6.01" have entirely different histories.
main ... v6.01

42 changed files with 372 additions and 1242 deletions

View file

@ -20,7 +20,7 @@ jobs:
fail-fast: false
matrix:
compiler: [gcc, clang]
os: [ubuntu-20.04, ubuntu-22.04]
os: [ubuntu-18.04, ubuntu-20.04, ubuntu-22.04]
steps:
- uses: actions/checkout@v3

View file

@ -6,7 +6,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v8
- uses: actions/stale@v6
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
exempt-issue-milestones: 'future,alpha,beta,release'

2
.gitignore vendored
View file

@ -8,7 +8,7 @@
*.o
# Generated file
build_version.h
githash.h
# Binaries
memtest_shared

View file

@ -129,8 +129,6 @@ recognised:
* disables ACPI table parsing and the use of multiple CPU cores
* nobench
* disables the integrated memory benchmark
* nobigstatus
* disables the big PASS/FAIL pop-up status display
* nosm
* disables SMBUS/SPD parsing, DMI decoding and memory benchmark
* nopause
@ -157,7 +155,7 @@ recognised:
* 9600
* 19200
* 38400
* 57600
* 54600
* 115200 (default if not specified or invalid)
* 230400
@ -483,9 +481,8 @@ selected by the user.
### Test 2 : Address test, own address + window
Across all memory regions, each address is written with its own virtual
address plus the window number (for 32-bit images) or own physical address
(for 64-bit images) and then each address is checked for consistency. This
Across all memory regions, each address is written with its own address plus
the window number and then each address is checked for consistency. This
catches any errors in the high order address bits that would be missed when
testing each window in turn. This test is performed sequentially with each
available CPU, regardless of the CPU sequencing mode selected by the user.

View file

@ -34,7 +34,6 @@
//------------------------------------------------------------------------------
#define MAX_PATTERNS 10
#define PATTERNS_SIZE (MAX_PATTERNS + 1)
// DEFAULT_MASK covers a uintptr_t, since that is the testing granularity.
#ifdef __x86_64__
@ -56,16 +55,14 @@ typedef struct {
// Private Variables
//------------------------------------------------------------------------------
static pattern_t patterns[PATTERNS_SIZE];
static pattern_t pattern[MAX_PATTERNS];
static int num_patterns = 0;
//------------------------------------------------------------------------------
// Private Functions
//------------------------------------------------------------------------------
// New mask is 1 where both masks were 1 (b & d) and the addresses were equal ~(a ^ c).
// If addresses were unequal the new mask must be 0 to allow for both values.
#define COMBINE_MASK(a,b,c,d) ((b & d) & ~(a ^ c))
#define COMBINE_MASK(a,b,c,d) ((a & b & c & d) | (~a & b & ~c & d))
/*
* Combine two addr/mask pairs to one addr/mask pair.
@ -75,7 +72,7 @@ static void combine(uintptr_t addr1, uintptr_t mask1, uintptr_t addr2, uintptr_t
*mask = COMBINE_MASK(addr1, mask1, addr2, mask2);
*addr = addr1 | addr2;
*addr &= *mask; // Normalise to ensure sorting on .addr will work as intended
*addr &= *mask; // Normalise, no fundamental need for this
}
/*
@ -107,110 +104,58 @@ static uintptr_t combi_cost(uintptr_t addr1, uintptr_t mask1, uintptr_t addr2, u
}
/*
* Determine if pattern is already covered by an existing pattern.
* Return true if that's the case, else false.
* Find the cheapest array index to extend with the given addr/mask pair.
* Return -1 if nothing below the given minimum cost can be found.
*/
static bool is_covered(pattern_t pattern)
static int cheap_index(uintptr_t addr1, uintptr_t mask1, uintptr_t min_cost)
{
for (int i = 0; i < num_patterns; i++) {
if (combi_cost(patterns[i].addr, patterns[i].mask, pattern.addr, pattern.mask) == 0) {
return true;
}
}
return false;
}
/*
* Find the pair of entries that would be the cheapest to merge.
* Assumes patterns is sorted by .addr asc and that for each index i, the cheapest entry to merge with is at i-1 or i+1.
* Return -1 if <= 1 patterns exist, else the index of the first entry of the pair (the other being that + 1).
*/
static int cheapest_pair()
{
// This is guaranteed to be overwritten with >= 0 as long as num_patterns > 1
int merge_idx = -1;
uintptr_t min_cost = UINTPTR_MAX;
for (int i = 0; i < num_patterns - 1; i++) {
uintptr_t tmp_cost = combi_cost(
patterns[i].addr,
patterns[i].mask,
patterns[i+1].addr,
patterns[i+1].mask
);
if (tmp_cost <= min_cost) {
int i = num_patterns;
int idx = -1;
while (i-- > 0) {
uintptr_t tmp_cost = combi_cost(pattern[i].addr, pattern[i].mask, addr1, mask1);
if (tmp_cost < min_cost) {
min_cost = tmp_cost;
merge_idx = i;
idx = i;
}
}
return merge_idx;
return idx;
}
/*
* Remove entries at idx and idx+1.
* Try to find a relocation index for idx if it costs nothing.
* Return -1 if no such index exists.
*/
static void remove_pair(int idx)
static int relocate_index(int idx)
{
for (int i = idx; i < num_patterns - 2; i++) {
patterns[i] = patterns[i + 2];
}
patterns[num_patterns - 1].addr = 0u;
patterns[num_patterns - 1].mask = 0u;
patterns[num_patterns - 2].addr = 0u;
patterns[num_patterns - 2].mask = 0u;
num_patterns -= 2;
uintptr_t addr = pattern[idx].addr;
uintptr_t mask = pattern[idx].mask;
pattern[idx].addr = ~pattern[idx].addr; // Never select idx
int new = cheap_index(addr, mask, 1 + addresses(mask));
pattern[idx].addr = addr;
return new;
}
/*
* Get the combined entry of idx1 and idx2.
* Relocate the given index idx only if free of charge.
* This is useful to combine to `neighbouring' sections to integrate.
* Inspired on the Buddy memalloc principle in the Linux kernel.
*/
static pattern_t combined_pattern(int idx1, int idx2)
static void relocate_if_free(int idx)
{
pattern_t combined;
combine(
patterns[idx1].addr,
patterns[idx1].mask,
patterns[idx2].addr,
patterns[idx2].mask,
&combined.addr,
&combined.mask
);
return combined;
}
/*
* Insert pattern at index idx, shuffling other entries on index towards the end.
*/
static void insert_at(pattern_t pattern, int idx)
{
// Move all entries >= idx one index towards the end to make space for the new entry
for (int i = num_patterns - 1; i >= idx; i--) {
patterns[i + 1] = patterns[i];
}
patterns[idx] = pattern;
num_patterns++;
}
/*
* Insert entry (addr, mask) in patterns in an index i so that patterns[i-1].addr < patterns[i]
* NOTE: Assumes patterns is already sorted by .addr asc!
*/
static void insert_sorted(pattern_t pattern)
{
// Normalise to ensure sorting on .addr will work as intended
pattern.addr &= pattern.mask;
// Find index to insert entry into
int new_idx = num_patterns;
for (int i = 0; i < num_patterns; i++) {
if (pattern.addr < patterns[i].addr) {
new_idx = i;
break;
int newidx = relocate_index(idx);
if (newidx >= 0) {
uintptr_t caddr, cmask;
combine(pattern[newidx].addr, pattern[newidx].mask,
pattern[ idx].addr, pattern[ idx].mask,
&caddr, &cmask);
pattern[newidx].addr = caddr;
pattern[newidx].mask = cmask;
if (idx < --num_patterns) {
pattern[idx].addr = pattern[num_patterns].addr;
pattern[idx].mask = pattern[num_patterns].mask;
}
relocate_if_free (newidx);
}
insert_at(pattern, new_idx);
}
//------------------------------------------------------------------------------
@ -220,40 +165,26 @@ static void insert_sorted(pattern_t pattern)
void badram_init(void)
{
num_patterns = 0;
for (int idx = 0; idx < PATTERNS_SIZE; idx++) {
patterns[idx].addr = 0u;
patterns[idx].mask = 0u;
}
}
bool badram_insert(uintptr_t addr)
{
pattern_t pattern = {
.addr = addr,
.mask = DEFAULT_MASK
};
// If covered by existing entry we return immediately
if (is_covered(pattern)) {
if (cheap_index(addr, DEFAULT_MASK, 1) != -1) {
return false;
}
// Add entry in order sorted by .addr asc
insert_sorted(pattern);
// If we have more patterns than the max we need to force a merge
if (num_patterns > MAX_PATTERNS) {
// Find the pair that is the cheapest to merge
// merge_idx will be -1 if num_patterns < 2, but that means MAX_PATTERNS = 0 which is not a valid state anyway
int merge_idx = cheapest_pair();
pattern_t combined = combined_pattern(merge_idx, merge_idx + 1);
// Remove the source pair so that we can maintain order as combined does not necessarily belong in merge_idx
remove_pair(merge_idx);
insert_sorted(combined);
if (num_patterns < MAX_PATTERNS) {
pattern[num_patterns].addr = addr;
pattern[num_patterns].mask = DEFAULT_MASK;
num_patterns++;
relocate_if_free(num_patterns - 1);
} else {
int idx = cheap_index(addr, DEFAULT_MASK, UINTPTR_MAX);
uintptr_t caddr, cmask;
combine(pattern[idx].addr, pattern[idx].mask, addr, DEFAULT_MASK, &caddr, &cmask);
pattern[idx].addr = caddr;
pattern[idx].mask = cmask;
relocate_if_free(idx);
}
return true;
}
@ -283,8 +214,8 @@ void badram_display(void)
col = 7;
}
display_scrolled_message(col, "0x%0*x,0x%0*x",
TESTWORD_DIGITS, patterns[i].addr,
TESTWORD_DIGITS, patterns[i].mask);
TESTWORD_DIGITS, pattern[i].addr,
TESTWORD_DIGITS, pattern[i].mask);
col += text_width;
}
}

View file

@ -91,7 +91,6 @@ bool exclude_ecores = true;
bool smp_enabled = true;
bool enable_big_status = true;
bool enable_temperature = true;
bool enable_trace = false;
@ -175,27 +174,7 @@ static void parse_option(const char *option, const char *params)
{
if (option[0] == '\0') return;
if (strncmp(option, "console", 8) == 0) {
parse_serial_params(params);
} else if (strncmp(option, "cpuseqmode", 11) == 0) {
if (strncmp(params, "par", 4) == 0) {
cpu_mode = PAR;
} else if (strncmp(params, "seq", 4) == 0) {
cpu_mode = SEQ;
} else if (strncmp(params, "rr", 3) == 0 || strncmp(params, "one", 4) == 0) {
cpu_mode = ONE;
}
} else if (strncmp(option, "reportmode", 11) == 0) {
if (strncmp(params, "none", 5) == 0) {
error_mode = ERROR_MODE_NONE;
} else if (strncmp(params, "summary", 8) == 0) {
error_mode = ERROR_MODE_SUMMARY;
} else if (strncmp(params, "address", 8) == 0) {
error_mode = ERROR_MODE_ADDRESS;
} else if (strncmp(params, "badram", 7) == 0) {
error_mode = ERROR_MODE_BADRAM;
}
} else if (strncmp(option, "keyboard", 9) == 0 && params != NULL) {
if (strncmp(option, "keyboard", 9) == 0 && params != NULL) {
if (strncmp(params, "legacy", 7) == 0) {
keyboard_types = KT_LEGACY;
} else if (strncmp(params, "usb", 4) == 0) {
@ -203,18 +182,6 @@ static void parse_option(const char *option, const char *params)
} else if (strncmp(params, "both", 5) == 0) {
keyboard_types = KT_USB|KT_LEGACY;
}
} else if (strncmp(option, "nobench", 8) == 0) {
enable_bench = false;
} else if (strncmp(option, "nobigstatus", 12) == 0) {
enable_big_status = false;
} else if (strncmp(option, "noehci", 7) == 0) {
usb_init_options |= USB_IGNORE_EHCI;
} else if (strncmp(option, "nopause", 8) == 0) {
pause_at_start = false;
} else if (strncmp(option, "nosm", 5) == 0) {
enable_sm = false;
} else if (strncmp(option, "nosmp", 6) == 0) {
smp_enabled = false;
} else if (strncmp(option, "powersave", 10) == 0) {
if (strncmp(params, "off", 4) == 0) {
power_save = POWER_SAVE_OFF;
@ -223,6 +190,16 @@ static void parse_option(const char *option, const char *params)
} else if (strncmp(params, "high", 5) == 0) {
power_save = POWER_SAVE_HIGH;
}
} else if (strncmp(option, "console", 8) == 0) {
parse_serial_params(params);
} else if (strncmp(option, "nobench", 8) == 0) {
enable_bench = false;
} else if (strncmp(option, "noehci", 7) == 0) {
usb_init_options |= USB_IGNORE_EHCI;
} else if (strncmp(option, "nopause", 8) == 0) {
pause_at_start = false;
} else if (strncmp(option, "nosmp", 6) == 0) {
smp_enabled = false;
} else if (strncmp(option, "trace", 6) == 0) {
enable_trace = true;
} else if (strncmp(option, "usbdebug", 9) == 0) {
@ -235,6 +212,8 @@ static void parse_option(const char *option, const char *params)
} else if (strncmp(params, "3", 2) == 0) {
usb_init_options |= USB_2_STEP_INIT|USB_EXTRA_RESET;
}
} else if (strncmp(option, "nosm", 5) == 0) {
enable_sm = false;
}
}

View file

@ -51,7 +51,6 @@ extern bool exclude_ecores;
extern bool smp_enabled;
extern bool enable_big_status;
extern bool enable_temperature;
extern bool enable_trace;

View file

@ -22,7 +22,7 @@
#include "config.h"
#include "error.h"
#include "build_version.h"
#include "githash.h"
#include "tests.h"
@ -49,7 +49,7 @@
static const char spin_state[NUM_SPIN_STATES] = { '|', '/', '-', '\\' };
static const char cpu_mode_str[3][4] = { "PAR", "SEQ", "RR " };
static const char *cpu_mode_str[] = { "PAR", "SEQ", "RR " };
//------------------------------------------------------------------------------
// Private Variables
@ -103,7 +103,7 @@ void display_init(void)
set_foreground_colour(BLACK);
set_background_colour(WHITE);
clear_screen_region(0, 0, 0, 27);
prints(0, 0, " Memtest86+ v" MT_VERSION);
prints(0, 0, " Memtest86+ v6.01");
set_foreground_colour(RED);
printc(0, 15, '+');
set_foreground_colour(WHITE);
@ -137,7 +137,8 @@ void display_init(void)
set_background_colour(WHITE);
clear_screen_region(ROW_FOOTER, 0, ROW_FOOTER, SCREEN_WIDTH - 1);
prints(ROW_FOOTER, 0, " <ESC> Exit <F1> Configuration <Space> Scroll Lock");
prints(ROW_FOOTER, 64, MT_VERSION "." GIT_HASH);
prints(ROW_FOOTER, 64, "6.01.");
prints(ROW_FOOTER, 69, GIT_HASH);
#if TESTWORD_WIDTH > 32
prints(ROW_FOOTER, 76, ".x64");
#else
@ -355,7 +356,7 @@ void display_temperature(void)
void display_big_status(bool pass)
{
if (!enable_big_status || big_status_displayed) {
if (big_status_displayed) {
return;
}
@ -409,7 +410,6 @@ void check_input(void)
return;
} else if (big_status_displayed) {
restore_big_status();
enable_big_status = false;
}
switch (input_key) {

View file

@ -251,16 +251,10 @@ static void global_init(void)
error_init();
temperature_init();
initial_config();
clear_message_area();
if (!smp_enabled) {
num_available_cpus = 1;
}
num_enabled_cpus = 0;
for (int i = 0; i < num_available_cpus; i++) {
if (cpu_state[i] == CPU_STATE_ENABLED) {
@ -671,8 +665,7 @@ void main(void)
if (error_count == 0) {
display_status("Pass ");
display_big_status(true);
} else {
display_big_status(false);
//display_notice("** Pass completed, no errors **");
}
}
}

View file

@ -1,2 +0,0 @@
#define MT_VERSION "6.20"
#define GIT_HASH "unknown"

View file

@ -58,7 +58,6 @@ typedef struct {
#define VIDEO_TYPE_VLFB 0x23 // VESA VGA in graphic mode
#define VIDEO_TYPE_EFI 0x70 // EFI graphic mode
#define VIDEO_TYPE_NONE 0xff // no video display (added for Memtest86+)
#define LFB_CAPABILITY_64BIT_BASE (1 << 1)

View file

@ -334,7 +334,9 @@ static efi_status_t set_screen_info_from_gop(screen_info_t *si, efi_handle_t *ha
efi_graphics_output_t *gop = find_gop(handles, handles_size);
if (!gop) {
print_string("No graphics display found\n");
#if DEBUG
print_string("GOP not found\n");
#endif
return EFI_NOT_FOUND;
}
@ -363,7 +365,9 @@ static efi_status_t set_screen_info_from_gop(screen_info_t *si, efi_handle_t *ha
efi_call_bs(free_pool, info);
}
if (best_mode == UINT32_MAX) {
print_string("No suitable screen resolution found\n");
#if DEBUG
print_string("No suitable GOP screen resolution\n");
#endif
return EFI_NOT_FOUND;
}
@ -465,7 +469,9 @@ static efi_status_t set_screen_info_from_gop(screen_info_t *si, efi_handle_t *ha
status = efi_call_proto(gop, set_mode, best_mode);
if (status != EFI_SUCCESS) {
#if DEBUG
print_string("Set GOP mode failed\n");
#endif
return status;
}
@ -496,16 +502,7 @@ static efi_status_t set_screen_info(boot_params_t *boot_params)
if (status == EFI_SUCCESS) {
status = set_screen_info_from_gop(&boot_params->screen_info, handles, handles_size);
}
if (status == EFI_NOT_FOUND) {
// This may be a headless system. We can still output to a serial console.
boot_params->screen_info.orig_video_isVGA = VIDEO_TYPE_NONE;
status = EFI_SUCCESS;
}
efi_call_bs(free_pool, handles);
} else if (status == EFI_NOT_FOUND) {
// This may be a headless system. We can still output to a serial console.
boot_params->screen_info.orig_video_isVGA = VIDEO_TYPE_NONE;
status = EFI_SUCCESS;
}
return status;

View file

@ -7,7 +7,7 @@
// end of the boot sector), with the remainder of the header being provided by
// setup.S.
//
// Copyright (C) 2020-2023 Martin Whitaker.
// Copyright (C) 2020 Martin Whitaker.
//
// Derived from Linux 5.6 arch/x86/boot/header.S:
//
@ -21,13 +21,13 @@
#define __ASSEMBLY__
#include "boot.h"
#include "peimage.h"
# The EFI loader loads the header at ImageBase, so we have to locate the main program
# after that. This means we can't load the main program at HIGH_LOAD_ADDR. Pick a load
# address well away from HIGH_LOAD_ADDR, to avoid overlap when relocating the code.
#define IMAGE_BASE 0x200000
#define BASE_OF_CODE 0x1000
.section ".header", "ax", @progbits
.code16
@ -85,46 +85,50 @@ pe_header:
coff_header:
#ifdef __x86_64__
.word IMAGE_FILE_MACHINE_X64 # Machine (x86-64)
.word 0x8664 # Machine (x86-64)
#else
.word IMAGE_FILE_MACHINE_I386 # Machine (i386)
.word 0x14c # Machine (i386)
#endif
.word 3 # NumberOfSections
.word 1 # NumberOfSections
.long 0 # TimeDateStamp
.long 0 # PointerToSymbolTable
.long 0 # NumberOfSymbols
.word section_table - optional_header # SizeOfOptionalHeader
#ifdef __x86_64__
.word IMAGE_FILE_DEBUG_STRIPPED \
| IMAGE_FILE_LOCAL_SYMS_STRIPPED \
| IMAGE_FILE_LINE_NUMS_STRIPPED \
| IMAGE_FILE_EXECUTABLE_IMAGE # Characteristics
.word 0x20f # Characteristics
# IMAGE_FILE_DEBUG_STRIPPED |
# IMAGE_FILE_LOCAL_SYMS_STRIPPED |
# IMAGE_FILE_LINE_NUMS_STRIPPED |
# IMAGE_FILE_EXECUTABLE_IMAGE |
# IMAGE_FILE_RELOCS_STRIPPED
#else
.word IMAGE_FILE_32BIT_MACHINE \
| IMAGE_FILE_DEBUG_STRIPPED \
| IMAGE_FILE_LOCAL_SYMS_STRIPPED \
| IMAGE_FILE_LINE_NUMS_STRIPPED \
| IMAGE_FILE_EXECUTABLE_IMAGE # Characteristics.
.word 0x30f # Characteristics.
# IMAGE_FILE_32BIT_MACHINE |
# IMAGE_FILE_DEBUG_STRIPPED |
# IMAGE_FILE_LOCAL_SYMS_STRIPPED |
# IMAGE_FILE_LINE_NUMS_STRIPPED |
# IMAGE_FILE_EXECUTABLE_IMAGE |
# IMAGE_FILE_RELOCS_STRIPPED
#endif
optional_header:
#ifdef __x86_64__
.word IMAGE_NT_OPTIONAL_HDR64_MAGIC # PE32+ format
.word 0x20b # PE32+ format
#else
.word IMAGE_NT_OPTIONAL_HDR32_MAGIC # PE32 format
.word 0x10b # PE32 format
#endif
.byte 0x02 # MajorLinkerVersion
.byte 0x14 # MinorLinkerVersion
.long _virt_text_size # SizeOfCode
.long _virt_sbat_size # SizeOfInitializedData
.long _text_size # SizeOfCode
.long 0 # SizeOfInitializedData
.long 0 # SizeOfUninitializedData
.long _virt_text_start + 0x1e0 # AddressOfEntryPoint
.long BASE_OF_CODE + 0x1e0 # AddressOfEntryPoint
.long _virt_text_start # BaseOfCode
.long BASE_OF_CODE # BaseOfCode
#ifndef __x86_64__
.long _virt_sbat_start # BaseOfData
.long 0 # data
#endif
extra_header_fields:
@ -143,8 +147,8 @@ extra_header_fields:
.word 0 # MinorSubsystemVersion
.long 0 # Win32VersionValue
.long _virt_img_size # SizeOfImage
.long _file_head_size # SizeOfHeaders
.long BASE_OF_CODE + _init_size # SizeOfImage
.long 512 # SizeOfHeaders
.long 0 # CheckSum
.word 10 # Subsystem (EFI application)
.word 0 # DllCharacteristics
@ -160,20 +164,7 @@ extra_header_fields:
.long 0 # SizeOfHeapCommit
#endif
.long 0 # LoaderFlags
.long IMAGE_DIRECTORY_ENTRY_DEBUG # NumberOfRvaAndSizes
.long 0 # DataDirectory.Export.VirtualAddress
.long 0 # DataDirectory.Export.Size
.long 0 # DataDirectory.Import.VirtualAddress
.long 0 # DataDirectory.Import.Size
.long 0 # DataDirectory.Resource.VirtualAddress
.long 0 # DataDirectory.Resource.Size
.long 0 # DataDirectory.Exception.VirtualAddress
.long 0 # DataDirectory.Exception.Size
.long 0 # DataDirectory.Certs.VirtualAddress
.long 0 # DataDirectory.Certs.Size
.long _virt_reloc_start # DataDirectory.BaseReloc.VirtualAddress
.long _real_reloc_size # DataDirectory.BaseReloc.Size
.long 0 # NumberOfRvaAndSizes
# Section table
section_table:
@ -181,46 +172,15 @@ section_table:
.byte 0
.byte 0
.byte 0
.long _virt_text_size # VirtualSize
.long _virt_text_start # VirtualAddress
.long _file_text_size # SizeOfRawData
.long _file_text_start # PointerToRawData
.long _text_size # VirtualSize
.long BASE_OF_CODE # VirtualAddress
.long _text_size # SizeOfRawData
.long _text_start # PointerToRawData
.long 0 # PointerToRelocations
.long 0 # PointerToLineNumbers
.word 0 # NumberOfRelocations
.word 0 # NumberOfLineNumbers
.long IMAGE_SCN_MEM_READ \
| IMAGE_SCN_MEM_EXECUTE \
| IMAGE_SCN_CNT_CODE # Characteristics (section flags)
.ascii ".reloc"
.byte 0
.byte 0
.long _virt_reloc_size # VirtualSize
.long _virt_reloc_start # VirtualAddress
.long _file_reloc_size # SizeOfRawData
.long _file_reloc_start # PointerToRawData
.long 0 # PointerToRelocations
.long 0 # PointerToLineNumbers
.word 0 # NumberOfRelocations
.word 0 # NumberOfLineNumbers
.long IMAGE_SCN_MEM_READ \
| IMAGE_SCN_CNT_INITIALIZED_DATA # Characteristics (section flags)
.ascii ".sbat"
.byte 0
.byte 0
.byte 0
.long _virt_sbat_size # VirtualSize
.long _virt_sbat_start # VirtualAddress
.long _file_sbat_size # SizeOfRawData
.long _file_sbat_start # PointerToRawData
.long 0 # PointerToRelocations
.long 0 # PointerToLineNumbers
.word 0 # NumberOfRelocations
.word 0 # NumberOfLineNumbers
.long IMAGE_SCN_MEM_READ \
| IMAGE_SCN_CNT_INITIALIZED_DATA # Characteristics (section flags)
.long 0x60500020 # Characteristics (section flags)
# Emulate the Linux boot header, to allow loading by intermediate boot loaders.
@ -239,13 +199,3 @@ root_dev:
.word 0
boot_flag:
.word 0xAA55
.org 512
.section ".reloc"
.long 0 // Page RVA
.long 10 // Block Size (2*4+2)
.word (IMAGE_REL_BASED_ABSOLUTE << 12) + 0 // reloc 0 -> 0
.section ".sbat", "a", @progbits
.incbin "../boot/sbat.csv"

View file

@ -1,292 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
// This is include/coff/pe.h from binutils-2.10.0.18
// Copyright The Free Software Foundation
/* PE COFF header information */
#ifndef _PE_H
#define _PE_H
/* NT specific file attributes. */
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
#define IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010
#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020
#define IMAGE_FILE_16BIT_MACHINE 0x0040
#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
#define IMAGE_FILE_32BIT_MACHINE 0x0100
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400
#define IMAGE_FILE_SYSTEM 0x1000
#define IMAGE_FILE_DLL 0x2000
#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
/* Additional flags to be set for section headers to allow the NT loader to
read and write to the section data (to replace the addresses of data in
dlls for one thing); also to execute the section in .text's case. */
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
#define IMAGE_SCN_MEM_READ 0x40000000
#define IMAGE_SCN_MEM_WRITE 0x80000000
/* Section characteristics added for ppc-nt. */
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Reserved. */
#define IMAGE_SCN_CNT_CODE 0x00000020 /* Section contains code. */
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* Section contains initialized data. */
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* Section contains uninitialized data. */
#define IMAGE_SCN_LNK_OTHER 0x00000100 /* Reserved. */
#define IMAGE_SCN_LNK_INFO 0x00000200 /* Section contains comments or some other type of information. */
#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* Section contents will not become part of image. */
#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* Section contents comdat. */
#define IMAGE_SCN_MEM_FARDATA 0x00008000
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
#define IMAGE_SCN_MEM_16BIT 0x00020000
#define IMAGE_SCN_MEM_LOCKED 0x00040000
#define IMAGE_SCN_MEM_PRELOAD 0x00080000
#define IMAGE_SCN_ALIGN_1BYTES 0x00100000
#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 /* Default alignment if no others are specified. */
#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
#define IMAGE_SCN_ALIGN_128BYTES 0x00800000
#define IMAGE_SCN_ALIGN_256BYTES 0x00900000
#define IMAGE_SCN_ALIGN_512BYTES 0x00a00000
#define IMAGE_SCN_ALIGN_1024BYTES 0x00b00000
#define IMAGE_SCN_ALIGN_2048BYTES 0x00c00000
#define IMAGE_SCN_ALIGN_4096BYTES 0x00d00000
#define IMAGE_SCN_ALIGN_8129BYTES 0x00e00000
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000
#define IMAGE_SCN_MEM_SHARED 0x10000000
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
#define IMAGE_SCN_MEM_READ 0x40000000
#define IMAGE_SCN_MEM_WRITE 0x80000000
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* Section contains extended relocations. */
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* Section is not cachable. */
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* Section is not pageable. */
#define IMAGE_SCN_MEM_SHARED 0x10000000 /* Section is shareable. */
#define IMAGE_REL_BASED_ABSOLUTE 0x0000
/* COMDAT selection codes. */
#define IMAGE_COMDAT_SELECT_NODUPLICATES (1) /* Warn if duplicates. */
#define IMAGE_COMDAT_SELECT_ANY (2) /* No warning. */
#define IMAGE_COMDAT_SELECT_SAME_SIZE (3) /* Warn if different size. */
#define IMAGE_COMDAT_SELECT_EXACT_MATCH (4) /* Warn if different. */
#define IMAGE_COMDAT_SELECT_ASSOCIATIVE (5) /* Base on other section. */
/* Machine numbers. */
#define IMAGE_FILE_MACHINE_UNKNOWN 0x0
#define IMAGE_FILE_MACHINE_ALPHA 0x184
#define IMAGE_FILE_MACHINE_ARM 0x1c0
#define IMAGE_FILE_MACHINE_ALPHA64 0x284
#define IMAGE_FILE_MACHINE_I386 0x14c
#define IMAGE_FILE_MACHINE_IA64 0x200
#define IMAGE_FILE_MACHINE_M68K 0x268
#define IMAGE_FILE_MACHINE_MIPS16 0x266
#define IMAGE_FILE_MACHINE_MIPSFPU 0x366
#define IMAGE_FILE_MACHINE_MIPSFPU16 0x466
#define IMAGE_FILE_MACHINE_POWERPC 0x1f0
#define IMAGE_FILE_MACHINE_R3000 0x162
#define IMAGE_FILE_MACHINE_R4000 0x166
#define IMAGE_FILE_MACHINE_R10000 0x168
#define IMAGE_FILE_MACHINE_SH3 0x1a2
#define IMAGE_FILE_MACHINE_SH4 0x1a6
#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x1c2
#define IMAGE_FILE_MACHINE_X64 0x8664
#define IMAGE_FILE_MACHINE_ARM64 0xaa64
#define IMAGE_SUBSYSTEM_UNKNOWN 0
#define IMAGE_SUBSYSTEM_NATIVE 1
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
#define IMAGE_SUBSYSTEM_POSIX_CUI 7
#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9
#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10
#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
/* Magic values that are true for all dos/nt implementations */
#define DOSMAGIC 0x5a4d
#define NT_SIGNATURE 0x00004550
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x010b
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x020b
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
#define IMAGE_DIRECTORY_ENTRY_TLS 9
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
#define IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16
/* NT allows long filenames, we want to accommodate this. This may break
some of the bfd functions */
#undef FILNMLEN
#define FILNMLEN 18 /* # characters in a file name */
#ifndef __ASSEMBLY__
struct external_PEI_filehdr
{
/* DOS header fields - always at offset zero in the EXE file */
char e_magic[2]; /* Magic number, 0x5a4d */
char e_cblp[2]; /* Bytes on last page of file, 0x90 */
char e_cp[2]; /* Pages in file, 0x3 */
char e_crlc[2]; /* Relocations, 0x0 */
char e_cparhdr[2]; /* Size of header in paragraphs, 0x4 */
char e_minalloc[2]; /* Minimum extra paragraphs needed, 0x0 */
char e_maxalloc[2]; /* Maximum extra paragraphs needed, 0xFFFF */
char e_ss[2]; /* Initial (relative) SS value, 0x0 */
char e_sp[2]; /* Initial SP value, 0xb8 */
char e_csum[2]; /* Checksum, 0x0 */
char e_ip[2]; /* Initial IP value, 0x0 */
char e_cs[2]; /* Initial (relative) CS value, 0x0 */
char e_lfarlc[2]; /* File address of relocation table, 0x40 */
char e_ovno[2]; /* Overlay number, 0x0 */
char e_res[4][2]; /* Reserved words, all 0x0 */
char e_oemid[2]; /* OEM identifier (for e_oeminfo), 0x0 */
char e_oeminfo[2]; /* OEM information; e_oemid specific, 0x0 */
char e_res2[10][2]; /* Reserved words, all 0x0 */
char e_lfanew[4]; /* File address of new exe header, usually 0x80 */
char dos_message[16][4]; /* other stuff, always follow DOS header */
/* Note: additional bytes may be inserted before the signature. Use
the e_lfanew field to find the actual location of the NT signature */
char nt_signature[4]; /* required NT signature, 0x4550 */
/* From standard header */
char f_magic[2]; /* magic number */
char f_nscns[2]; /* number of sections */
char f_timdat[4]; /* time & date stamp */
char f_symptr[4]; /* file pointer to symtab */
char f_nsyms[4]; /* number of symtab entries */
char f_opthdr[2]; /* sizeof(optional hdr) */
char f_flags[2]; /* flags */
};
#endif
#ifdef COFF_IMAGE_WITH_PE
/* The filehdr is only weird in images. */
#undef FILHDR
#define FILHDR struct external_PEI_filehdr
#undef FILHSZ
#define FILHSZ 152
#endif /* COFF_IMAGE_WITH_PE */
/* 32-bit PE a.out header: */
#ifndef __ASSEMBLY__
typedef struct
{
AOUTHDR standard;
/* NT extra fields; see internal.h for descriptions */
char ImageBase[4];
char SectionAlignment[4];
char FileAlignment[4];
char MajorOperatingSystemVersion[2];
char MinorOperatingSystemVersion[2];
char MajorImageVersion[2];
char MinorImageVersion[2];
char MajorSubsystemVersion[2];
char MinorSubsystemVersion[2];
char Reserved1[4];
char SizeOfImage[4];
char SizeOfHeaders[4];
char CheckSum[4];
char Subsystem[2];
char DllCharacteristics[2];
char SizeOfStackReserve[4];
char SizeOfStackCommit[4];
char SizeOfHeapReserve[4];
char SizeOfHeapCommit[4];
char LoaderFlags[4];
char NumberOfRvaAndSizes[4];
/* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */
char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars */
} PEAOUTHDR;
#endif
#undef AOUTSZ
#define AOUTSZ (AOUTHDRSZ + 196)
/* Like PEAOUTHDR, except that the "standard" member has no BaseOfData
(aka data_start) member and that some of the members are 8 instead
of just 4 bytes long. */
#ifndef __ASSEMBLY__
typedef struct
{
AOUTHDR standard;
/* NT extra fields; see internal.h for descriptions */
char ImageBase[8];
char SectionAlignment[4];
char FileAlignment[4];
char MajorOperatingSystemVersion[2];
char MinorOperatingSystemVersion[2];
char MajorImageVersion[2];
char MinorImageVersion[2];
char MajorSubsystemVersion[2];
char MinorSubsystemVersion[2];
char Reserved1[4];
char SizeOfImage[4];
char SizeOfHeaders[4];
char CheckSum[4];
char Subsystem[2];
char DllCharacteristics[2];
char SizeOfStackReserve[8];
char SizeOfStackCommit[8];
char SizeOfHeapReserve[8];
char SizeOfHeapCommit[8];
char LoaderFlags[4];
char NumberOfRvaAndSizes[4];
/* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */
char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars */
} PEP64AOUTHDR;
#endif
#define PEP64AOUTSZ 240
#undef E_FILNMLEN
#define E_FILNMLEN 18 /* # characters in a file name */
/* Import Tyoes fot ILF format object files.. */
#define IMPORT_CODE 0
#define IMPORT_DATA 1
#define IMPORT_CONST 2
/* Import Name Tyoes for ILF format object files. */
#define IMPORT_ORDINAL 0
#define IMPORT_NAME 1
#define IMPORT_NAME_NOPREFIX 2
#define IMPORT_NAME_UNDECORATE 3
#endif /* _PE_H */

View file

@ -1,2 +0,0 @@
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
memtest86+,1,Memtest86+,6.0,https://github.com/memtest86plus
1 sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
2 memtest86+,1,Memtest86+,6.0,https://github.com/memtest86plus

View file

@ -18,7 +18,6 @@
#define __ASSEMBLY__
#include "boot.h"
#include "build_version.h"
#define BOOT_PARAMS_START (SETUP_SECS * 512)
#define BOOT_PARAMS_END (BOOT_PARAMS_START + 4096)
@ -42,7 +41,7 @@ realmode_swtch:
start_sys_seg:
.word 0x1000
kernel_version:
.word mt86plus_version-512
.word 0
type_of_loader:
.byte 0
loadflags:
@ -386,10 +385,6 @@ idt_descr:
.word 0 # idt limit=0
.long 0 # idt base=0
mt86plus_version:
.ascii "Memtest86+ v" , MT_VERSION
.byte 0
# Pad to the declared size.
.org (SETUP_SECS*512)

View file

@ -812,7 +812,7 @@ startup_stack_top:
# Main stack area.
.section ".stacks", "aw", @nobits
.section "stacks", "aw", @progbits
.align 16
. = . + STACKS_SIZE

View file

@ -75,15 +75,16 @@ all: memtest.bin memtest.efi
-include $(subst .o,.d,$(TST_OBJS))
-include $(subst .o,.d,$(APP_OBJS))
boot/header.o : | ../boot/sbat.csv
boot/%.o: boot/%.s
$(AS) $< -o $@
boot/startup.o: ../boot/startup32.S ../boot/boot.h
boot/startup.s: ../boot/startup32.S ../boot/boot.h
@mkdir -p boot
$(CC) -m32 -x assembler-with-cpp -c -I../boot -o $@ $<
$(CC) -m32 -E -traditional -I../boot -o $@ $<
boot/%.o: ../boot/%.S ../boot/boot.h app/build_version.h
boot/%.s: ../boot/%.S ../boot/boot.h
@mkdir -p boot
$(CC) -m32 -x assembler-with-cpp -c -I../boot -Iapp -o $@ $<
$(CC) -m32 -E -traditional -I../boot -o $@ $<
boot/efisetup.o: ../boot/efisetup.c
@mkdir -p boot
@ -105,22 +106,20 @@ tests/%.o: ../tests/%.c
@mkdir -p tests
$(CC) -c $(CFLAGS) -O3 $(INC_DIRS) -o $@ $< -MMD -MP -MT $@ -MF $(@:.o=.d)
app/%.o: ../app/%.c app/build_version.h
app/%.o: ../app/%.c app/githash.h
@mkdir -p app
$(CC) -c $(CFLAGS) -Os $(INC_DIRS) -o $@ $< -MMD -MP -MT $@ -MF $(@:.o=.d)
app/build_version.h: FORCE
app/githash.h: FORCE
@mkdir -p app
@( \
cp -f ../app/version.h $@.tmp; \
if $(GIT_AVAILABLE) && test -d ../.git ; then \
hash=`git rev-parse HEAD | cut -c1-7`; \
sed -i 's/GIT_HASH\s\".*"/GIT_HASH "'$$hash'"/' $@.tmp; \
else \
sed -i 's/GIT_HASH\s\".*"/GIT_HASH "unknown"/' $@.tmp; \
hash="unknown"; \
fi; \
cmp $@ $@.tmp 2>/dev/null || cp -f $@.tmp $@; \
rm -f $@.tmp; \
define=`echo "#define GIT_HASH \"$$hash\""`; \
echo $$define | diff - $@ > /dev/null 2>&1 || echo $$define > $@; \
)
FORCE:

View file

@ -12,48 +12,15 @@ SECTIONS {
}
. = ALIGN(512);
.text : {
_file_text_start = . ;
_text_start = . ;
*(.data)
_real_text_end = . ;
. = ALIGN(512);
_file_text_end = . ;
}
.reloc : {
_file_reloc_start = . ;
*(.reloc)
_real_reloc_end = . ;
. = ALIGN(512);
_file_reloc_end = . ;
}
.sbat : {
_file_sbat_start = . ;
*(.sbat)
_real_sbat_end = . ;
. = ALIGN(512);
_file_sbat_end = . ;
_text_end = . ;
}
/DISCARD/ : { *(*) }
_real_text_size = _real_text_end - _file_text_start;
_real_reloc_size = _real_reloc_end - _file_reloc_start;
_real_sbat_size = _real_sbat_end - _file_sbat_start;
_text_size = (_text_end - _text_start);
_file_head_size = _file_text_start;
_file_text_size = _file_text_end - _file_text_start;
_file_reloc_size = _file_reloc_end - _file_reloc_start;
_file_sbat_size = _file_sbat_end - _file_sbat_start;
_sys_size = (_real_text_size + 15) >> 4;
_init_size = _real_text_size + _bss_size;
_virt_head_size = ((_file_head_size + 4095) >> 12) << 12;
_virt_text_size = ((_init_size + 4095) >> 12) << 12;
_virt_reloc_size = ((_file_reloc_size + 4095) >> 12) << 12;
_virt_sbat_size = ((_file_sbat_size + 4095) >> 12) << 12;
_virt_text_start = _virt_head_size;
_virt_reloc_start = _virt_text_start + _virt_text_size;
_virt_sbat_start = _virt_reloc_start + _virt_reloc_size;
_virt_img_size = _virt_sbat_start + _virt_sbat_size;
_sys_size = _text_size >> 4;
_init_size = _text_size + _bss_size;
}

View file

@ -74,15 +74,16 @@ all: memtest.bin memtest.efi
-include $(subst .o,.d,$(TST_OBJS))
-include $(subst .o,.d,$(APP_OBJS))
boot/header.o : | ../boot/sbat.csv
boot/%.o: boot/%.s
$(AS) $< -o $@
boot/startup.o: ../boot/startup64.S ../boot/boot.h
boot/startup.s: ../boot/startup64.S ../boot/boot.h
@mkdir -p boot
$(CC) -m64 -x assembler-with-cpp -c -I../boot -o $@ $<
$(CC) -E -traditional -I../boot -o $@ $<
boot/%.o: ../boot/%.S ../boot/boot.h app/build_version.h
boot/%.s: ../boot/%.S ../boot/boot.h
@mkdir -p boot
$(CC) -m64 -x assembler-with-cpp -c -I../boot -Iapp -o $@ $<
$(CC) -E -traditional -I../boot -o $@ $<
boot/efisetup.o: ../boot/efisetup.c
@mkdir -p boot
@ -104,22 +105,20 @@ tests/%.o: ../tests/%.c
@mkdir -p tests
$(CC) -c $(CFLAGS) -O3 $(INC_DIRS) -o $@ $< -MMD -MP -MT $@ -MF $(@:.o=.d)
app/%.o: ../app/%.c app/build_version.h
app/%.o: ../app/%.c app/githash.h
@mkdir -p app
$(CC) -c $(CFLAGS) -Os $(INC_DIRS) -o $@ $< -MMD -MP -MT $@ -MF $(@:.o=.d)
app/build_version.h: FORCE
app/githash.h: FORCE
@mkdir -p app
@( \
cp -f ../app/version.h $@.tmp; \
if $(GIT_AVAILABLE) && test -d ../.git ; then \
hash=`git rev-parse HEAD | cut -c1-7`; \
sed -i 's/GIT_HASH\s\".*"/GIT_HASH "'$$hash'"/' $@.tmp; \
else \
sed -i 's/GIT_HASH\s\".*"/GIT_HASH "unknown"/' $@.tmp; \
hash="unknown"; \
fi; \
cmp $@ $@.tmp 2>/dev/null || cp -f $@.tmp $@; \
rm -f $@.tmp; \
define=`echo "#define GIT_HASH \"$$hash\""`; \
echo $$define | diff - $@ > /dev/null 2>&1 || echo $$define > $@; \
)
FORCE:

View file

@ -12,48 +12,15 @@ SECTIONS {
}
. = ALIGN(512);
.text : {
_file_text_start = . ;
_text_start = . ;
*(.data)
_real_text_end = . ;
. = ALIGN(512);
_file_text_end = . ;
}
.reloc : {
_file_reloc_start = . ;
*(.reloc)
_real_reloc_end = . ;
. = ALIGN(512);
_file_reloc_end = . ;
}
.sbat : {
_file_sbat_start = . ;
*(.sbat)
_real_sbat_end = . ;
. = ALIGN(512);
_file_sbat_end = . ;
_text_end = . ;
}
/DISCARD/ : { *(*) }
_real_text_size = _real_text_end - _file_text_start;
_real_reloc_size = _real_reloc_end - _file_reloc_start;
_real_sbat_size = _real_sbat_end - _file_sbat_start;
_text_size = (_text_end - _text_start);
_file_head_size = _file_text_start;
_file_text_size = _file_text_end - _file_text_start;
_file_reloc_size = _file_reloc_end - _file_reloc_start;
_file_sbat_size = _file_sbat_end - _file_sbat_start;
_sys_size = (_real_text_size + 15) >> 4;
_init_size = _real_text_size + _bss_size;
_virt_head_size = ((_file_head_size + 4095) >> 12) << 12;
_virt_text_size = ((_init_size + 4095) >> 12) << 12;
_virt_reloc_size = ((_file_reloc_size + 4095) >> 12) << 12;
_virt_sbat_size = ((_file_sbat_size + 4095) >> 12) << 12;
_virt_text_start = _virt_head_size;
_virt_reloc_start = _virt_text_start + _virt_text_size;
_virt_sbat_start = _virt_reloc_start + _virt_reloc_size;
_virt_img_size = _virt_sbat_start + _virt_sbat_size;
_sys_size = _text_size >> 4;
_init_size = _text_size + _bss_size;
}

View file

@ -31,6 +31,18 @@ void reverse(char s[])
// Public Functions
//------------------------------------------------------------------------------
int memcmp(const void *s1, const void *s2, size_t n)
{
const unsigned char *src1 = s1, *src2 = s2;
for (size_t i = 0; i < n; i++) {
if (src1[i] != src2[i]) {
return (int)src1[i] - (int)src2[i];
}
}
return 0;
}
void *memmove(void *dest, const void *src, size_t n)
{
char *d = (char *)dest, *s = (char *)src;
@ -52,6 +64,28 @@ void *memmove(void *dest, const void *src, size_t n)
return dest;
}
size_t strlen(const char *s)
{
size_t len = 0;
while (*s++) {
len++;
}
return len;
}
int strncmp(const char *s1, const char *s2, size_t n)
{
for (size_t i = 0; i < n; i++) {
if (s1[i] != s2[i]) {
return (int)s1[i] - (int)s2[i];
}
if (s1[i] == '\0') {
return 0;
}
}
return 0;
}
char *strstr(const char *haystack, const char *needle)
{
size_t haystack_len = strlen(haystack);

View file

@ -18,17 +18,7 @@
* between the first mismatching byte in s1 (interpreted as an unsigned
* value) and the corresponding byte in s2.
*/
static inline int memcmp(const void *s1, const void *s2, size_t n)
{
const unsigned char *src1 = s1, *src2 = s2;
for (size_t i = 0; i < n; i++) {
if (src1[i] != src2[i]) {
return (int)src1[i] - (int)src2[i];
}
}
return 0;
}
int memcmp(const void *s1, const void *s2, size_t n);
/**
* Copies n bytes from the memory area pointed to by src to the memory area
@ -55,14 +45,7 @@ void *memmove(void *dest, const void *src, size_t n);
/**
* Returns the string length, excluding the terminating null character.
*/
static inline size_t strlen(const char *s)
{
size_t len = 0;
while (*s++) {
len++;
}
return len;
}
size_t strlen(const char *s);
/**
* Compares at most the first n characters in the strings s1 and s2 and
@ -70,18 +53,7 @@ static inline size_t strlen(const char *s)
* between the first mismatching character in s1 (interpreted as a signed
* value) and the corresponding character in s2.
*/
static inline int strncmp(const char *s1, const char *s2, size_t n)
{
for (size_t i = 0; i < n; i++) {
if (s1[i] != s2[i]) {
return (int)s1[i] - (int)s2[i];
}
if (s1[i] == '\0') {
return 0;
}
}
return 0;
}
int strncmp(const char *s1, const char *s2, size_t n);
/**
* Finds the first occurrence of the substring needle in the string haystack

View file

@ -4,7 +4,7 @@
//
// Derived from memtest86+ cpuid.h
#include <stdbool.h>
#include <stdint.h>
#include "cpuid.h"
@ -36,7 +36,7 @@ void cpuid_init(void)
// Get the processor family information & feature flags.
if (cpuid_info.max_cpuid >= 1) {
cpuid(0x1, 0,
&cpuid_info.version.raw[0],
&cpuid_info.version.raw,
&cpuid_info.proc_info.raw,
&cpuid_info.flags.raw[1],
&cpuid_info.flags.raw[0]
@ -65,8 +65,8 @@ void cpuid_init(void)
if (cpuid_info.max_xcpuid >= 0x80000001) {
cpuid(0x80000001, 0,
&reg[0],
&cpuid_info.version.raw[1],
&reg[1],
&reg[2],
&cpuid_info.flags.raw[2]
);
}
@ -108,21 +108,30 @@ void cpuid_init(void)
}
// Get cache information.
if (cpuid_info.max_xcpuid >= 0x80000005) {
cpuid(0x80000005, 0,
&reg[0],
&reg[1],
&cpuid_info.cache_info.raw[0],
&cpuid_info.cache_info.raw[1]
);
}
if (cpuid_info.max_xcpuid >= 0x80000006) {
cpuid(0x80000006, 0,
&reg[0],
&reg[1],
&cpuid_info.cache_info.raw[2],
&cpuid_info.cache_info.raw[3]
);
switch (cpuid_info.vendor_id.str[0]) {
case 'A':
// AMD Processors
if (cpuid_info.max_xcpuid >= 0x80000005) {
cpuid(0x80000005, 0,
&reg[0],
&reg[1],
&cpuid_info.cache_info.raw[0],
&cpuid_info.cache_info.raw[1]
);
}
if (cpuid_info.max_xcpuid >= 0x80000006) {
cpuid(0x80000006, 0,
&reg[0],
&reg[1],
&cpuid_info.cache_info.raw[2],
&cpuid_info.cache_info.raw[3]
);
}
break;
case 'G':
// Intel Processors
// No cpuid info to read.
break;
}
// Detect CPU Topology (Core/Thread) infos
@ -167,8 +176,7 @@ void cpuid_init(void)
}
break;
case 'C':
// Cyrix / VIA / CentaurHauls / Zhaoxin
cpuid_info.flags.htt = false;
// VIA / CentaurHauls
break;
case 'G':
if (cpuid_info.vendor_id.str[7] == 'T') break; // Transmeta

View file

@ -29,7 +29,7 @@ typedef enum {
*/
typedef union {
uint32_t raw[2];
uint32_t raw;
struct {
uint32_t stepping : 4;
uint32_t model : 4;
@ -39,7 +39,6 @@ typedef union {
uint32_t extendedModel : 4;
uint32_t extendedFamily : 8;
uint32_t : 4;
uint32_t extendedBrandID : 32; // AMD Only
};
} cpuid_version_t;
@ -123,7 +122,7 @@ typedef union {
} cpuid_brand_string_t;
typedef union {
uint32_t raw[4];
uint32_t raw[12];
struct {
uint32_t : 24;
uint32_t l1_i_size : 8;

View file

@ -71,45 +71,12 @@ static void determine_cache_size()
l3_cache *= 512;
break;
case 'C':
if (cpuid_info.vendor_id.str[5] == 'I') {
// Cyrix
if (cpuid_info.version.family == 5 && cpuid_info.version.model == 4) {
// Media GXm, Geode GXm/GXLV/GX1
// Cache info in CPUID has a Cyrix-specific encoding so hardcode it
l1_cache = 16;
}
break;
}
// WinChip 2/3, VIA C3/C7/Nano
if (cpuid_info.version.family == 5 || cpuid_info.version.family == 6) {
l1_cache = cpuid_info.cache_info.l1_d_size;
l2_cache = cpuid_info.cache_info.l2_size;
break;
} else if (cpuid_info.version.family != 7) {
break;
}
// Zhaoxin CPU only
if (cpuid_info.version.family != 7) {
break;
}
/* fall through */
case 'G':
if (cpuid_info.vendor_id.str[9] == 'N') {
// National Semiconductor
if (cpuid_info.version.family == 5) {
switch (cpuid_info.version.model) {
case 4:
// Geode GXm/GXLV/GX1
// Cache info in CPUID has a Cyrix-specific encoding so hardcode it
l1_cache = 16;
break;
case 5:
// Geode GX2
l1_cache = cpuid_info.cache_info.l1_d_size;
break;
default:
break;
}
}
break;
}
// Intel Processors
l1_cache = 0;
l2_cache = 0;
@ -493,9 +460,6 @@ static void determine_imc(void)
case 0x9:
imc_type = IMC_KBL; // Core 7/8/9th Gen (Kaby/Coffee/Comet Lake)
break;
case 0xB:
imc_type = IMC_ADL_N; // Core 12th Gen (Alder Lake-N - Gracemont E-Cores only)
break;
default:
break;
}
@ -635,9 +599,9 @@ static void determine_cpu_model(void)
// Transmeta Processors - vendor_id starts with "GenuineTMx86"
if (cpuid_info.vendor_id.str[7] == 'T' ) {
if (cpuid_info.version.family == 5) {
cpu_model = "Transmeta TM 5x00";
cpu_model = "TM 5x00";
} else if (cpuid_info.version.family == 15) {
cpu_model = "Transmeta TM 8x00";
cpu_model = "TM 8x00";
}
l1_cache = cpuid_info.cache_info.l1_i_size + cpuid_info.cache_info.l1_d_size;
l2_cache = cpuid_info.cache_info.l2_size;
@ -683,14 +647,14 @@ static void determine_cpu_model(void)
case 2:
case 3:
case 7:
cpu_model = "Intel Pentium";
cpu_model = "Pentium";
if (l1_cache == 0) {
l1_cache = 8;
}
break;
case 4:
case 8:
cpu_model = "Intel Pentium MMX";
cpu_model = "Pentium-MMX";
if (l1_cache == 0) {
l1_cache = 16;
}
@ -703,54 +667,54 @@ static void determine_cpu_model(void)
switch (cpuid_info.version.model) {
case 0:
case 1:
cpu_model = "Intel Pentium Pro";
cpu_model = "Pentium Pro";
break;
case 3:
case 4:
cpu_model = "Intel Pentium II";
cpu_model = "Pentium II";
break;
case 5:
if (l2_cache == 0) {
cpu_model = "Intel Celeron";
cpu_model = "Celeron";
} else {
cpu_model = "Intel Pentium II";
cpu_model = "Pentium II";
}
break;
case 6:
if (l2_cache == 128) {
cpu_model = "Intel Celeron";
cpu_model = "Celeron";
} else {
cpu_model = "Intel Pentium II";
cpu_model = "Pentium II";
}
break;
case 7:
case 8:
case 11:
if (l2_cache == 128) {
cpu_model = "Intel Celeron";
cpu_model = "Celeron";
} else {
cpu_model = "Intel Pentium III";
cpu_model = "Pentium III";
}
break;
case 9:
if (l2_cache == 512) {
cpu_model = "Intel Celeron M (0.13)";
cpu_model = "Celeron M (0.13)";
} else {
cpu_model = "Intel Pentium M (0.13)";
cpu_model = "Pentium M (0.13)";
}
break;
case 10:
cpu_model = "Intel Pentium III Xeon";
cpu_model = "Pentium III Xeon";
break;
case 12:
l1_cache = 24;
cpu_model = "Intel Atom (0.045)";
cpu_model = "Atom (0.045)";
break;
case 13:
if (l2_cache == 1024) {
cpu_model = "Intel Celeron M (0.09)";
cpu_model = "Celeron M (0.09)";
} else {
cpu_model = "Intel Pentium M (0.09)";
cpu_model = "Pentium M (0.09)";
}
break;
case 14:
@ -758,7 +722,7 @@ static void determine_cpu_model(void)
break;
case 15:
if (l2_cache == 1024) {
cpu_model = "Intel Pentium E";
cpu_model = "Pentium E";
} else {
cpu_model = "Intel Core 2";
}
@ -773,17 +737,17 @@ static void determine_cpu_model(void)
case 1:
case 2:
if (l2_cache == 128) {
cpu_model = "Intel Celeron";
cpu_model = "Celeron";
} else {
cpu_model = "Intel Pentium 4";
cpu_model = "Pentium 4";
}
break;
case 3:
case 4:
if (l2_cache == 256) {
cpu_model = "Intel Celeron (0.09)";
cpu_model = "Celeron (0.09)";
} else {
cpu_model = "Intel Pentium 4 (0.09)";
cpu_model = "Pentium 4 (0.09)";
}
break;
case 6:
@ -803,40 +767,78 @@ static void determine_cpu_model(void)
// VIA/Cyrix/Centaur Processors with CPUID
if (cpuid_info.vendor_id.str[1] == 'e' ) {
// CentaurHauls
l1_cache = cpuid_info.cache_info.l1_i_size + cpuid_info.cache_info.l1_d_size;
l2_cache = cpuid_info.cache_info.l2_size >> 8;
switch (cpuid_info.version.family) {
case 5:
cpu_model = "IDT WinChip C6";
l1_cache = 32;
// WinChip 2/3 (models 8/9) have brand string
cpu_model = "Centaur 5x86";
break;
case 6: // VIA C3
switch (cpuid_info.version.model) {
case 10:
cpu_model = "VIA C7 (C5J)";
l1_cache = 64;
l2_cache = 128;
break;
case 13:
cpu_model = "VIA C7 (C5R)";
l1_cache = 64;
l2_cache = 128;
break;
case 15:
cpu_model = "VIA Isaiah (CN)";
l1_cache = 64;
l2_cache = 128;
break;
default:
if (cpuid_info.version.stepping < 8) {
cpu_model = "VIA C3 Samuel2";
} else {
cpu_model = "VIA C3 Eden";
}
break;
}
default:
// All VIA/Centaur family values >= 6 have brand string
break;
}
} else { /* CyrixInstead */
switch (cpuid_info.version.family) {
case 4:
case 5:
switch (cpuid_info.version.model) {
case 2:
cpu_model = "Cyrix 5x86";
l1_cache = 16;
case 0:
cpu_model = "Cyrix 6x86MX/MII";
break;
case 4:
cpu_model = "Cyrix MediaGX/GXi";
l1_cache = 16;
cpu_model = "Cyrix GXm";
break;
default:
break;
}
break;
case 5:
cpu_model = "Cyrix 6x86/6x86L";
l1_cache = 16;
// Media GXm (model 4) has brand string
break;
case 6:
cpu_model = "Cyrix 6x86MX/MII";
case 6: // VIA C3
switch (cpuid_info.version.model) {
case 6:
cpu_model = "Cyrix III";
break;
case 7:
if (cpuid_info.version.stepping < 8) {
cpu_model = "VIA C3 Samuel2";
} else {
cpu_model = "VIA C3 Ezra-T";
}
break;
case 8:
cpu_model = "VIA C3 Ezra-T";
break;
case 9:
cpu_model = "VIA C3 Nehemiah";
break;
default:
break;
}
// L1 = L2 = 64 KB from Cyrix III to Nehemiah
l1_cache = 64;
l2_cache = 64;
break;
default:
break;
@ -847,10 +849,10 @@ static void determine_cpu_model(void)
// Unknown processor - make a guess at the family.
switch (cpuid_info.version.family) {
case 5:
cpu_model = "586-class CPU (unknown)";
cpu_model = "586";
break;
case 6:
cpu_model = "686-class CPU (unknown)";
cpu_model = "686";
break;
default:
cpu_model = "Unidentified Processor";

View file

@ -8,7 +8,7 @@
*
*//*
* Copyright (C) 2020-2022 Martin Whitaker.
* Copyright (C) 2004-2023 Sam Demeulemeester.
* Copyright (C) 2004-2022 Sam Demeulemeester.
*/
#include <stdbool.h>
@ -47,7 +47,6 @@
#define IMC_KBL_UY 0x3030 // Core 7/8/9th Gen (Kaby/Coffee/Comet/Amber Lake-U/Y)
#define IMC_ICL 0x3040 // Core 10th Gen (IceLake-Y)
#define IMC_TGL 0x3050 // Core 11th Gen (Tiger Lake-U)
#define IMC_ADL_N 0x3061 // Core 12th Gen (Alder Lake-N - Gracemont E-Cores only)
#define IMC_BYT 0x4010 // Atom Bay Trail
#define IMC_CDT 0x4020 // Atom Cedar Trail

View file

@ -32,9 +32,9 @@ void heap_init(void);
* region will be at least the requested size with the requested alignment.
* This memory is always mapped to the identical address in virtual memory.
*
* \param heap_id - the target heap.
* \param size - the requested size in bytes.
* \param alignment - the requested byte alignment (must be a power of 2).
* \param heap - the heap on which this allocation shall be performed.
*
* \returns
* On success, the allocated address in physical memory. On failure, 0.
@ -46,8 +46,6 @@ uintptr_t heap_alloc(heap_type_t heap_id, size_t size, uintptr_t alignment);
* memory heap. This value may be passed to heap_rewind() to free any
* memory from that heap allocated after this call.
*
* \param heap_id - the target heap.
*
* \returns
* An opaque value indicating the current allocation state.
*/
@ -57,8 +55,8 @@ uintptr_t heap_mark(heap_type_t heap_id);
* Frees any memory allocated in the given heap since the specified mark was
* obtained from a call to heap_mark().
*
* \param heap_id - the target heap.
* \param mark - the mark that indicates how much memory to free.
* \param heap - the heap on which this rewind shall be performed.
*/
void heap_rewind(heap_type_t heap_id, uintptr_t mark);

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2004-2023 Sam Demeulemeester
// Copyright (C) 2004-2022 Samuel Demeulemeester
//
// ------------------------
// This file is used to detect quirks on specific hardware
@ -13,9 +13,6 @@
#include "pci.h"
#include "unistd.h"
#include "cpuinfo.h"
#include "cpuid.h"
#include "config.h"
#include "temperature.h"
quirk_t quirk;
@ -67,38 +64,6 @@ static void get_m1541_l2_cache_size(void)
if (reg == 0b10) { l2_cache = 1024; }
}
static void disable_temp_reporting(void)
{
enable_temperature = false;
}
static void amd_k8_revfg_temp(void)
{
uint32_t rtcr = pci_config_read32(0, 24, 3, AMD_TEMP_REG_K8);
// For Rev F & G, switch sensor if no temperature is reported
if (!((rtcr >> 16) & 0xFF)) {
pci_config_write8(0, 24, 3, AMD_TEMP_REG_K8, rtcr | 0x04);
}
// K8 Rev G Desktop requires an additional offset.
if (cpuid_info.version.extendedModel < 6 && cpuid_info.version.extendedModel > 7) // Not Rev G
return;
if (cpuid_info.version.extendedModel == 6 && cpuid_info.version.extendedModel < 9) // Not Desktop
return;
uint16_t brandID = (cpuid_info.version.extendedBrandID >> 9) & 0x1f;
if (cpuid_info.version.model == 0xF && (brandID == 0x7 || brandID == 0x9 || brandID == 0xC)) // Mobile (Single Core)
return;
if (cpuid_info.version.model == 0xB && brandID > 0xB) // Mobile (Dual Core)
return;
cpu_temp_offset = 21.0f;
}
// ---------------------
// -- Public function --
// ---------------------
@ -107,8 +72,8 @@ void quirks_init(void)
{
quirk.id = QUIRK_NONE;
quirk.type = QUIRK_TYPE_NONE;
quirk.root_vid = pci_config_read16(0, 0, 0, PCI_VID_REG);
quirk.root_did = pci_config_read16(0, 0, 0, PCI_DID_REG);
quirk.root_vid = pci_config_read16(0, 0, 0, 0);
quirk.root_did = pci_config_read16(0, 0, 0, 2);
quirk.process = NULL;
// -------------------------
@ -128,75 +93,13 @@ void quirks_init(void)
// This motherboard has an ASB100 ASIC with a SMBUS Mux Integrated.
// To access SPD later in the code, we need to configure the mux.
// PS: Detection via DMI is unreliable, so using Root PCI Registers
if (quirk.root_vid == PCI_VID_INTEL && quirk.root_did == 0x1130) { // Intel i815
if (pci_config_read16(0, 0, 0, PCI_SUB_VID_REG) == PCI_VID_ASUS) { // ASUS
if (pci_config_read16(0, 0, 0, PCI_SUB_DID_REG) == 0x8027) { // TUSL2-C
if (quirk.root_vid == PCI_VID_INTEL && quirk.root_did == 0x1130) { // Intel i815
if (pci_config_read16(0, 0, 0, 0x2C) == PCI_VID_ASUS) { // ASUS
if (pci_config_read16(0, 0, 0, 0x2E) == 0x8027) { // TUSL2-C
quirk.id = QUIRK_TUSL2;
quirk.type |= QUIRK_TYPE_SMBUS;
quirk.process = asus_tusl2_configure_mux;
}
}
}
// -------------------------------------------------
// -- SuperMicro X10SDV Quirk (GitHub Issue #233) --
// -------------------------------------------------
// Memtest86+ crashs on Super Micro X10SDV motherboard with SMP Enabled
// We were unable to find a solution so far, so disable SMP by default
if (quirk.root_vid == PCI_VID_INTEL && quirk.root_did == 0x6F00) { // Broadwell-E (Xeon-D)
if (pci_config_read16(0, 0, 0, PCI_SUB_VID_REG) == PCI_VID_SUPERMICRO) { // Super Micro
quirk.id = QUIRK_X10SDV_NOSMP;
quirk.type |= QUIRK_TYPE_SMP;
quirk.process = NULL;
}
}
// ------------------------------------------------------
// -- Early AMD K8 doesn't support temperature reading --
// ------------------------------------------------------
// The on-die temperature diode on SH-B0/B3 stepping does not work.
if (cpuid_info.vendor_id.str[0] == 'A' && cpuid_info.version.family == 0xF
&& cpuid_info.version.extendedFamily == 0 && cpuid_info.version.extendedModel == 0) { // Early K8
if ((cpuid_info.version.model == 4 && cpuid_info.version.stepping == 0) || // SH-B0 ClawHammer (Athlon 64)
(cpuid_info.version.model == 5 && cpuid_info.version.stepping <= 1)) { // SH-B0/B3 SledgeHammer (Opteron)
quirk.id = QUIRK_K8_BSTEP_NOTEMP;
quirk.type |= QUIRK_TYPE_TEMP;
quirk.process = disable_temp_reporting;
}
}
// ---------------------------------------------------
// -- Late AMD K8 (rev F/G) temp sensor workaround --
// ---------------------------------------------------
if (cpuid_info.vendor_id.str[0] == 'A' && cpuid_info.version.family == 0xF
&& cpuid_info.version.extendedFamily == 0 && cpuid_info.version.extendedModel >= 4) { // Later K8
quirk.id = QUIRK_K8_REVFG_TEMP;
quirk.type |= QUIRK_TYPE_TEMP;
quirk.process = amd_k8_revfg_temp;
}
// ------------------------------------------------
// -- AMD K10 CPUs Temp workaround (Errata #319) --
// ------------------------------------------------
// Some AMD K10 CPUs on Socket AM2+/F have buggued thermal diode leading
// to inaccurate temperature measurements. Affected steppings: DR-BA/B2/B3, RB-C2 & HY-D0.
if (cpuid_info.vendor_id.str[0] == 'A' && cpuid_info.version.family == 0xF
&& cpuid_info.version.extendedFamily == 1 && cpuid_info.version.extendedModel == 0) { // AMD K10
uint8_t pkg_type = (cpuid_info.version.extendedBrandID >> 28) & 0x0F;
uint32_t dct0_high = pci_config_read32(0, 24, 2, 0x94); // 0x94[8] = 1 for DDR3
if (pkg_type == 0b0000 || (pkg_type == 0b0001 && (((dct0_high >> 8) & 1) == 0))) { // Socket F or AM2+ (exclude AM3)
if (cpuid_info.version.model < 4 || // DR-BA, DR-B2 & DR-B3
(cpuid_info.version.model == 4 && cpuid_info.version.stepping <= 2) || // RB-C2
cpuid_info.version.model == 8) { // HY-D0
quirk.id = QUIRK_AMD_ERRATA_319;
quirk.type |= QUIRK_TYPE_TEMP;
quirk.process = disable_temp_reporting;
}
}
}
}

View file

@ -19,16 +19,11 @@
#define QUIRK_TYPE_SMBUS (1 << 4)
#define QUIRK_TYPE_TIMER (1 << 5)
#define QUIRK_TYPE_MEM_SIZE (1 << 6)
#define QUIRK_TYPE_TEMP (1 << 7)
typedef enum {
QUIRK_NONE,
QUIRK_TUSL2,
QUIRK_ALI_ALADDIN_V,
QUIRK_X10SDV_NOSMP,
QUIRK_K8_BSTEP_NOTEMP,
QUIRK_K8_REVFG_TEMP,
QUIRK_AMD_ERRATA_319
QUIRK_ALI_ALADDIN_V
} quirk_id_t;
typedef struct {

View file

@ -478,7 +478,7 @@ static const struct spd_jedec_manufacturer jep106[] = {
// { 0x0353, "Primarion" },
// { 0x0354, "Picochip Designs Ltd" },
// { 0x0355, "Silverback Systems" },
{ 0x0356, "Jade Star" },
// { 0x0356, "Jade Star Technologies" },
// { 0x0357, "Pijnenburg Securealink" },
{ 0x0358, "takeMS" }, // Ultron AG
// { 0x0359, "Cambridge Silicon Radio" },
@ -882,7 +882,7 @@ static const struct spd_jedec_manufacturer jep106[] = {
// { 0x066E, "Certicom Corporation" },
// { 0x066F, "JSC ICC Milandr" },
// { 0x0670, "PhotoFast Global Inc" },
{ 0x0671, "InnoDisk" },
// { 0x0671, "InnoDisk Corporation" },
// { 0x0672, "Muscle Power" },
// { 0x0673, "Energy Micro" },
// { 0x0674, "Innofidei" },

View file

@ -30,9 +30,6 @@
#define MSR_AMD64_NB_CFG 0xc001001f
#define MSR_AMD64_COFVID_STATUS 0xc0010071
#define MSR_VIA_TEMP_C7 0x1169
#define MSR_VIA_TEMP_NANO 0x1423
#define rdmsr(msr, value1, value2) \
__asm__ __volatile__("rdmsr" \
: "=a" (value1), \

View file

@ -12,11 +12,6 @@
#include <stdint.h>
#define PCI_VID_REG 0x00
#define PCI_DID_REG 0x02
#define PCI_SUB_VID_REG 0x2C
#define PCI_SUB_DID_REG 0x2E
/* Vendor IDs */
#define PCI_VID_ATI 0x1002
#define PCI_VID_AMD 0x1022
@ -27,7 +22,6 @@
#define PCI_VID_NVIDIA 0x10DE
#define PCI_VID_VIA 0x1106
#define PCI_VID_SERVERWORKS 0x1166
#define PCI_VID_SUPERMICRO 0x15D9
#define PCI_VID_HYGON 0x1D94
#define PCI_VID_INTEL 0x8086

View file

@ -42,7 +42,7 @@ static const rgb_value_t vga_pallete[16] = {
{ 255, 255, 255 } // BOLD+WHITE
};
static vga_buffer_t *vga_buffer = NULL;
static vga_buffer_t *vga_buffer = (vga_buffer_t *)(0xb8000);
vga_buffer_t shadow_buffer;
@ -64,9 +64,7 @@ static void vga_put_char(int row, int col, uint8_t ch, uint8_t attr)
shadow_buffer[row][col].ch = ch;
shadow_buffer[row][col].attr = attr;
if (vga_buffer) {
(*vga_buffer)[row][col].value = shadow_buffer[row][col].value;
}
(*vga_buffer)[row][col].value = shadow_buffer[row][col].value;
}
static void lfb8_put_char(int row, int col, uint8_t ch, uint8_t attr)
@ -241,8 +239,6 @@ void screen_init(void)
uint32_t b = ((vga_pallete[i].b * b_max) / 255) << screen_info->blue_pos;
lfb_pallete[i] = r | g | b;
}
} else if (screen_info->orig_video_isVGA != VIDEO_TYPE_NONE) {
vga_buffer = (vga_buffer_t *)(0xb8000);
}
}

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2004-2023 Sam Demeulemeester
// Copyright (C) 2004-2022 Samuel Demeulemeester
#include "display.h"
@ -48,14 +48,11 @@ static uint8_t get_spd(uint8_t slot_idx, uint16_t spd_adr);
static bool nv_mcp_get_smb(void);
static bool amd_sb_get_smb(void);
static bool fch_zen_get_smb(void);
static bool piix4_get_smb(uint8_t address);
static bool piix4_get_smb(void);
static bool ich5_get_smb(void);
static bool ali_get_smb(uint8_t address);
static uint8_t ich5_process(void);
static uint8_t ich5_read_spd_byte(uint8_t adr, uint16_t cmd);
static uint8_t nf_read_spd_byte(uint8_t smbus_adr, uint8_t spd_adr);
static uint8_t ali_m1563_read_spd_byte(uint8_t smbus_adr, uint8_t spd_adr);
static uint8_t ali_m1543_read_spd_byte(uint8_t smbus_adr, uint8_t spd_adr);
static inline uint8_t bcd_to_ui8(uint8_t bcd)
{
@ -1161,7 +1158,7 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
return ich5_get_smb();
}
if (did == 0x7113) { // 82371AB/EB/MB PIIX4
return piix4_get_smb(PIIX4_SMB_BASE_ADR_DEFAULT);
return piix4_get_smb();
}
// 0x719B 82440/82443MX PMC - PIIX4
// 0x0F13 ValleyView SMBus Controller ?
@ -1192,8 +1189,7 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
{
// case 0x4353: // SB200
// case 0x4363: // SB300
case 0x4372: // SB400
return piix4_get_smb(PIIX4_SMB_BASE_ADR_DEFAULT);
// case 0x4372: // SB400
case 0x4385: // SB600+
return amd_sb_get_smb();
default:
@ -1207,7 +1203,7 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
// case 0x01B4: // nForce
case 0x0064: // nForce 2
// case 0x0084: // nForce 2 Mobile
case 0x00E4: // nForce 3
// case 0x00E4: // nForce 3
// case 0x0034: // MCP04
// case 0x0052: // nForce 4
case 0x0264: // nForce 410/430 MCP
@ -1247,17 +1243,16 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
// via SMBus controller.
// case 0x3050: // 82C596_3
// Try SMB base address = 0x90, then SMB base address = 0x80
// viapro SMBus controller, i.e. PIIX4 with a small quirk.
// viapro SMBus controller.
// case 0x3051: // 82C596B_3
case 0x3057: // 82C686_4
// case 0x3057: // 82C686_4
// case 0x8235: // 8231_4
// SMB base address = 0x90
// viapro SMBus controller, i.e. PIIX4.
return piix4_get_smb(PIIX4_SMB_BASE_ADR_DEFAULT);
case 0x3074: // 8233
case 0x3147: // 8233A
case 0x3177: // 8235
case 0x3227: // 8237
// viapro SMBus controller.
// case 0x3074: // 8233_0
// case 0x3147: // 8233A
// case 0x3177: // 8235
// case 0x3227: // 8237
// case 0x3337: // 8237A
// case 0x3372: // 8237S
// case 0x3287: // 8251
@ -1266,8 +1261,7 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
// case 0x8409: // VX855
// case 0x8410: // VX900
// SMB base address = 0xD0
// viapro I2C controller, i.e. PIIX4 with a small quirk.
return piix4_get_smb(PIIX4_SMB_BASE_ADR_VIAPRO);
// viapro I2C controller.
default:
return false;
}
@ -1285,10 +1279,8 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
case PCI_VID_ALI:
switch(did)
{
case 0x7101: // ALi M1533/1535/1543C
return ali_get_smb(PIIX4_SMB_BASE_ADR_ALI1543);
case 0x1563: // ALi M1563
return piix4_get_smb(PIIX4_SMB_BASE_ADR_ALI1563);
// case 0x1563: // ali1563 (M1563) SMBus controller
// case 0x7101: // ali1535 (M1535) or ali15x3 (M1533/M1543) SMBus controllers
default:
return false;
}
@ -1305,7 +1297,7 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
// case 0x0203: // CSB6
// case 0x0205: // HT1000SB
// case 0x0408: // HT1100LD
return piix4_get_smb(PIIX4_SMB_BASE_ADR_DEFAULT);
return piix4_get_smb();
default:
return false;
}
@ -1320,9 +1312,9 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
// PIIX4 SMBUS Controller
// ----------------------
static bool piix4_get_smb(uint8_t address)
static bool piix4_get_smb(void)
{
uint16_t x = pci_config_read16(0, smbdev, smbfun, address) & 0xFFF0;
uint16_t x = pci_config_read16(0, smbdev, smbfun, 0x90) & 0xFFF0;
if (x != 0) {
smbusbase = x;
@ -1340,18 +1332,10 @@ static bool ich5_get_smb(void)
{
uint16_t x;
// Enable SMBus IO Space if disabled
x = pci_config_read16(0, smbdev, smbfun, 0x4);
if (!(x & 1)) {
pci_config_write16(0, smbdev, smbfun, 0x4, x | 1);
}
// Read Base Address
x = pci_config_read16(0, smbdev, smbfun, 0x20);
smbusbase = x & 0xFFF0;
// Enable I2C Host Controller Interface if disabled
// Enable I2C Bus
uint8_t temp = pci_config_read8(0, smbdev, smbfun, 0x40);
if ((temp & 4) == 0) {
pci_config_write8(0, smbdev, smbfun, 0x40, temp | 0x04);
@ -1377,7 +1361,7 @@ static bool amd_sb_get_smb(void)
if ((smbus_id & 0xFFFF) == 0x4385 && rev_id <= 0x3D) {
// Older AMD SouthBridge (SB700 & older) use PIIX4 registers
return piix4_get_smb(PIIX4_SMB_BASE_ADR_DEFAULT);
return piix4_get_smb();
} else if ((smbus_id & 0xFFFF) == 0x780B && rev_id == 0x42) {
// Latest Pre-Zen APUs use the newer Zen PM registers
return fch_zen_get_smb();
@ -1450,35 +1434,6 @@ static bool nv_mcp_get_smb(void)
return false;
}
// ---------------------------------------
// ALi SMBUS Controller (M1533/1535/1543C)
// ---------------------------------------
static bool ali_get_smb(uint8_t address)
{
// Enable SMB I/O Base Address Register Control (Reg0x5B[2] = 0)
uint16_t temp = pci_config_read8(0, smbdev, smbfun, 0x5B);
pci_config_write8(0, smbdev, smbfun, 0x5B, temp & ~0x06);
// Enable Response to I/O Access. (Reg0x04[0] = 1)
temp = pci_config_read8(0, smbdev, smbfun, 0x04);
pci_config_write8(0, smbdev, smbfun, 0x04, temp | 0x01);
// SMB Host Controller Interface Enable (Reg0xE0[0] = 1)
temp = pci_config_read8(0, smbdev, smbfun, 0xE0);
pci_config_write8(0, smbdev, smbfun, 0xE0, temp | 0x01);
// Read SMBase Register (usually 0xE800)
uint16_t x = pci_config_read16(0, smbdev, smbfun, address) & 0xFFF0;
if (x != 0) {
smbusbase = x;
return true;
}
return false;
}
// ------------------
// get_spd() function
// ------------------
@ -1486,11 +1441,6 @@ static bool ali_get_smb(uint8_t address)
static uint8_t get_spd(uint8_t slot_idx, uint16_t spd_adr)
{
switch ((smbus_id >> 16) & 0xFFFF) {
case PCI_VID_ALI:
if ((smbus_id & 0xFFFF) == 0x7101)
return ali_m1543_read_spd_byte(slot_idx, (uint8_t)spd_adr);
else
return ali_m1563_read_spd_byte(slot_idx, (uint8_t)spd_adr);
case PCI_VID_NVIDIA:
return nf_read_spd_byte(slot_idx, (uint8_t)spd_adr);
default:
@ -1618,7 +1568,7 @@ static uint8_t nf_read_spd_byte(uint8_t smbus_adr, uint8_t spd_adr)
// Start transaction
__outb(NVSMBCNT_BYTE_DATA | NVSMBCNT_READ, NVSMBCNT);
// Wait until transaction complete
// Wait until transction complete
for (i = 500; i > 0; i--) {
usleep(50);
if (__inb(NVSMBCNT) == 0) {
@ -1633,73 +1583,3 @@ static uint8_t nf_read_spd_byte(uint8_t smbus_adr, uint8_t spd_adr)
return __inb(NVSMBDAT(0));
}
static uint8_t ali_m1563_read_spd_byte(uint8_t smbus_adr, uint8_t spd_adr)
{
int i;
smbus_adr += 0x50;
// Reset Status Register
__outb(0xFF, SMBHSTSTS);
// Set Slave ADR
__outb((smbus_adr << 1 | I2C_READ), SMBHSTADD);
__outb((__inb(SMBHSTCNT) & ~ALI_SMBHSTCNT_SIZEMASK) | (ALI_SMBHSTCNT_BYTE_DATA << 3), SMBHSTCNT);
// Set Command (SPD Byte to Read)
__outb(spd_adr, SMBHSTCMD);
// Start transaction
__outb(__inb(SMBHSTCNT) | SMBHSTCNT_START, SMBHSTCNT);
// Wait until transaction complete
for (i = 500; i > 0; i--) {
usleep(50);
if (!(__inb(SMBHSTSTS) & SMBHSTSTS_HOST_BUSY)) {
break;
}
}
// If timeout or Error Status, exit
if (i == 0 || __inb(SMBHSTSTS) & ALI_SMBHSTSTS_BAD) {
return 0xFF;
}
return __inb(SMBHSTDAT0);
}
static uint8_t ali_m1543_read_spd_byte(uint8_t smbus_adr, uint8_t spd_adr)
{
int i;
smbus_adr += 0x50;
// Reset Status Register
__outb(0xFF, SMBHSTSTS);
// Set Slave ADR
__outb((smbus_adr << 1 | I2C_READ), ALI_OLD_SMBHSTADD);
// Set Command (SPD Byte to Read)
__outb(spd_adr, ALI_OLD_SMBHSTCMD);
// Start transaction
__outb(ALI_OLD_SMBHSTCNT_BYTE_DATA, ALI_OLD_SMBHSTCNT);
__outb(0xFF, ALI_OLD_SMBHSTSTART);
// Wait until transaction complete
for (i = 500; i > 0; i--) {
usleep(50);
if (!(__inb(SMBHSTSTS) & ALI_OLD_SMBHSTSTS_BUSY)) {
break;
}
}
// If timeout or Error Status, exit
if (i == 0 || __inb(SMBHSTSTS) & ALI_OLD_SMBHSTSTS_BAD) {
return 0xFF;
}
return __inb(ALI_OLD_SMBHSTDAT0);
}

View file

@ -7,7 +7,7 @@
*
* Provides functions for reading SPD via SMBUS
*
* Copyright (C) 2004-2023 Sam Demeulemeester.
* Copyright (C) 2004-2022 Samuel Demeulemeester.
*/
#define I2C_WRITE 0
@ -74,28 +74,6 @@
#define NVSMBSTS_RES 0x20
#define NVSMBSTS_STATUS 0x1f
/* ALi-Specific constants (M1563 & newer) */
#define ALI_SMBHSTCNT_SIZEMASK 0x03
#define ALI_SMBHSTSTS_BAD 0x1C
#define ALI_SMBHSTCNT_QUICK 0x00
#define ALI_SMBHSTCNT_BYTE 0x01
#define ALI_SMBHSTCNT_BYTE_DATA 0x02
#define ALI_SMBHSTCNT_WORD_DATA 0x03
#define ALI_SMBHSTCNT_KILL 0x04
#define ALI_SMBHSTCNT_BLOCK 0x05
/* ALi-Specific constants (M1543 & older) */
#define ALI_OLD_SMBHSTSTS_BAD 0xE0
#define ALI_OLD_SMBHSTSTS_BUSY 0x08
#define ALI_OLD_SMBHSTCNT_BYTE_DATA 0x20
#define ALI_OLD_SMBHSTCNT smbusbase + 1
#define ALI_OLD_SMBHSTSTART smbusbase + 2
#define ALI_OLD_SMBHSTADD smbusbase + 3
#define ALI_OLD_SMBHSTDAT0 smbusbase + 4
#define ALI_OLD_SMBHSTCMD smbusbase + 7
/** Rounding factors for timing computation
*
* These factors are used as a configurable CEIL() function
@ -107,11 +85,6 @@
#define SPD_SKU_LEN 32
#define PIIX4_SMB_BASE_ADR_DEFAULT 0x90
#define PIIX4_SMB_BASE_ADR_VIAPRO 0xD0
#define PIIX4_SMB_BASE_ADR_ALI1563 0x80
#define PIIX4_SMB_BASE_ADR_ALI1543 0x14
struct pci_smbus_controller {
unsigned vendor;
unsigned device;

View file

@ -21,7 +21,6 @@
#include "cpuid.h"
#include "heap.h"
#include "hwquirks.h"
#include "memrw32.h"
#include "memsize.h"
#include "msr.h"
@ -540,12 +539,6 @@ void smp_init(bool smp_enable)
}
}
// Process SMP Quirks
if (quirk.type & QUIRK_TYPE_SMP) {
// quirk.process();
smp_enable = false;
}
if (smp_enable) {
(void)(find_cpus_in_madt() || find_cpus_in_floating_mp_struct());

View file

@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2020-2022 Martin Whitaker.
// Copyright (C) 2004-2023 Sam Demeulemeester.
//
// Derived from an extract of memtest86+ init.c:
//
@ -17,120 +16,57 @@
#include "cpuid.h"
#include "cpuinfo.h"
#include "hwquirks.h"
#include "msr.h"
#include "pci.h"
#include "temperature.h"
//------------------------------------------------------------------------------
// Public Variables
//------------------------------------------------------------------------------
float cpu_temp_offset = 0;
//------------------------------------------------------------------------------
// Public Functions
//------------------------------------------------------------------------------
static int TjMax = 0;
void get_specific_TjMax(void)
{
// The TjMax value for some Mobile/Embedded CPUs must be read from a fixed
// table according to their CPUID, PCI Root DID/VID or PNS.
// Trying to read the MSR 0x1A2 on some of them trigger a reboot.
// Yonah C0 Step (Pentium/Core Duo T2000 & Celeron M 200/400)
if (cpuid_info.version.raw[0] == 0x6E8) {
TjMax = 100;
}
}
void temperature_init(void)
{
uint32_t regl, regh;
// Process temperature-related quirks
if (quirk.type & QUIRK_TYPE_TEMP) {
quirk.process();
}
// Get TjMax for Intel CPU
if (cpuid_info.vendor_id.str[0] == 'G' && cpuid_info.max_cpuid >= 6 && (cpuid_info.dts_pmp & 1)) {
get_specific_TjMax();
if (TjMax == 0) {
// Generic Method using MSR 0x1A2
rdmsr(MSR_IA32_TEMPERATURE_TARGET, regl, regh);
TjMax = (regl >> 16) & 0x7F;
if (TjMax < 50 || TjMax > 125) {
TjMax = 100;
}
}
}
}
int get_cpu_temperature(void)
{
uint32_t regl, regh;
// Intel CPU
if (cpuid_info.vendor_id.str[0] == 'G' && cpuid_info.max_cpuid >= 6 && (cpuid_info.dts_pmp & 1)) {
if (cpuid_info.vendor_id.str[0] == 'G' && cpuid_info.max_cpuid >= 6) {
if (cpuid_info.dts_pmp & 1) {
uint32_t msrl, msrh;
rdmsr(MSR_IA32_THERM_STATUS, regl, regh);
int Tabs = (regl >> 16) & 0x7F;
rdmsr(MSR_IA32_THERM_STATUS, msrl, msrh);
int Tabs = (msrl >> 16) & 0x7F;
return TjMax - Tabs;
rdmsr(MSR_IA32_TEMPERATURE_TARGET, msrl, msrh);
int Tjunc = (msrl >> 16) & 0x7F;
if (Tjunc < 50 || Tjunc > 125) {
Tjunc = 90;
}
return Tjunc - Tabs;
}
}
// AMD CPU
else if (cpuid_info.vendor_id.str[0] == 'A' && cpuid_info.version.family == 0xF) { // Target only K8 & newer
if (cpuid_info.vendor_id.str[0] == 'A' && cpuid_info.version.extendedFamily > 0 && cpuid_info.version.extendedFamily < 8) {
if (cpuid_info.version.extendedFamily >= 8) { // Target Zen µarch and newer. Use SMN to get temperature.
// Untested yet
uint32_t rtcr = pci_config_read32(0, 24, 3, 0xA4);
int raw_temp = (rtcr >> 21) & 0x7FF;
regl = amd_smn_read(SMN_THM_TCON_CUR_TMP);
return raw_temp / 8;
if ((regl >> 19) & 0x01) {
cpu_temp_offset = -49.0f;
}
} else if (cpuid_info.vendor_id.str[0] == 'A' && cpuid_info.version.extendedFamily >= 8) {
return cpu_temp_offset + 0.125f * (float)((regl >> 21) & 0x7FF);
// Grab CPU Temp. for ZEN CPUs using SNM
uint32_t tval = amd_smn_read(SMN_THM_TCON_CUR_TMP);
} else if (cpuid_info.version.extendedFamily > 0) { // Target K10 to K15 (Bulldozer)
float offset = 0;
regl = pci_config_read32(0, 24, 3, AMD_TEMP_REG_K10);
int raw_temp = ((regl >> 21) & 0x7FF) / 8;
return (raw_temp > 0) ? raw_temp : 0;
} else { // Target K8 (CPUID ExtFamily = 0)
regl = pci_config_read32(0, 24, 3, AMD_TEMP_REG_K8);
int raw_temp = ((regl >> 16) & 0xFF) - 49 + cpu_temp_offset;
return (raw_temp > 0) ? raw_temp : 0;
}
}
// VIA/Centaur/Zhaoxin CPU
else if (cpuid_info.vendor_id.str[0] == 'C' && cpuid_info.vendor_id.str[1] == 'e'
&& (cpuid_info.version.family == 6 || cpuid_info.version.family == 7)) {
uint32_t msr_temp;
if (cpuid_info.version.family == 7 || cpuid_info.version.model == 0xF) {
msr_temp = MSR_VIA_TEMP_NANO; // Zhaoxin, Nano
} else if (cpuid_info.version.model == 0xA || cpuid_info.version.model == 0xD) {
msr_temp = MSR_VIA_TEMP_C7; // C7 A/D
} else {
return 0;
if((tval >> 19) & 0x01) {
offset = -49.0f;
}
rdmsr(msr_temp, regl, regh);
return (int)(regl & 0xffffff);
return offset + 0.125f * (float)((tval >> 21) & 0x7FF);
}
return 0;

View file

@ -8,22 +8,8 @@
*
*//*
* Copyright (C) 2020-2022 Martin Whitaker.
* Copyright (C) 2003-2023 Sam Demeulemeester.
*/
#define AMD_TEMP_REG_K8 0xE4
#define AMD_TEMP_REG_K10 0xA4
/**
* Global CPU Temperature offset
*/
extern float cpu_temp_offset;
/**
* Init temperature sensor and compute offsets if needed
*/
void temperature_init(void);
/**
* Returns the current temperature of the CPU. Returns 0 if
* the temperature cannot be read.

View file

@ -18,6 +18,7 @@
#define PIT_TICKS_50mS 59659 // PIT clock is 1.193182MHz
#define APIC_TICKS_50mS 178977 // APIC clock is 3.579545MHz
#define BENCH_MIN_START_ADR 0x1000000 // 16MB
//------------------------------------------------------------------------------
// Private Functions
@ -38,9 +39,6 @@ static void correct_tsc(void)
counter = inl(acpi_config.pm_addr);
// Generate a dirty delay
for(volatile uint8_t i=0; i<100u; i++);
// Make sure counter is incrementing
if (inl(acpi_config.pm_addr) > counter) {

View file

@ -16,8 +16,6 @@
#include <stdbool.h>
#include <stdint.h>
#include "vmem.h"
#include "display.h"
#include "error.h"
#include "test.h"
@ -129,20 +127,12 @@ int test_own_addr1(int my_cpu)
int test_own_addr2(int my_cpu, int stage)
{
static testword_t offset = 0;
static int last_stage = -1;
int ticks = 0;
testword_t offset;
// Calculate the offset (in pages) between the virtual address and the physical address.
offset = (vm_map[0].pm_base_addr / VM_WINDOW_SIZE) * VM_WINDOW_SIZE;
offset = (offset >= VM_PINNED_SIZE) ? offset - VM_PINNED_SIZE : 0;
#ifdef __x86_64__
// Convert to a byte address offset. This will translate the virtual address into a physical address.
offset *= PAGE_SIZE;
#else
// Convert to a VM window offset. This will get added into the LSBs of the virtual address.
offset /= VM_WINDOW_SIZE;
#endif
offset = (stage == last_stage) ? offset + 1 : 1;
switch (stage) {
case 0:
@ -155,5 +145,6 @@ int test_own_addr2(int my_cpu, int stage)
break;
}
last_stage = stage;
return ticks;
}

View file

@ -51,7 +51,7 @@
test_pattern_t test_list[NUM_TEST_PATTERNS] = {
// ena, cpu, stgs, itrs, errs, description
{ true, SEQ, 1, 6, 0, "[Address test, walking ones, no cache] "},
{false, SEQ, 1, 6, 0, "[Address test, own address in window] "},
{ true, SEQ, 1, 6, 0, "[Address test, own address in window] "},
{ true, SEQ, 2, 6, 0, "[Address test, own address + window] "},
{ true, PAR, 1, 6, 0, "[Moving inversions, 1s & 0s] "},
{ true, PAR, 1, 3, 0, "[Moving inversions, 8 bit pattern] "},