mirror of
https://codeberg.org/libreboot/memtest86plus.git
synced 2025-07-04 00:07:05 +00:00
Compare commits
55 commits
Author | SHA1 | Date | |
---|---|---|---|
|
5dcd424ea7 | ||
|
1f1fe5bfe8 | ||
|
0fd2e4c37a | ||
|
fa4e903509 | ||
|
bfbb167a72 | ||
|
79bb781431 | ||
|
c6b04e5414 | ||
|
5cbcd2046b | ||
|
bf0dae04bc | ||
|
dcca756e48 | ||
|
262aac4f85 | ||
|
66bd82f12a | ||
|
ee0c400821 | ||
|
e1fc02bfe0 | ||
|
a1d046fc3a | ||
|
1a38f513de | ||
|
22663f89bb | ||
|
c38b0cbc5f | ||
|
dfc41f7196 | ||
|
f62bbfde32 | ||
|
8305d47675 | ||
|
a47f681151 | ||
|
68e9542c1e | ||
|
ce2c29eddc | ||
|
b01c8e4388 | ||
|
d088740757 | ||
|
9c16a0568a | ||
|
040e253b54 | ||
|
2fa2346ae0 | ||
|
e5d7119abf | ||
|
a4c9adc445 | ||
|
485bfa46a3 | ||
|
b15a8bb632 | ||
|
327495ec61 | ||
|
8f788b27e1 | ||
|
f24e897883 | ||
|
3aeda70e24 | ||
|
b6992b9ec0 | ||
|
10e8435604 | ||
|
186ef6e913 | ||
|
d0399fd287 | ||
|
68deff493f | ||
|
1fca6dbcab | ||
|
a1af48a8cf | ||
|
03cd8d1898 | ||
|
d3d52b8a11 | ||
|
04980dfda3 | ||
|
d1014365c1 | ||
|
e022441544 | ||
|
3dd1fa8959 | ||
|
e3c0d6df60 | ||
|
87f03f3b10 | ||
|
f96c5b5093 | ||
|
59a0996070 | ||
|
da7b9b955d |
42 changed files with 1242 additions and 372 deletions
2
.github/workflows/Linux.yml
vendored
2
.github/workflows/Linux.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
compiler: [gcc, clang]
|
compiler: [gcc, clang]
|
||||||
os: [ubuntu-18.04, ubuntu-20.04, ubuntu-22.04]
|
os: [ubuntu-20.04, ubuntu-22.04]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
2
.github/workflows/expired.yml
vendored
2
.github/workflows/expired.yml
vendored
|
@ -6,7 +6,7 @@ jobs:
|
||||||
stale:
|
stale:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v6
|
- uses: actions/stale@v8
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
exempt-issue-milestones: 'future,alpha,beta,release'
|
exempt-issue-milestones: 'future,alpha,beta,release'
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -8,7 +8,7 @@
|
||||||
*.o
|
*.o
|
||||||
|
|
||||||
# Generated file
|
# Generated file
|
||||||
githash.h
|
build_version.h
|
||||||
|
|
||||||
# Binaries
|
# Binaries
|
||||||
memtest_shared
|
memtest_shared
|
||||||
|
|
|
@ -129,6 +129,8 @@ recognised:
|
||||||
* disables ACPI table parsing and the use of multiple CPU cores
|
* disables ACPI table parsing and the use of multiple CPU cores
|
||||||
* nobench
|
* nobench
|
||||||
* disables the integrated memory benchmark
|
* disables the integrated memory benchmark
|
||||||
|
* nobigstatus
|
||||||
|
* disables the big PASS/FAIL pop-up status display
|
||||||
* nosm
|
* nosm
|
||||||
* disables SMBUS/SPD parsing, DMI decoding and memory benchmark
|
* disables SMBUS/SPD parsing, DMI decoding and memory benchmark
|
||||||
* nopause
|
* nopause
|
||||||
|
@ -155,7 +157,7 @@ recognised:
|
||||||
* 9600
|
* 9600
|
||||||
* 19200
|
* 19200
|
||||||
* 38400
|
* 38400
|
||||||
* 54600
|
* 57600
|
||||||
* 115200 (default if not specified or invalid)
|
* 115200 (default if not specified or invalid)
|
||||||
* 230400
|
* 230400
|
||||||
|
|
||||||
|
@ -481,8 +483,9 @@ selected by the user.
|
||||||
|
|
||||||
### Test 2 : Address test, own address + window
|
### Test 2 : Address test, own address + window
|
||||||
|
|
||||||
Across all memory regions, each address is written with its own address plus
|
Across all memory regions, each address is written with its own virtual
|
||||||
the window number and then each address is checked for consistency. This
|
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
|
||||||
catches any errors in the high order address bits that would be missed when
|
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
|
testing each window in turn. This test is performed sequentially with each
|
||||||
available CPU, regardless of the CPU sequencing mode selected by the user.
|
available CPU, regardless of the CPU sequencing mode selected by the user.
|
||||||
|
|
177
app/badram.c
177
app/badram.c
|
@ -34,6 +34,7 @@
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#define MAX_PATTERNS 10
|
#define MAX_PATTERNS 10
|
||||||
|
#define PATTERNS_SIZE (MAX_PATTERNS + 1)
|
||||||
|
|
||||||
// DEFAULT_MASK covers a uintptr_t, since that is the testing granularity.
|
// DEFAULT_MASK covers a uintptr_t, since that is the testing granularity.
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
|
@ -55,14 +56,16 @@ typedef struct {
|
||||||
// Private Variables
|
// Private Variables
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
static pattern_t pattern[MAX_PATTERNS];
|
static pattern_t patterns[PATTERNS_SIZE];
|
||||||
static int num_patterns = 0;
|
static int num_patterns = 0;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Private Functions
|
// Private Functions
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#define COMBINE_MASK(a,b,c,d) ((a & b & c & d) | (~a & b & ~c & d))
|
// 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))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Combine two addr/mask pairs to one addr/mask pair.
|
* Combine two addr/mask pairs to one addr/mask pair.
|
||||||
|
@ -72,7 +75,7 @@ static void combine(uintptr_t addr1, uintptr_t mask1, uintptr_t addr2, uintptr_t
|
||||||
*mask = COMBINE_MASK(addr1, mask1, addr2, mask2);
|
*mask = COMBINE_MASK(addr1, mask1, addr2, mask2);
|
||||||
|
|
||||||
*addr = addr1 | addr2;
|
*addr = addr1 | addr2;
|
||||||
*addr &= *mask; // Normalise, no fundamental need for this
|
*addr &= *mask; // Normalise to ensure sorting on .addr will work as intended
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -104,58 +107,110 @@ static uintptr_t combi_cost(uintptr_t addr1, uintptr_t mask1, uintptr_t addr2, u
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the cheapest array index to extend with the given addr/mask pair.
|
* Determine if pattern is already covered by an existing pattern.
|
||||||
* Return -1 if nothing below the given minimum cost can be found.
|
* Return true if that's the case, else false.
|
||||||
*/
|
*/
|
||||||
static int cheap_index(uintptr_t addr1, uintptr_t mask1, uintptr_t min_cost)
|
static bool is_covered(pattern_t pattern)
|
||||||
{
|
{
|
||||||
int i = num_patterns;
|
for (int i = 0; i < num_patterns; i++) {
|
||||||
int idx = -1;
|
if (combi_cost(patterns[i].addr, patterns[i].mask, pattern.addr, pattern.mask) == 0) {
|
||||||
while (i-- > 0) {
|
return true;
|
||||||
uintptr_t tmp_cost = combi_cost(pattern[i].addr, pattern[i].mask, addr1, mask1);
|
}
|
||||||
if (tmp_cost < min_cost) {
|
}
|
||||||
|
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) {
|
||||||
min_cost = tmp_cost;
|
min_cost = tmp_cost;
|
||||||
idx = i;
|
merge_idx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return idx;
|
return merge_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to find a relocation index for idx if it costs nothing.
|
* Remove entries at idx and idx+1.
|
||||||
* Return -1 if no such index exists.
|
|
||||||
*/
|
*/
|
||||||
static int relocate_index(int idx)
|
static void remove_pair(int idx)
|
||||||
{
|
{
|
||||||
uintptr_t addr = pattern[idx].addr;
|
for (int i = idx; i < num_patterns - 2; i++) {
|
||||||
uintptr_t mask = pattern[idx].mask;
|
patterns[i] = patterns[i + 2];
|
||||||
pattern[idx].addr = ~pattern[idx].addr; // Never select idx
|
}
|
||||||
int new = cheap_index(addr, mask, 1 + addresses(mask));
|
patterns[num_patterns - 1].addr = 0u;
|
||||||
pattern[idx].addr = addr;
|
patterns[num_patterns - 1].mask = 0u;
|
||||||
return new;
|
patterns[num_patterns - 2].addr = 0u;
|
||||||
|
patterns[num_patterns - 2].mask = 0u;
|
||||||
|
num_patterns -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Relocate the given index idx only if free of charge.
|
* Get the combined entry of idx1 and idx2.
|
||||||
* This is useful to combine to `neighbouring' sections to integrate.
|
|
||||||
* Inspired on the Buddy memalloc principle in the Linux kernel.
|
|
||||||
*/
|
*/
|
||||||
static void relocate_if_free(int idx)
|
static pattern_t combined_pattern(int idx1, int idx2)
|
||||||
{
|
{
|
||||||
int newidx = relocate_index(idx);
|
pattern_t combined;
|
||||||
if (newidx >= 0) {
|
combine(
|
||||||
uintptr_t caddr, cmask;
|
patterns[idx1].addr,
|
||||||
combine(pattern[newidx].addr, pattern[newidx].mask,
|
patterns[idx1].mask,
|
||||||
pattern[ idx].addr, pattern[ idx].mask,
|
patterns[idx2].addr,
|
||||||
&caddr, &cmask);
|
patterns[idx2].mask,
|
||||||
pattern[newidx].addr = caddr;
|
&combined.addr,
|
||||||
pattern[newidx].mask = cmask;
|
&combined.mask
|
||||||
if (idx < --num_patterns) {
|
);
|
||||||
pattern[idx].addr = pattern[num_patterns].addr;
|
return combined;
|
||||||
pattern[idx].mask = pattern[num_patterns].mask;
|
}
|
||||||
}
|
|
||||||
relocate_if_free (newidx);
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
insert_at(pattern, new_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -165,26 +220,40 @@ static void relocate_if_free(int idx)
|
||||||
void badram_init(void)
|
void badram_init(void)
|
||||||
{
|
{
|
||||||
num_patterns = 0;
|
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)
|
bool badram_insert(uintptr_t addr)
|
||||||
{
|
{
|
||||||
if (cheap_index(addr, DEFAULT_MASK, 1) != -1) {
|
pattern_t pattern = {
|
||||||
|
.addr = addr,
|
||||||
|
.mask = DEFAULT_MASK
|
||||||
|
};
|
||||||
|
|
||||||
|
// If covered by existing entry we return immediately
|
||||||
|
if (is_covered(pattern)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_patterns < MAX_PATTERNS) {
|
// Add entry in order sorted by .addr asc
|
||||||
pattern[num_patterns].addr = addr;
|
insert_sorted(pattern);
|
||||||
pattern[num_patterns].mask = DEFAULT_MASK;
|
|
||||||
num_patterns++;
|
// If we have more patterns than the max we need to force a merge
|
||||||
relocate_if_free(num_patterns - 1);
|
if (num_patterns > MAX_PATTERNS) {
|
||||||
} else {
|
// Find the pair that is the cheapest to merge
|
||||||
int idx = cheap_index(addr, DEFAULT_MASK, UINTPTR_MAX);
|
// merge_idx will be -1 if num_patterns < 2, but that means MAX_PATTERNS = 0 which is not a valid state anyway
|
||||||
uintptr_t caddr, cmask;
|
int merge_idx = cheapest_pair();
|
||||||
combine(pattern[idx].addr, pattern[idx].mask, addr, DEFAULT_MASK, &caddr, &cmask);
|
|
||||||
pattern[idx].addr = caddr;
|
pattern_t combined = combined_pattern(merge_idx, merge_idx + 1);
|
||||||
pattern[idx].mask = cmask;
|
|
||||||
relocate_if_free(idx);
|
// 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);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -214,8 +283,8 @@ void badram_display(void)
|
||||||
col = 7;
|
col = 7;
|
||||||
}
|
}
|
||||||
display_scrolled_message(col, "0x%0*x,0x%0*x",
|
display_scrolled_message(col, "0x%0*x,0x%0*x",
|
||||||
TESTWORD_DIGITS, pattern[i].addr,
|
TESTWORD_DIGITS, patterns[i].addr,
|
||||||
TESTWORD_DIGITS, pattern[i].mask);
|
TESTWORD_DIGITS, patterns[i].mask);
|
||||||
col += text_width;
|
col += text_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
47
app/config.c
47
app/config.c
|
@ -91,6 +91,7 @@ bool exclude_ecores = true;
|
||||||
|
|
||||||
bool smp_enabled = true;
|
bool smp_enabled = true;
|
||||||
|
|
||||||
|
bool enable_big_status = true;
|
||||||
bool enable_temperature = true;
|
bool enable_temperature = true;
|
||||||
bool enable_trace = false;
|
bool enable_trace = false;
|
||||||
|
|
||||||
|
@ -174,7 +175,27 @@ static void parse_option(const char *option, const char *params)
|
||||||
{
|
{
|
||||||
if (option[0] == '\0') return;
|
if (option[0] == '\0') return;
|
||||||
|
|
||||||
if (strncmp(option, "keyboard", 9) == 0 && params != NULL) {
|
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(params, "legacy", 7) == 0) {
|
if (strncmp(params, "legacy", 7) == 0) {
|
||||||
keyboard_types = KT_LEGACY;
|
keyboard_types = KT_LEGACY;
|
||||||
} else if (strncmp(params, "usb", 4) == 0) {
|
} else if (strncmp(params, "usb", 4) == 0) {
|
||||||
|
@ -182,6 +203,18 @@ static void parse_option(const char *option, const char *params)
|
||||||
} else if (strncmp(params, "both", 5) == 0) {
|
} else if (strncmp(params, "both", 5) == 0) {
|
||||||
keyboard_types = KT_USB|KT_LEGACY;
|
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) {
|
} else if (strncmp(option, "powersave", 10) == 0) {
|
||||||
if (strncmp(params, "off", 4) == 0) {
|
if (strncmp(params, "off", 4) == 0) {
|
||||||
power_save = POWER_SAVE_OFF;
|
power_save = POWER_SAVE_OFF;
|
||||||
|
@ -190,16 +223,6 @@ static void parse_option(const char *option, const char *params)
|
||||||
} else if (strncmp(params, "high", 5) == 0) {
|
} else if (strncmp(params, "high", 5) == 0) {
|
||||||
power_save = POWER_SAVE_HIGH;
|
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) {
|
} else if (strncmp(option, "trace", 6) == 0) {
|
||||||
enable_trace = true;
|
enable_trace = true;
|
||||||
} else if (strncmp(option, "usbdebug", 9) == 0) {
|
} else if (strncmp(option, "usbdebug", 9) == 0) {
|
||||||
|
@ -212,8 +235,6 @@ static void parse_option(const char *option, const char *params)
|
||||||
} else if (strncmp(params, "3", 2) == 0) {
|
} else if (strncmp(params, "3", 2) == 0) {
|
||||||
usb_init_options |= USB_2_STEP_INIT|USB_EXTRA_RESET;
|
usb_init_options |= USB_2_STEP_INIT|USB_EXTRA_RESET;
|
||||||
}
|
}
|
||||||
} else if (strncmp(option, "nosm", 5) == 0) {
|
|
||||||
enable_sm = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ extern bool exclude_ecores;
|
||||||
|
|
||||||
extern bool smp_enabled;
|
extern bool smp_enabled;
|
||||||
|
|
||||||
|
extern bool enable_big_status;
|
||||||
extern bool enable_temperature;
|
extern bool enable_temperature;
|
||||||
extern bool enable_trace;
|
extern bool enable_trace;
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "githash.h"
|
#include "build_version.h"
|
||||||
|
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
|
|
||||||
static const char spin_state[NUM_SPIN_STATES] = { '|', '/', '-', '\\' };
|
static const char spin_state[NUM_SPIN_STATES] = { '|', '/', '-', '\\' };
|
||||||
|
|
||||||
static const char *cpu_mode_str[] = { "PAR", "SEQ", "RR " };
|
static const char cpu_mode_str[3][4] = { "PAR", "SEQ", "RR " };
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Private Variables
|
// Private Variables
|
||||||
|
@ -103,7 +103,7 @@ void display_init(void)
|
||||||
set_foreground_colour(BLACK);
|
set_foreground_colour(BLACK);
|
||||||
set_background_colour(WHITE);
|
set_background_colour(WHITE);
|
||||||
clear_screen_region(0, 0, 0, 27);
|
clear_screen_region(0, 0, 0, 27);
|
||||||
prints(0, 0, " Memtest86+ v6.01");
|
prints(0, 0, " Memtest86+ v" MT_VERSION);
|
||||||
set_foreground_colour(RED);
|
set_foreground_colour(RED);
|
||||||
printc(0, 15, '+');
|
printc(0, 15, '+');
|
||||||
set_foreground_colour(WHITE);
|
set_foreground_colour(WHITE);
|
||||||
|
@ -137,8 +137,7 @@ void display_init(void)
|
||||||
set_background_colour(WHITE);
|
set_background_colour(WHITE);
|
||||||
clear_screen_region(ROW_FOOTER, 0, ROW_FOOTER, SCREEN_WIDTH - 1);
|
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, 0, " <ESC> Exit <F1> Configuration <Space> Scroll Lock");
|
||||||
prints(ROW_FOOTER, 64, "6.01.");
|
prints(ROW_FOOTER, 64, MT_VERSION "." GIT_HASH);
|
||||||
prints(ROW_FOOTER, 69, GIT_HASH);
|
|
||||||
#if TESTWORD_WIDTH > 32
|
#if TESTWORD_WIDTH > 32
|
||||||
prints(ROW_FOOTER, 76, ".x64");
|
prints(ROW_FOOTER, 76, ".x64");
|
||||||
#else
|
#else
|
||||||
|
@ -356,7 +355,7 @@ void display_temperature(void)
|
||||||
|
|
||||||
void display_big_status(bool pass)
|
void display_big_status(bool pass)
|
||||||
{
|
{
|
||||||
if (big_status_displayed) {
|
if (!enable_big_status || big_status_displayed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,6 +409,7 @@ void check_input(void)
|
||||||
return;
|
return;
|
||||||
} else if (big_status_displayed) {
|
} else if (big_status_displayed) {
|
||||||
restore_big_status();
|
restore_big_status();
|
||||||
|
enable_big_status = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (input_key) {
|
switch (input_key) {
|
||||||
|
|
|
@ -251,10 +251,16 @@ static void global_init(void)
|
||||||
|
|
||||||
error_init();
|
error_init();
|
||||||
|
|
||||||
|
temperature_init();
|
||||||
|
|
||||||
initial_config();
|
initial_config();
|
||||||
|
|
||||||
clear_message_area();
|
clear_message_area();
|
||||||
|
|
||||||
|
if (!smp_enabled) {
|
||||||
|
num_available_cpus = 1;
|
||||||
|
}
|
||||||
|
|
||||||
num_enabled_cpus = 0;
|
num_enabled_cpus = 0;
|
||||||
for (int i = 0; i < num_available_cpus; i++) {
|
for (int i = 0; i < num_available_cpus; i++) {
|
||||||
if (cpu_state[i] == CPU_STATE_ENABLED) {
|
if (cpu_state[i] == CPU_STATE_ENABLED) {
|
||||||
|
@ -665,7 +671,8 @@ void main(void)
|
||||||
if (error_count == 0) {
|
if (error_count == 0) {
|
||||||
display_status("Pass ");
|
display_status("Pass ");
|
||||||
display_big_status(true);
|
display_big_status(true);
|
||||||
//display_notice("** Pass completed, no errors **");
|
} else {
|
||||||
|
display_big_status(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
app/version.h
Normal file
2
app/version.h
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#define MT_VERSION "6.20"
|
||||||
|
#define GIT_HASH "unknown"
|
|
@ -58,6 +58,7 @@ typedef struct {
|
||||||
|
|
||||||
#define VIDEO_TYPE_VLFB 0x23 // VESA VGA in graphic mode
|
#define VIDEO_TYPE_VLFB 0x23 // VESA VGA in graphic mode
|
||||||
#define VIDEO_TYPE_EFI 0x70 // EFI 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)
|
#define LFB_CAPABILITY_64BIT_BASE (1 << 1)
|
||||||
|
|
||||||
|
|
|
@ -334,9 +334,7 @@ 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);
|
efi_graphics_output_t *gop = find_gop(handles, handles_size);
|
||||||
if (!gop) {
|
if (!gop) {
|
||||||
#if DEBUG
|
print_string("No graphics display found\n");
|
||||||
print_string("GOP not found\n");
|
|
||||||
#endif
|
|
||||||
return EFI_NOT_FOUND;
|
return EFI_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,9 +363,7 @@ static efi_status_t set_screen_info_from_gop(screen_info_t *si, efi_handle_t *ha
|
||||||
efi_call_bs(free_pool, info);
|
efi_call_bs(free_pool, info);
|
||||||
}
|
}
|
||||||
if (best_mode == UINT32_MAX) {
|
if (best_mode == UINT32_MAX) {
|
||||||
#if DEBUG
|
print_string("No suitable screen resolution found\n");
|
||||||
print_string("No suitable GOP screen resolution\n");
|
|
||||||
#endif
|
|
||||||
return EFI_NOT_FOUND;
|
return EFI_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,9 +465,7 @@ 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);
|
status = efi_call_proto(gop, set_mode, best_mode);
|
||||||
if (status != EFI_SUCCESS) {
|
if (status != EFI_SUCCESS) {
|
||||||
#if DEBUG
|
|
||||||
print_string("Set GOP mode failed\n");
|
print_string("Set GOP mode failed\n");
|
||||||
#endif
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,7 +496,16 @@ static efi_status_t set_screen_info(boot_params_t *boot_params)
|
||||||
if (status == EFI_SUCCESS) {
|
if (status == EFI_SUCCESS) {
|
||||||
status = set_screen_info_from_gop(&boot_params->screen_info, handles, handles_size);
|
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);
|
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;
|
return status;
|
||||||
|
|
116
boot/header.S
116
boot/header.S
|
@ -7,7 +7,7 @@
|
||||||
// end of the boot sector), with the remainder of the header being provided by
|
// end of the boot sector), with the remainder of the header being provided by
|
||||||
// setup.S.
|
// setup.S.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2020 Martin Whitaker.
|
// Copyright (C) 2020-2023 Martin Whitaker.
|
||||||
//
|
//
|
||||||
// Derived from Linux 5.6 arch/x86/boot/header.S:
|
// Derived from Linux 5.6 arch/x86/boot/header.S:
|
||||||
//
|
//
|
||||||
|
@ -21,13 +21,13 @@
|
||||||
#define __ASSEMBLY__
|
#define __ASSEMBLY__
|
||||||
|
|
||||||
#include "boot.h"
|
#include "boot.h"
|
||||||
|
#include "peimage.h"
|
||||||
|
|
||||||
# The EFI loader loads the header at ImageBase, so we have to locate the main program
|
# 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
|
# 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.
|
# address well away from HIGH_LOAD_ADDR, to avoid overlap when relocating the code.
|
||||||
|
|
||||||
#define IMAGE_BASE 0x200000
|
#define IMAGE_BASE 0x200000
|
||||||
#define BASE_OF_CODE 0x1000
|
|
||||||
|
|
||||||
.section ".header", "ax", @progbits
|
.section ".header", "ax", @progbits
|
||||||
.code16
|
.code16
|
||||||
|
@ -85,50 +85,46 @@ pe_header:
|
||||||
|
|
||||||
coff_header:
|
coff_header:
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
.word 0x8664 # Machine (x86-64)
|
.word IMAGE_FILE_MACHINE_X64 # Machine (x86-64)
|
||||||
#else
|
#else
|
||||||
.word 0x14c # Machine (i386)
|
.word IMAGE_FILE_MACHINE_I386 # Machine (i386)
|
||||||
#endif
|
#endif
|
||||||
.word 1 # NumberOfSections
|
.word 3 # NumberOfSections
|
||||||
.long 0 # TimeDateStamp
|
.long 0 # TimeDateStamp
|
||||||
.long 0 # PointerToSymbolTable
|
.long 0 # PointerToSymbolTable
|
||||||
.long 0 # NumberOfSymbols
|
.long 0 # NumberOfSymbols
|
||||||
.word section_table - optional_header # SizeOfOptionalHeader
|
.word section_table - optional_header # SizeOfOptionalHeader
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
.word 0x20f # Characteristics
|
.word IMAGE_FILE_DEBUG_STRIPPED \
|
||||||
# IMAGE_FILE_DEBUG_STRIPPED |
|
| IMAGE_FILE_LOCAL_SYMS_STRIPPED \
|
||||||
# IMAGE_FILE_LOCAL_SYMS_STRIPPED |
|
| IMAGE_FILE_LINE_NUMS_STRIPPED \
|
||||||
# IMAGE_FILE_LINE_NUMS_STRIPPED |
|
| IMAGE_FILE_EXECUTABLE_IMAGE # Characteristics
|
||||||
# IMAGE_FILE_EXECUTABLE_IMAGE |
|
|
||||||
# IMAGE_FILE_RELOCS_STRIPPED
|
|
||||||
#else
|
#else
|
||||||
.word 0x30f # Characteristics.
|
.word IMAGE_FILE_32BIT_MACHINE \
|
||||||
# IMAGE_FILE_32BIT_MACHINE |
|
| IMAGE_FILE_DEBUG_STRIPPED \
|
||||||
# IMAGE_FILE_DEBUG_STRIPPED |
|
| IMAGE_FILE_LOCAL_SYMS_STRIPPED \
|
||||||
# IMAGE_FILE_LOCAL_SYMS_STRIPPED |
|
| IMAGE_FILE_LINE_NUMS_STRIPPED \
|
||||||
# IMAGE_FILE_LINE_NUMS_STRIPPED |
|
| IMAGE_FILE_EXECUTABLE_IMAGE # Characteristics.
|
||||||
# IMAGE_FILE_EXECUTABLE_IMAGE |
|
|
||||||
# IMAGE_FILE_RELOCS_STRIPPED
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
optional_header:
|
optional_header:
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
.word 0x20b # PE32+ format
|
.word IMAGE_NT_OPTIONAL_HDR64_MAGIC # PE32+ format
|
||||||
#else
|
#else
|
||||||
.word 0x10b # PE32 format
|
.word IMAGE_NT_OPTIONAL_HDR32_MAGIC # PE32 format
|
||||||
#endif
|
#endif
|
||||||
.byte 0x02 # MajorLinkerVersion
|
.byte 0x02 # MajorLinkerVersion
|
||||||
.byte 0x14 # MinorLinkerVersion
|
.byte 0x14 # MinorLinkerVersion
|
||||||
|
|
||||||
.long _text_size # SizeOfCode
|
.long _virt_text_size # SizeOfCode
|
||||||
.long 0 # SizeOfInitializedData
|
.long _virt_sbat_size # SizeOfInitializedData
|
||||||
.long 0 # SizeOfUninitializedData
|
.long 0 # SizeOfUninitializedData
|
||||||
|
|
||||||
.long BASE_OF_CODE + 0x1e0 # AddressOfEntryPoint
|
.long _virt_text_start + 0x1e0 # AddressOfEntryPoint
|
||||||
|
|
||||||
.long BASE_OF_CODE # BaseOfCode
|
.long _virt_text_start # BaseOfCode
|
||||||
#ifndef __x86_64__
|
#ifndef __x86_64__
|
||||||
.long 0 # data
|
.long _virt_sbat_start # BaseOfData
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extra_header_fields:
|
extra_header_fields:
|
||||||
|
@ -147,8 +143,8 @@ extra_header_fields:
|
||||||
.word 0 # MinorSubsystemVersion
|
.word 0 # MinorSubsystemVersion
|
||||||
.long 0 # Win32VersionValue
|
.long 0 # Win32VersionValue
|
||||||
|
|
||||||
.long BASE_OF_CODE + _init_size # SizeOfImage
|
.long _virt_img_size # SizeOfImage
|
||||||
.long 512 # SizeOfHeaders
|
.long _file_head_size # SizeOfHeaders
|
||||||
.long 0 # CheckSum
|
.long 0 # CheckSum
|
||||||
.word 10 # Subsystem (EFI application)
|
.word 10 # Subsystem (EFI application)
|
||||||
.word 0 # DllCharacteristics
|
.word 0 # DllCharacteristics
|
||||||
|
@ -164,7 +160,20 @@ extra_header_fields:
|
||||||
.long 0 # SizeOfHeapCommit
|
.long 0 # SizeOfHeapCommit
|
||||||
#endif
|
#endif
|
||||||
.long 0 # LoaderFlags
|
.long 0 # LoaderFlags
|
||||||
.long 0 # NumberOfRvaAndSizes
|
.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
|
||||||
|
|
||||||
# Section table
|
# Section table
|
||||||
section_table:
|
section_table:
|
||||||
|
@ -172,15 +181,46 @@ section_table:
|
||||||
.byte 0
|
.byte 0
|
||||||
.byte 0
|
.byte 0
|
||||||
.byte 0
|
.byte 0
|
||||||
.long _text_size # VirtualSize
|
.long _virt_text_size # VirtualSize
|
||||||
.long BASE_OF_CODE # VirtualAddress
|
.long _virt_text_start # VirtualAddress
|
||||||
.long _text_size # SizeOfRawData
|
.long _file_text_size # SizeOfRawData
|
||||||
.long _text_start # PointerToRawData
|
.long _file_text_start # PointerToRawData
|
||||||
.long 0 # PointerToRelocations
|
.long 0 # PointerToRelocations
|
||||||
.long 0 # PointerToLineNumbers
|
.long 0 # PointerToLineNumbers
|
||||||
.word 0 # NumberOfRelocations
|
.word 0 # NumberOfRelocations
|
||||||
.word 0 # NumberOfLineNumbers
|
.word 0 # NumberOfLineNumbers
|
||||||
.long 0x60500020 # Characteristics (section flags)
|
.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)
|
||||||
|
|
||||||
# Emulate the Linux boot header, to allow loading by intermediate boot loaders.
|
# Emulate the Linux boot header, to allow loading by intermediate boot loaders.
|
||||||
|
|
||||||
|
@ -199,3 +239,13 @@ root_dev:
|
||||||
.word 0
|
.word 0
|
||||||
boot_flag:
|
boot_flag:
|
||||||
.word 0xAA55
|
.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"
|
||||||
|
|
292
boot/peimage.h
Normal file
292
boot/peimage.h
Normal file
|
@ -0,0 +1,292 @@
|
||||||
|
// 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 */
|
2
boot/sbat.csv
Normal file
2
boot/sbat.csv
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
|
||||||
|
memtest86+,1,Memtest86+,6.0,https://github.com/memtest86plus
|
|
|
@ -18,6 +18,7 @@
|
||||||
#define __ASSEMBLY__
|
#define __ASSEMBLY__
|
||||||
|
|
||||||
#include "boot.h"
|
#include "boot.h"
|
||||||
|
#include "build_version.h"
|
||||||
|
|
||||||
#define BOOT_PARAMS_START (SETUP_SECS * 512)
|
#define BOOT_PARAMS_START (SETUP_SECS * 512)
|
||||||
#define BOOT_PARAMS_END (BOOT_PARAMS_START + 4096)
|
#define BOOT_PARAMS_END (BOOT_PARAMS_START + 4096)
|
||||||
|
@ -41,7 +42,7 @@ realmode_swtch:
|
||||||
start_sys_seg:
|
start_sys_seg:
|
||||||
.word 0x1000
|
.word 0x1000
|
||||||
kernel_version:
|
kernel_version:
|
||||||
.word 0
|
.word mt86plus_version-512
|
||||||
type_of_loader:
|
type_of_loader:
|
||||||
.byte 0
|
.byte 0
|
||||||
loadflags:
|
loadflags:
|
||||||
|
@ -385,6 +386,10 @@ idt_descr:
|
||||||
.word 0 # idt limit=0
|
.word 0 # idt limit=0
|
||||||
.long 0 # idt base=0
|
.long 0 # idt base=0
|
||||||
|
|
||||||
|
mt86plus_version:
|
||||||
|
.ascii "Memtest86+ v" , MT_VERSION
|
||||||
|
.byte 0
|
||||||
|
|
||||||
# Pad to the declared size.
|
# Pad to the declared size.
|
||||||
|
|
||||||
.org (SETUP_SECS*512)
|
.org (SETUP_SECS*512)
|
||||||
|
|
|
@ -812,7 +812,7 @@ startup_stack_top:
|
||||||
|
|
||||||
# Main stack area.
|
# Main stack area.
|
||||||
|
|
||||||
.section "stacks", "aw", @progbits
|
.section ".stacks", "aw", @nobits
|
||||||
.align 16
|
.align 16
|
||||||
|
|
||||||
. = . + STACKS_SIZE
|
. = . + STACKS_SIZE
|
||||||
|
|
|
@ -75,16 +75,15 @@ all: memtest.bin memtest.efi
|
||||||
-include $(subst .o,.d,$(TST_OBJS))
|
-include $(subst .o,.d,$(TST_OBJS))
|
||||||
-include $(subst .o,.d,$(APP_OBJS))
|
-include $(subst .o,.d,$(APP_OBJS))
|
||||||
|
|
||||||
boot/%.o: boot/%.s
|
boot/header.o : | ../boot/sbat.csv
|
||||||
$(AS) $< -o $@
|
|
||||||
|
|
||||||
boot/startup.s: ../boot/startup32.S ../boot/boot.h
|
boot/startup.o: ../boot/startup32.S ../boot/boot.h
|
||||||
@mkdir -p boot
|
@mkdir -p boot
|
||||||
$(CC) -m32 -E -traditional -I../boot -o $@ $<
|
$(CC) -m32 -x assembler-with-cpp -c -I../boot -o $@ $<
|
||||||
|
|
||||||
boot/%.s: ../boot/%.S ../boot/boot.h
|
boot/%.o: ../boot/%.S ../boot/boot.h app/build_version.h
|
||||||
@mkdir -p boot
|
@mkdir -p boot
|
||||||
$(CC) -m32 -E -traditional -I../boot -o $@ $<
|
$(CC) -m32 -x assembler-with-cpp -c -I../boot -Iapp -o $@ $<
|
||||||
|
|
||||||
boot/efisetup.o: ../boot/efisetup.c
|
boot/efisetup.o: ../boot/efisetup.c
|
||||||
@mkdir -p boot
|
@mkdir -p boot
|
||||||
|
@ -106,20 +105,22 @@ tests/%.o: ../tests/%.c
|
||||||
@mkdir -p tests
|
@mkdir -p tests
|
||||||
$(CC) -c $(CFLAGS) -O3 $(INC_DIRS) -o $@ $< -MMD -MP -MT $@ -MF $(@:.o=.d)
|
$(CC) -c $(CFLAGS) -O3 $(INC_DIRS) -o $@ $< -MMD -MP -MT $@ -MF $(@:.o=.d)
|
||||||
|
|
||||||
app/%.o: ../app/%.c app/githash.h
|
app/%.o: ../app/%.c app/build_version.h
|
||||||
@mkdir -p app
|
@mkdir -p app
|
||||||
$(CC) -c $(CFLAGS) -Os $(INC_DIRS) -o $@ $< -MMD -MP -MT $@ -MF $(@:.o=.d)
|
$(CC) -c $(CFLAGS) -Os $(INC_DIRS) -o $@ $< -MMD -MP -MT $@ -MF $(@:.o=.d)
|
||||||
|
|
||||||
app/githash.h: FORCE
|
app/build_version.h: FORCE
|
||||||
@mkdir -p app
|
@mkdir -p app
|
||||||
@( \
|
@( \
|
||||||
|
cp -f ../app/version.h $@.tmp; \
|
||||||
if $(GIT_AVAILABLE) && test -d ../.git ; then \
|
if $(GIT_AVAILABLE) && test -d ../.git ; then \
|
||||||
hash=`git rev-parse HEAD | cut -c1-7`; \
|
hash=`git rev-parse HEAD | cut -c1-7`; \
|
||||||
|
sed -i 's/GIT_HASH\s\".*"/GIT_HASH "'$$hash'"/' $@.tmp; \
|
||||||
else \
|
else \
|
||||||
hash="unknown"; \
|
sed -i 's/GIT_HASH\s\".*"/GIT_HASH "unknown"/' $@.tmp; \
|
||||||
fi; \
|
fi; \
|
||||||
define=`echo "#define GIT_HASH \"$$hash\""`; \
|
cmp $@ $@.tmp 2>/dev/null || cp -f $@.tmp $@; \
|
||||||
echo $$define | diff - $@ > /dev/null 2>&1 || echo $$define > $@; \
|
rm -f $@.tmp; \
|
||||||
)
|
)
|
||||||
|
|
||||||
FORCE:
|
FORCE:
|
||||||
|
|
|
@ -12,15 +12,48 @@ SECTIONS {
|
||||||
}
|
}
|
||||||
. = ALIGN(512);
|
. = ALIGN(512);
|
||||||
.text : {
|
.text : {
|
||||||
_text_start = . ;
|
_file_text_start = . ;
|
||||||
*(.data)
|
*(.data)
|
||||||
|
_real_text_end = . ;
|
||||||
. = ALIGN(512);
|
. = ALIGN(512);
|
||||||
_text_end = . ;
|
_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 = . ;
|
||||||
}
|
}
|
||||||
/DISCARD/ : { *(*) }
|
/DISCARD/ : { *(*) }
|
||||||
|
|
||||||
_text_size = (_text_end - _text_start);
|
_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;
|
||||||
|
|
||||||
_sys_size = _text_size >> 4;
|
_file_head_size = _file_text_start;
|
||||||
_init_size = _text_size + _bss_size;
|
_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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,16 +74,15 @@ all: memtest.bin memtest.efi
|
||||||
-include $(subst .o,.d,$(TST_OBJS))
|
-include $(subst .o,.d,$(TST_OBJS))
|
||||||
-include $(subst .o,.d,$(APP_OBJS))
|
-include $(subst .o,.d,$(APP_OBJS))
|
||||||
|
|
||||||
boot/%.o: boot/%.s
|
boot/header.o : | ../boot/sbat.csv
|
||||||
$(AS) $< -o $@
|
|
||||||
|
|
||||||
boot/startup.s: ../boot/startup64.S ../boot/boot.h
|
boot/startup.o: ../boot/startup64.S ../boot/boot.h
|
||||||
@mkdir -p boot
|
@mkdir -p boot
|
||||||
$(CC) -E -traditional -I../boot -o $@ $<
|
$(CC) -m64 -x assembler-with-cpp -c -I../boot -o $@ $<
|
||||||
|
|
||||||
boot/%.s: ../boot/%.S ../boot/boot.h
|
boot/%.o: ../boot/%.S ../boot/boot.h app/build_version.h
|
||||||
@mkdir -p boot
|
@mkdir -p boot
|
||||||
$(CC) -E -traditional -I../boot -o $@ $<
|
$(CC) -m64 -x assembler-with-cpp -c -I../boot -Iapp -o $@ $<
|
||||||
|
|
||||||
boot/efisetup.o: ../boot/efisetup.c
|
boot/efisetup.o: ../boot/efisetup.c
|
||||||
@mkdir -p boot
|
@mkdir -p boot
|
||||||
|
@ -105,20 +104,22 @@ tests/%.o: ../tests/%.c
|
||||||
@mkdir -p tests
|
@mkdir -p tests
|
||||||
$(CC) -c $(CFLAGS) -O3 $(INC_DIRS) -o $@ $< -MMD -MP -MT $@ -MF $(@:.o=.d)
|
$(CC) -c $(CFLAGS) -O3 $(INC_DIRS) -o $@ $< -MMD -MP -MT $@ -MF $(@:.o=.d)
|
||||||
|
|
||||||
app/%.o: ../app/%.c app/githash.h
|
app/%.o: ../app/%.c app/build_version.h
|
||||||
@mkdir -p app
|
@mkdir -p app
|
||||||
$(CC) -c $(CFLAGS) -Os $(INC_DIRS) -o $@ $< -MMD -MP -MT $@ -MF $(@:.o=.d)
|
$(CC) -c $(CFLAGS) -Os $(INC_DIRS) -o $@ $< -MMD -MP -MT $@ -MF $(@:.o=.d)
|
||||||
|
|
||||||
app/githash.h: FORCE
|
app/build_version.h: FORCE
|
||||||
@mkdir -p app
|
@mkdir -p app
|
||||||
@( \
|
@( \
|
||||||
|
cp -f ../app/version.h $@.tmp; \
|
||||||
if $(GIT_AVAILABLE) && test -d ../.git ; then \
|
if $(GIT_AVAILABLE) && test -d ../.git ; then \
|
||||||
hash=`git rev-parse HEAD | cut -c1-7`; \
|
hash=`git rev-parse HEAD | cut -c1-7`; \
|
||||||
|
sed -i 's/GIT_HASH\s\".*"/GIT_HASH "'$$hash'"/' $@.tmp; \
|
||||||
else \
|
else \
|
||||||
hash="unknown"; \
|
sed -i 's/GIT_HASH\s\".*"/GIT_HASH "unknown"/' $@.tmp; \
|
||||||
fi; \
|
fi; \
|
||||||
define=`echo "#define GIT_HASH \"$$hash\""`; \
|
cmp $@ $@.tmp 2>/dev/null || cp -f $@.tmp $@; \
|
||||||
echo $$define | diff - $@ > /dev/null 2>&1 || echo $$define > $@; \
|
rm -f $@.tmp; \
|
||||||
)
|
)
|
||||||
|
|
||||||
FORCE:
|
FORCE:
|
||||||
|
|
|
@ -12,15 +12,48 @@ SECTIONS {
|
||||||
}
|
}
|
||||||
. = ALIGN(512);
|
. = ALIGN(512);
|
||||||
.text : {
|
.text : {
|
||||||
_text_start = . ;
|
_file_text_start = . ;
|
||||||
*(.data)
|
*(.data)
|
||||||
|
_real_text_end = . ;
|
||||||
. = ALIGN(512);
|
. = ALIGN(512);
|
||||||
_text_end = . ;
|
_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 = . ;
|
||||||
}
|
}
|
||||||
/DISCARD/ : { *(*) }
|
/DISCARD/ : { *(*) }
|
||||||
|
|
||||||
_text_size = (_text_end - _text_start);
|
_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;
|
||||||
|
|
||||||
_sys_size = _text_size >> 4;
|
_file_head_size = _file_text_start;
|
||||||
_init_size = _text_size + _bss_size;
|
_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;
|
||||||
}
|
}
|
||||||
|
|
34
lib/string.c
34
lib/string.c
|
@ -31,18 +31,6 @@ void reverse(char s[])
|
||||||
// Public Functions
|
// 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)
|
void *memmove(void *dest, const void *src, size_t n)
|
||||||
{
|
{
|
||||||
char *d = (char *)dest, *s = (char *)src;
|
char *d = (char *)dest, *s = (char *)src;
|
||||||
|
@ -64,28 +52,6 @@ void *memmove(void *dest, const void *src, size_t n)
|
||||||
return dest;
|
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)
|
char *strstr(const char *haystack, const char *needle)
|
||||||
{
|
{
|
||||||
size_t haystack_len = strlen(haystack);
|
size_t haystack_len = strlen(haystack);
|
||||||
|
|
34
lib/string.h
34
lib/string.h
|
@ -18,7 +18,17 @@
|
||||||
* between the first mismatching byte in s1 (interpreted as an unsigned
|
* between the first mismatching byte in s1 (interpreted as an unsigned
|
||||||
* value) and the corresponding byte in s2.
|
* value) and the corresponding byte in s2.
|
||||||
*/
|
*/
|
||||||
int memcmp(const void *s1, const void *s2, size_t n);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies n bytes from the memory area pointed to by src to the memory area
|
* Copies n bytes from the memory area pointed to by src to the memory area
|
||||||
|
@ -45,7 +55,14 @@ void *memmove(void *dest, const void *src, size_t n);
|
||||||
/**
|
/**
|
||||||
* Returns the string length, excluding the terminating null character.
|
* Returns the string length, excluding the terminating null character.
|
||||||
*/
|
*/
|
||||||
size_t strlen(const char *s);
|
static inline size_t strlen(const char *s)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
while (*s++) {
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares at most the first n characters in the strings s1 and s2 and
|
* Compares at most the first n characters in the strings s1 and s2 and
|
||||||
|
@ -53,7 +70,18 @@ size_t strlen(const char *s);
|
||||||
* between the first mismatching character in s1 (interpreted as a signed
|
* between the first mismatching character in s1 (interpreted as a signed
|
||||||
* value) and the corresponding character in s2.
|
* value) and the corresponding character in s2.
|
||||||
*/
|
*/
|
||||||
int strncmp(const char *s1, const char *s2, size_t n);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the first occurrence of the substring needle in the string haystack
|
* Finds the first occurrence of the substring needle in the string haystack
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//
|
//
|
||||||
// Derived from memtest86+ cpuid.h
|
// Derived from memtest86+ cpuid.h
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "cpuid.h"
|
#include "cpuid.h"
|
||||||
|
@ -36,7 +36,7 @@ void cpuid_init(void)
|
||||||
// Get the processor family information & feature flags.
|
// Get the processor family information & feature flags.
|
||||||
if (cpuid_info.max_cpuid >= 1) {
|
if (cpuid_info.max_cpuid >= 1) {
|
||||||
cpuid(0x1, 0,
|
cpuid(0x1, 0,
|
||||||
&cpuid_info.version.raw,
|
&cpuid_info.version.raw[0],
|
||||||
&cpuid_info.proc_info.raw,
|
&cpuid_info.proc_info.raw,
|
||||||
&cpuid_info.flags.raw[1],
|
&cpuid_info.flags.raw[1],
|
||||||
&cpuid_info.flags.raw[0]
|
&cpuid_info.flags.raw[0]
|
||||||
|
@ -65,8 +65,8 @@ void cpuid_init(void)
|
||||||
if (cpuid_info.max_xcpuid >= 0x80000001) {
|
if (cpuid_info.max_xcpuid >= 0x80000001) {
|
||||||
cpuid(0x80000001, 0,
|
cpuid(0x80000001, 0,
|
||||||
®[0],
|
®[0],
|
||||||
|
&cpuid_info.version.raw[1],
|
||||||
®[1],
|
®[1],
|
||||||
®[2],
|
|
||||||
&cpuid_info.flags.raw[2]
|
&cpuid_info.flags.raw[2]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -108,30 +108,21 @@ void cpuid_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get cache information.
|
// Get cache information.
|
||||||
switch (cpuid_info.vendor_id.str[0]) {
|
if (cpuid_info.max_xcpuid >= 0x80000005) {
|
||||||
case 'A':
|
cpuid(0x80000005, 0,
|
||||||
// AMD Processors
|
®[0],
|
||||||
if (cpuid_info.max_xcpuid >= 0x80000005) {
|
®[1],
|
||||||
cpuid(0x80000005, 0,
|
&cpuid_info.cache_info.raw[0],
|
||||||
®[0],
|
&cpuid_info.cache_info.raw[1]
|
||||||
®[1],
|
);
|
||||||
&cpuid_info.cache_info.raw[0],
|
}
|
||||||
&cpuid_info.cache_info.raw[1]
|
if (cpuid_info.max_xcpuid >= 0x80000006) {
|
||||||
);
|
cpuid(0x80000006, 0,
|
||||||
}
|
®[0],
|
||||||
if (cpuid_info.max_xcpuid >= 0x80000006) {
|
®[1],
|
||||||
cpuid(0x80000006, 0,
|
&cpuid_info.cache_info.raw[2],
|
||||||
®[0],
|
&cpuid_info.cache_info.raw[3]
|
||||||
®[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
|
// Detect CPU Topology (Core/Thread) infos
|
||||||
|
@ -176,7 +167,8 @@ void cpuid_init(void)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
// VIA / CentaurHauls
|
// Cyrix / VIA / CentaurHauls / Zhaoxin
|
||||||
|
cpuid_info.flags.htt = false;
|
||||||
break;
|
break;
|
||||||
case 'G':
|
case 'G':
|
||||||
if (cpuid_info.vendor_id.str[7] == 'T') break; // Transmeta
|
if (cpuid_info.vendor_id.str[7] == 'T') break; // Transmeta
|
||||||
|
|
|
@ -29,7 +29,7 @@ typedef enum {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
uint32_t raw;
|
uint32_t raw[2];
|
||||||
struct {
|
struct {
|
||||||
uint32_t stepping : 4;
|
uint32_t stepping : 4;
|
||||||
uint32_t model : 4;
|
uint32_t model : 4;
|
||||||
|
@ -39,6 +39,7 @@ typedef union {
|
||||||
uint32_t extendedModel : 4;
|
uint32_t extendedModel : 4;
|
||||||
uint32_t extendedFamily : 8;
|
uint32_t extendedFamily : 8;
|
||||||
uint32_t : 4;
|
uint32_t : 4;
|
||||||
|
uint32_t extendedBrandID : 32; // AMD Only
|
||||||
};
|
};
|
||||||
} cpuid_version_t;
|
} cpuid_version_t;
|
||||||
|
|
||||||
|
@ -122,7 +123,7 @@ typedef union {
|
||||||
} cpuid_brand_string_t;
|
} cpuid_brand_string_t;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
uint32_t raw[12];
|
uint32_t raw[4];
|
||||||
struct {
|
struct {
|
||||||
uint32_t : 24;
|
uint32_t : 24;
|
||||||
uint32_t l1_i_size : 8;
|
uint32_t l1_i_size : 8;
|
||||||
|
|
162
system/cpuinfo.c
162
system/cpuinfo.c
|
@ -71,12 +71,45 @@ static void determine_cache_size()
|
||||||
l3_cache *= 512;
|
l3_cache *= 512;
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
// Zhaoxin CPU only
|
if (cpuid_info.vendor_id.str[5] == 'I') {
|
||||||
if (cpuid_info.version.family != 7) {
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
|
// Zhaoxin CPU only
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 'G':
|
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
|
// Intel Processors
|
||||||
l1_cache = 0;
|
l1_cache = 0;
|
||||||
l2_cache = 0;
|
l2_cache = 0;
|
||||||
|
@ -460,6 +493,9 @@ static void determine_imc(void)
|
||||||
case 0x9:
|
case 0x9:
|
||||||
imc_type = IMC_KBL; // Core 7/8/9th Gen (Kaby/Coffee/Comet Lake)
|
imc_type = IMC_KBL; // Core 7/8/9th Gen (Kaby/Coffee/Comet Lake)
|
||||||
break;
|
break;
|
||||||
|
case 0xB:
|
||||||
|
imc_type = IMC_ADL_N; // Core 12th Gen (Alder Lake-N - Gracemont E-Cores only)
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -599,9 +635,9 @@ static void determine_cpu_model(void)
|
||||||
// Transmeta Processors - vendor_id starts with "GenuineTMx86"
|
// Transmeta Processors - vendor_id starts with "GenuineTMx86"
|
||||||
if (cpuid_info.vendor_id.str[7] == 'T' ) {
|
if (cpuid_info.vendor_id.str[7] == 'T' ) {
|
||||||
if (cpuid_info.version.family == 5) {
|
if (cpuid_info.version.family == 5) {
|
||||||
cpu_model = "TM 5x00";
|
cpu_model = "Transmeta TM 5x00";
|
||||||
} else if (cpuid_info.version.family == 15) {
|
} else if (cpuid_info.version.family == 15) {
|
||||||
cpu_model = "TM 8x00";
|
cpu_model = "Transmeta TM 8x00";
|
||||||
}
|
}
|
||||||
l1_cache = cpuid_info.cache_info.l1_i_size + cpuid_info.cache_info.l1_d_size;
|
l1_cache = cpuid_info.cache_info.l1_i_size + cpuid_info.cache_info.l1_d_size;
|
||||||
l2_cache = cpuid_info.cache_info.l2_size;
|
l2_cache = cpuid_info.cache_info.l2_size;
|
||||||
|
@ -647,14 +683,14 @@ static void determine_cpu_model(void)
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
case 7:
|
case 7:
|
||||||
cpu_model = "Pentium";
|
cpu_model = "Intel Pentium";
|
||||||
if (l1_cache == 0) {
|
if (l1_cache == 0) {
|
||||||
l1_cache = 8;
|
l1_cache = 8;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
case 8:
|
case 8:
|
||||||
cpu_model = "Pentium-MMX";
|
cpu_model = "Intel Pentium MMX";
|
||||||
if (l1_cache == 0) {
|
if (l1_cache == 0) {
|
||||||
l1_cache = 16;
|
l1_cache = 16;
|
||||||
}
|
}
|
||||||
|
@ -667,54 +703,54 @@ static void determine_cpu_model(void)
|
||||||
switch (cpuid_info.version.model) {
|
switch (cpuid_info.version.model) {
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
cpu_model = "Pentium Pro";
|
cpu_model = "Intel Pentium Pro";
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
cpu_model = "Pentium II";
|
cpu_model = "Intel Pentium II";
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
if (l2_cache == 0) {
|
if (l2_cache == 0) {
|
||||||
cpu_model = "Celeron";
|
cpu_model = "Intel Celeron";
|
||||||
} else {
|
} else {
|
||||||
cpu_model = "Pentium II";
|
cpu_model = "Intel Pentium II";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
if (l2_cache == 128) {
|
if (l2_cache == 128) {
|
||||||
cpu_model = "Celeron";
|
cpu_model = "Intel Celeron";
|
||||||
} else {
|
} else {
|
||||||
cpu_model = "Pentium II";
|
cpu_model = "Intel Pentium II";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
case 8:
|
case 8:
|
||||||
case 11:
|
case 11:
|
||||||
if (l2_cache == 128) {
|
if (l2_cache == 128) {
|
||||||
cpu_model = "Celeron";
|
cpu_model = "Intel Celeron";
|
||||||
} else {
|
} else {
|
||||||
cpu_model = "Pentium III";
|
cpu_model = "Intel Pentium III";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
if (l2_cache == 512) {
|
if (l2_cache == 512) {
|
||||||
cpu_model = "Celeron M (0.13)";
|
cpu_model = "Intel Celeron M (0.13)";
|
||||||
} else {
|
} else {
|
||||||
cpu_model = "Pentium M (0.13)";
|
cpu_model = "Intel Pentium M (0.13)";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
cpu_model = "Pentium III Xeon";
|
cpu_model = "Intel Pentium III Xeon";
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
l1_cache = 24;
|
l1_cache = 24;
|
||||||
cpu_model = "Atom (0.045)";
|
cpu_model = "Intel Atom (0.045)";
|
||||||
break;
|
break;
|
||||||
case 13:
|
case 13:
|
||||||
if (l2_cache == 1024) {
|
if (l2_cache == 1024) {
|
||||||
cpu_model = "Celeron M (0.09)";
|
cpu_model = "Intel Celeron M (0.09)";
|
||||||
} else {
|
} else {
|
||||||
cpu_model = "Pentium M (0.09)";
|
cpu_model = "Intel Pentium M (0.09)";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 14:
|
case 14:
|
||||||
|
@ -722,7 +758,7 @@ static void determine_cpu_model(void)
|
||||||
break;
|
break;
|
||||||
case 15:
|
case 15:
|
||||||
if (l2_cache == 1024) {
|
if (l2_cache == 1024) {
|
||||||
cpu_model = "Pentium E";
|
cpu_model = "Intel Pentium E";
|
||||||
} else {
|
} else {
|
||||||
cpu_model = "Intel Core 2";
|
cpu_model = "Intel Core 2";
|
||||||
}
|
}
|
||||||
|
@ -737,17 +773,17 @@ static void determine_cpu_model(void)
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
if (l2_cache == 128) {
|
if (l2_cache == 128) {
|
||||||
cpu_model = "Celeron";
|
cpu_model = "Intel Celeron";
|
||||||
} else {
|
} else {
|
||||||
cpu_model = "Pentium 4";
|
cpu_model = "Intel Pentium 4";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
if (l2_cache == 256) {
|
if (l2_cache == 256) {
|
||||||
cpu_model = "Celeron (0.09)";
|
cpu_model = "Intel Celeron (0.09)";
|
||||||
} else {
|
} else {
|
||||||
cpu_model = "Pentium 4 (0.09)";
|
cpu_model = "Intel Pentium 4 (0.09)";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
|
@ -767,78 +803,40 @@ static void determine_cpu_model(void)
|
||||||
// VIA/Cyrix/Centaur Processors with CPUID
|
// VIA/Cyrix/Centaur Processors with CPUID
|
||||||
if (cpuid_info.vendor_id.str[1] == 'e' ) {
|
if (cpuid_info.vendor_id.str[1] == 'e' ) {
|
||||||
// CentaurHauls
|
// 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) {
|
switch (cpuid_info.version.family) {
|
||||||
case 5:
|
case 5:
|
||||||
cpu_model = "Centaur 5x86";
|
cpu_model = "IDT WinChip C6";
|
||||||
|
l1_cache = 32;
|
||||||
|
// WinChip 2/3 (models 8/9) have brand string
|
||||||
break;
|
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:
|
default:
|
||||||
|
// All VIA/Centaur family values >= 6 have brand string
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else { /* CyrixInstead */
|
} else { /* CyrixInstead */
|
||||||
switch (cpuid_info.version.family) {
|
switch (cpuid_info.version.family) {
|
||||||
case 5:
|
case 4:
|
||||||
switch (cpuid_info.version.model) {
|
switch (cpuid_info.version.model) {
|
||||||
case 0:
|
case 2:
|
||||||
cpu_model = "Cyrix 6x86MX/MII";
|
cpu_model = "Cyrix 5x86";
|
||||||
|
l1_cache = 16;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
cpu_model = "Cyrix GXm";
|
cpu_model = "Cyrix MediaGX/GXi";
|
||||||
|
l1_cache = 16;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6: // VIA C3
|
case 5:
|
||||||
switch (cpuid_info.version.model) {
|
cpu_model = "Cyrix 6x86/6x86L";
|
||||||
case 6:
|
l1_cache = 16;
|
||||||
cpu_model = "Cyrix III";
|
// Media GXm (model 4) has brand string
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 6:
|
||||||
if (cpuid_info.version.stepping < 8) {
|
cpu_model = "Cyrix 6x86MX/MII";
|
||||||
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;
|
l1_cache = 64;
|
||||||
l2_cache = 64;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -849,10 +847,10 @@ static void determine_cpu_model(void)
|
||||||
// Unknown processor - make a guess at the family.
|
// Unknown processor - make a guess at the family.
|
||||||
switch (cpuid_info.version.family) {
|
switch (cpuid_info.version.family) {
|
||||||
case 5:
|
case 5:
|
||||||
cpu_model = "586";
|
cpu_model = "586-class CPU (unknown)";
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
cpu_model = "686";
|
cpu_model = "686-class CPU (unknown)";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cpu_model = "Unidentified Processor";
|
cpu_model = "Unidentified Processor";
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*//*
|
*//*
|
||||||
* Copyright (C) 2020-2022 Martin Whitaker.
|
* Copyright (C) 2020-2022 Martin Whitaker.
|
||||||
* Copyright (C) 2004-2022 Sam Demeulemeester.
|
* Copyright (C) 2004-2023 Sam Demeulemeester.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -47,6 +47,7 @@
|
||||||
#define IMC_KBL_UY 0x3030 // Core 7/8/9th Gen (Kaby/Coffee/Comet/Amber Lake-U/Y)
|
#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_ICL 0x3040 // Core 10th Gen (IceLake-Y)
|
||||||
#define IMC_TGL 0x3050 // Core 11th Gen (Tiger Lake-U)
|
#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_BYT 0x4010 // Atom Bay Trail
|
||||||
#define IMC_CDT 0x4020 // Atom Cedar Trail
|
#define IMC_CDT 0x4020 // Atom Cedar Trail
|
||||||
|
|
|
@ -32,9 +32,9 @@ void heap_init(void);
|
||||||
* region will be at least the requested size with the requested alignment.
|
* region will be at least the requested size with the requested alignment.
|
||||||
* This memory is always mapped to the identical address in virtual memory.
|
* 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 size - the requested size in bytes.
|
||||||
* \param alignment - the requested byte alignment (must be a power of 2).
|
* \param alignment - the requested byte alignment (must be a power of 2).
|
||||||
* \param heap - the heap on which this allocation shall be performed.
|
|
||||||
*
|
*
|
||||||
* \returns
|
* \returns
|
||||||
* On success, the allocated address in physical memory. On failure, 0.
|
* On success, the allocated address in physical memory. On failure, 0.
|
||||||
|
@ -46,6 +46,8 @@ 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 heap. This value may be passed to heap_rewind() to free any
|
||||||
* memory from that heap allocated after this call.
|
* memory from that heap allocated after this call.
|
||||||
*
|
*
|
||||||
|
* \param heap_id - the target heap.
|
||||||
|
*
|
||||||
* \returns
|
* \returns
|
||||||
* An opaque value indicating the current allocation state.
|
* An opaque value indicating the current allocation state.
|
||||||
*/
|
*/
|
||||||
|
@ -55,8 +57,8 @@ uintptr_t heap_mark(heap_type_t heap_id);
|
||||||
* Frees any memory allocated in the given heap since the specified mark was
|
* Frees any memory allocated in the given heap since the specified mark was
|
||||||
* obtained from a call to heap_mark().
|
* 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 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);
|
void heap_rewind(heap_type_t heap_id, uintptr_t mark);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
// Copyright (C) 2004-2022 Samuel Demeulemeester
|
// Copyright (C) 2004-2023 Sam Demeulemeester
|
||||||
//
|
//
|
||||||
// ------------------------
|
// ------------------------
|
||||||
// This file is used to detect quirks on specific hardware
|
// This file is used to detect quirks on specific hardware
|
||||||
|
@ -13,6 +13,9 @@
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
#include "unistd.h"
|
#include "unistd.h"
|
||||||
#include "cpuinfo.h"
|
#include "cpuinfo.h"
|
||||||
|
#include "cpuid.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "temperature.h"
|
||||||
|
|
||||||
quirk_t quirk;
|
quirk_t quirk;
|
||||||
|
|
||||||
|
@ -64,6 +67,38 @@ static void get_m1541_l2_cache_size(void)
|
||||||
if (reg == 0b10) { l2_cache = 1024; }
|
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 --
|
// -- Public function --
|
||||||
// ---------------------
|
// ---------------------
|
||||||
|
@ -72,8 +107,8 @@ void quirks_init(void)
|
||||||
{
|
{
|
||||||
quirk.id = QUIRK_NONE;
|
quirk.id = QUIRK_NONE;
|
||||||
quirk.type = QUIRK_TYPE_NONE;
|
quirk.type = QUIRK_TYPE_NONE;
|
||||||
quirk.root_vid = pci_config_read16(0, 0, 0, 0);
|
quirk.root_vid = pci_config_read16(0, 0, 0, PCI_VID_REG);
|
||||||
quirk.root_did = pci_config_read16(0, 0, 0, 2);
|
quirk.root_did = pci_config_read16(0, 0, 0, PCI_DID_REG);
|
||||||
quirk.process = NULL;
|
quirk.process = NULL;
|
||||||
|
|
||||||
// -------------------------
|
// -------------------------
|
||||||
|
@ -93,13 +128,75 @@ void quirks_init(void)
|
||||||
// This motherboard has an ASB100 ASIC with a SMBUS Mux Integrated.
|
// This motherboard has an ASB100 ASIC with a SMBUS Mux Integrated.
|
||||||
// To access SPD later in the code, we need to configure the mux.
|
// To access SPD later in the code, we need to configure the mux.
|
||||||
// PS: Detection via DMI is unreliable, so using Root PCI Registers
|
// 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 (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, PCI_SUB_VID_REG) == PCI_VID_ASUS) { // ASUS
|
||||||
if (pci_config_read16(0, 0, 0, 0x2E) == 0x8027) { // TUSL2-C
|
if (pci_config_read16(0, 0, 0, PCI_SUB_DID_REG) == 0x8027) { // TUSL2-C
|
||||||
quirk.id = QUIRK_TUSL2;
|
quirk.id = QUIRK_TUSL2;
|
||||||
quirk.type |= QUIRK_TYPE_SMBUS;
|
quirk.type |= QUIRK_TYPE_SMBUS;
|
||||||
quirk.process = asus_tusl2_configure_mux;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,16 @@
|
||||||
#define QUIRK_TYPE_SMBUS (1 << 4)
|
#define QUIRK_TYPE_SMBUS (1 << 4)
|
||||||
#define QUIRK_TYPE_TIMER (1 << 5)
|
#define QUIRK_TYPE_TIMER (1 << 5)
|
||||||
#define QUIRK_TYPE_MEM_SIZE (1 << 6)
|
#define QUIRK_TYPE_MEM_SIZE (1 << 6)
|
||||||
|
#define QUIRK_TYPE_TEMP (1 << 7)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
QUIRK_NONE,
|
QUIRK_NONE,
|
||||||
QUIRK_TUSL2,
|
QUIRK_TUSL2,
|
||||||
QUIRK_ALI_ALADDIN_V
|
QUIRK_ALI_ALADDIN_V,
|
||||||
|
QUIRK_X10SDV_NOSMP,
|
||||||
|
QUIRK_K8_BSTEP_NOTEMP,
|
||||||
|
QUIRK_K8_REVFG_TEMP,
|
||||||
|
QUIRK_AMD_ERRATA_319
|
||||||
} quirk_id_t;
|
} quirk_id_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -478,7 +478,7 @@ static const struct spd_jedec_manufacturer jep106[] = {
|
||||||
// { 0x0353, "Primarion" },
|
// { 0x0353, "Primarion" },
|
||||||
// { 0x0354, "Picochip Designs Ltd" },
|
// { 0x0354, "Picochip Designs Ltd" },
|
||||||
// { 0x0355, "Silverback Systems" },
|
// { 0x0355, "Silverback Systems" },
|
||||||
// { 0x0356, "Jade Star Technologies" },
|
{ 0x0356, "Jade Star" },
|
||||||
// { 0x0357, "Pijnenburg Securealink" },
|
// { 0x0357, "Pijnenburg Securealink" },
|
||||||
{ 0x0358, "takeMS" }, // Ultron AG
|
{ 0x0358, "takeMS" }, // Ultron AG
|
||||||
// { 0x0359, "Cambridge Silicon Radio" },
|
// { 0x0359, "Cambridge Silicon Radio" },
|
||||||
|
@ -882,7 +882,7 @@ static const struct spd_jedec_manufacturer jep106[] = {
|
||||||
// { 0x066E, "Certicom Corporation" },
|
// { 0x066E, "Certicom Corporation" },
|
||||||
// { 0x066F, "JSC ICC Milandr" },
|
// { 0x066F, "JSC ICC Milandr" },
|
||||||
// { 0x0670, "PhotoFast Global Inc" },
|
// { 0x0670, "PhotoFast Global Inc" },
|
||||||
// { 0x0671, "InnoDisk Corporation" },
|
{ 0x0671, "InnoDisk" },
|
||||||
// { 0x0672, "Muscle Power" },
|
// { 0x0672, "Muscle Power" },
|
||||||
// { 0x0673, "Energy Micro" },
|
// { 0x0673, "Energy Micro" },
|
||||||
// { 0x0674, "Innofidei" },
|
// { 0x0674, "Innofidei" },
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
#define MSR_AMD64_NB_CFG 0xc001001f
|
#define MSR_AMD64_NB_CFG 0xc001001f
|
||||||
#define MSR_AMD64_COFVID_STATUS 0xc0010071
|
#define MSR_AMD64_COFVID_STATUS 0xc0010071
|
||||||
|
|
||||||
|
#define MSR_VIA_TEMP_C7 0x1169
|
||||||
|
#define MSR_VIA_TEMP_NANO 0x1423
|
||||||
|
|
||||||
#define rdmsr(msr, value1, value2) \
|
#define rdmsr(msr, value1, value2) \
|
||||||
__asm__ __volatile__("rdmsr" \
|
__asm__ __volatile__("rdmsr" \
|
||||||
: "=a" (value1), \
|
: "=a" (value1), \
|
||||||
|
|
|
@ -12,6 +12,11 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#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 */
|
/* Vendor IDs */
|
||||||
#define PCI_VID_ATI 0x1002
|
#define PCI_VID_ATI 0x1002
|
||||||
#define PCI_VID_AMD 0x1022
|
#define PCI_VID_AMD 0x1022
|
||||||
|
@ -22,6 +27,7 @@
|
||||||
#define PCI_VID_NVIDIA 0x10DE
|
#define PCI_VID_NVIDIA 0x10DE
|
||||||
#define PCI_VID_VIA 0x1106
|
#define PCI_VID_VIA 0x1106
|
||||||
#define PCI_VID_SERVERWORKS 0x1166
|
#define PCI_VID_SERVERWORKS 0x1166
|
||||||
|
#define PCI_VID_SUPERMICRO 0x15D9
|
||||||
#define PCI_VID_HYGON 0x1D94
|
#define PCI_VID_HYGON 0x1D94
|
||||||
#define PCI_VID_INTEL 0x8086
|
#define PCI_VID_INTEL 0x8086
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ static const rgb_value_t vga_pallete[16] = {
|
||||||
{ 255, 255, 255 } // BOLD+WHITE
|
{ 255, 255, 255 } // BOLD+WHITE
|
||||||
};
|
};
|
||||||
|
|
||||||
static vga_buffer_t *vga_buffer = (vga_buffer_t *)(0xb8000);
|
static vga_buffer_t *vga_buffer = NULL;
|
||||||
|
|
||||||
vga_buffer_t shadow_buffer;
|
vga_buffer_t shadow_buffer;
|
||||||
|
|
||||||
|
@ -64,7 +64,9 @@ 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].ch = ch;
|
||||||
shadow_buffer[row][col].attr = attr;
|
shadow_buffer[row][col].attr = attr;
|
||||||
|
|
||||||
(*vga_buffer)[row][col].value = shadow_buffer[row][col].value;
|
if (vga_buffer) {
|
||||||
|
(*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)
|
static void lfb8_put_char(int row, int col, uint8_t ch, uint8_t attr)
|
||||||
|
@ -239,6 +241,8 @@ void screen_init(void)
|
||||||
uint32_t b = ((vga_pallete[i].b * b_max) / 255) << screen_info->blue_pos;
|
uint32_t b = ((vga_pallete[i].b * b_max) / 255) << screen_info->blue_pos;
|
||||||
lfb_pallete[i] = r | g | b;
|
lfb_pallete[i] = r | g | b;
|
||||||
}
|
}
|
||||||
|
} else if (screen_info->orig_video_isVGA != VIDEO_TYPE_NONE) {
|
||||||
|
vga_buffer = (vga_buffer_t *)(0xb8000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
162
system/smbus.c
162
system/smbus.c
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
// Copyright (C) 2004-2022 Samuel Demeulemeester
|
// Copyright (C) 2004-2023 Sam Demeulemeester
|
||||||
|
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
|
||||||
|
@ -48,11 +48,14 @@ static uint8_t get_spd(uint8_t slot_idx, uint16_t spd_adr);
|
||||||
static bool nv_mcp_get_smb(void);
|
static bool nv_mcp_get_smb(void);
|
||||||
static bool amd_sb_get_smb(void);
|
static bool amd_sb_get_smb(void);
|
||||||
static bool fch_zen_get_smb(void);
|
static bool fch_zen_get_smb(void);
|
||||||
static bool piix4_get_smb(void);
|
static bool piix4_get_smb(uint8_t address);
|
||||||
static bool ich5_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_process(void);
|
||||||
static uint8_t ich5_read_spd_byte(uint8_t adr, uint16_t cmd);
|
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 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)
|
static inline uint8_t bcd_to_ui8(uint8_t bcd)
|
||||||
{
|
{
|
||||||
|
@ -1158,7 +1161,7 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
|
||||||
return ich5_get_smb();
|
return ich5_get_smb();
|
||||||
}
|
}
|
||||||
if (did == 0x7113) { // 82371AB/EB/MB PIIX4
|
if (did == 0x7113) { // 82371AB/EB/MB PIIX4
|
||||||
return piix4_get_smb();
|
return piix4_get_smb(PIIX4_SMB_BASE_ADR_DEFAULT);
|
||||||
}
|
}
|
||||||
// 0x719B 82440/82443MX PMC - PIIX4
|
// 0x719B 82440/82443MX PMC - PIIX4
|
||||||
// 0x0F13 ValleyView SMBus Controller ?
|
// 0x0F13 ValleyView SMBus Controller ?
|
||||||
|
@ -1189,7 +1192,8 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
|
||||||
{
|
{
|
||||||
// case 0x4353: // SB200
|
// case 0x4353: // SB200
|
||||||
// case 0x4363: // SB300
|
// case 0x4363: // SB300
|
||||||
// case 0x4372: // SB400
|
case 0x4372: // SB400
|
||||||
|
return piix4_get_smb(PIIX4_SMB_BASE_ADR_DEFAULT);
|
||||||
case 0x4385: // SB600+
|
case 0x4385: // SB600+
|
||||||
return amd_sb_get_smb();
|
return amd_sb_get_smb();
|
||||||
default:
|
default:
|
||||||
|
@ -1203,7 +1207,7 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
|
||||||
// case 0x01B4: // nForce
|
// case 0x01B4: // nForce
|
||||||
case 0x0064: // nForce 2
|
case 0x0064: // nForce 2
|
||||||
// case 0x0084: // nForce 2 Mobile
|
// case 0x0084: // nForce 2 Mobile
|
||||||
// case 0x00E4: // nForce 3
|
case 0x00E4: // nForce 3
|
||||||
// case 0x0034: // MCP04
|
// case 0x0034: // MCP04
|
||||||
// case 0x0052: // nForce 4
|
// case 0x0052: // nForce 4
|
||||||
case 0x0264: // nForce 410/430 MCP
|
case 0x0264: // nForce 410/430 MCP
|
||||||
|
@ -1243,16 +1247,17 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
|
||||||
// via SMBus controller.
|
// via SMBus controller.
|
||||||
// case 0x3050: // 82C596_3
|
// case 0x3050: // 82C596_3
|
||||||
// Try SMB base address = 0x90, then SMB base address = 0x80
|
// Try SMB base address = 0x90, then SMB base address = 0x80
|
||||||
// viapro SMBus controller.
|
// viapro SMBus controller, i.e. PIIX4 with a small quirk.
|
||||||
// case 0x3051: // 82C596B_3
|
// case 0x3051: // 82C596B_3
|
||||||
// case 0x3057: // 82C686_4
|
case 0x3057: // 82C686_4
|
||||||
// case 0x8235: // 8231_4
|
// case 0x8235: // 8231_4
|
||||||
// SMB base address = 0x90
|
// SMB base address = 0x90
|
||||||
// viapro SMBus controller.
|
// viapro SMBus controller, i.e. PIIX4.
|
||||||
// case 0x3074: // 8233_0
|
return piix4_get_smb(PIIX4_SMB_BASE_ADR_DEFAULT);
|
||||||
// case 0x3147: // 8233A
|
case 0x3074: // 8233
|
||||||
// case 0x3177: // 8235
|
case 0x3147: // 8233A
|
||||||
// case 0x3227: // 8237
|
case 0x3177: // 8235
|
||||||
|
case 0x3227: // 8237
|
||||||
// case 0x3337: // 8237A
|
// case 0x3337: // 8237A
|
||||||
// case 0x3372: // 8237S
|
// case 0x3372: // 8237S
|
||||||
// case 0x3287: // 8251
|
// case 0x3287: // 8251
|
||||||
|
@ -1261,7 +1266,8 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
|
||||||
// case 0x8409: // VX855
|
// case 0x8409: // VX855
|
||||||
// case 0x8410: // VX900
|
// case 0x8410: // VX900
|
||||||
// SMB base address = 0xD0
|
// SMB base address = 0xD0
|
||||||
// viapro I2C controller.
|
// viapro I2C controller, i.e. PIIX4 with a small quirk.
|
||||||
|
return piix4_get_smb(PIIX4_SMB_BASE_ADR_VIAPRO);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1279,8 +1285,10 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
|
||||||
case PCI_VID_ALI:
|
case PCI_VID_ALI:
|
||||||
switch(did)
|
switch(did)
|
||||||
{
|
{
|
||||||
// case 0x1563: // ali1563 (M1563) SMBus controller
|
case 0x7101: // ALi M1533/1535/1543C
|
||||||
// case 0x7101: // ali1535 (M1535) or ali15x3 (M1533/M1543) SMBus controllers
|
return ali_get_smb(PIIX4_SMB_BASE_ADR_ALI1543);
|
||||||
|
case 0x1563: // ALi M1563
|
||||||
|
return piix4_get_smb(PIIX4_SMB_BASE_ADR_ALI1563);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1297,7 +1305,7 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
|
||||||
// case 0x0203: // CSB6
|
// case 0x0203: // CSB6
|
||||||
// case 0x0205: // HT1000SB
|
// case 0x0205: // HT1000SB
|
||||||
// case 0x0408: // HT1100LD
|
// case 0x0408: // HT1100LD
|
||||||
return piix4_get_smb();
|
return piix4_get_smb(PIIX4_SMB_BASE_ADR_DEFAULT);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1312,9 +1320,9 @@ static bool find_smb_controller(uint16_t vid, uint16_t did)
|
||||||
// PIIX4 SMBUS Controller
|
// PIIX4 SMBUS Controller
|
||||||
// ----------------------
|
// ----------------------
|
||||||
|
|
||||||
static bool piix4_get_smb(void)
|
static bool piix4_get_smb(uint8_t address)
|
||||||
{
|
{
|
||||||
uint16_t x = pci_config_read16(0, smbdev, smbfun, 0x90) & 0xFFF0;
|
uint16_t x = pci_config_read16(0, smbdev, smbfun, address) & 0xFFF0;
|
||||||
|
|
||||||
if (x != 0) {
|
if (x != 0) {
|
||||||
smbusbase = x;
|
smbusbase = x;
|
||||||
|
@ -1332,10 +1340,18 @@ static bool ich5_get_smb(void)
|
||||||
{
|
{
|
||||||
uint16_t x;
|
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);
|
x = pci_config_read16(0, smbdev, smbfun, 0x20);
|
||||||
smbusbase = x & 0xFFF0;
|
smbusbase = x & 0xFFF0;
|
||||||
|
|
||||||
// Enable I2C Bus
|
// Enable I2C Host Controller Interface if disabled
|
||||||
uint8_t temp = pci_config_read8(0, smbdev, smbfun, 0x40);
|
uint8_t temp = pci_config_read8(0, smbdev, smbfun, 0x40);
|
||||||
if ((temp & 4) == 0) {
|
if ((temp & 4) == 0) {
|
||||||
pci_config_write8(0, smbdev, smbfun, 0x40, temp | 0x04);
|
pci_config_write8(0, smbdev, smbfun, 0x40, temp | 0x04);
|
||||||
|
@ -1361,7 +1377,7 @@ static bool amd_sb_get_smb(void)
|
||||||
|
|
||||||
if ((smbus_id & 0xFFFF) == 0x4385 && rev_id <= 0x3D) {
|
if ((smbus_id & 0xFFFF) == 0x4385 && rev_id <= 0x3D) {
|
||||||
// Older AMD SouthBridge (SB700 & older) use PIIX4 registers
|
// Older AMD SouthBridge (SB700 & older) use PIIX4 registers
|
||||||
return piix4_get_smb();
|
return piix4_get_smb(PIIX4_SMB_BASE_ADR_DEFAULT);
|
||||||
} else if ((smbus_id & 0xFFFF) == 0x780B && rev_id == 0x42) {
|
} else if ((smbus_id & 0xFFFF) == 0x780B && rev_id == 0x42) {
|
||||||
// Latest Pre-Zen APUs use the newer Zen PM registers
|
// Latest Pre-Zen APUs use the newer Zen PM registers
|
||||||
return fch_zen_get_smb();
|
return fch_zen_get_smb();
|
||||||
|
@ -1434,6 +1450,35 @@ static bool nv_mcp_get_smb(void)
|
||||||
return false;
|
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
|
// get_spd() function
|
||||||
// ------------------
|
// ------------------
|
||||||
|
@ -1441,6 +1486,11 @@ static bool nv_mcp_get_smb(void)
|
||||||
static uint8_t get_spd(uint8_t slot_idx, uint16_t spd_adr)
|
static uint8_t get_spd(uint8_t slot_idx, uint16_t spd_adr)
|
||||||
{
|
{
|
||||||
switch ((smbus_id >> 16) & 0xFFFF) {
|
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:
|
case PCI_VID_NVIDIA:
|
||||||
return nf_read_spd_byte(slot_idx, (uint8_t)spd_adr);
|
return nf_read_spd_byte(slot_idx, (uint8_t)spd_adr);
|
||||||
default:
|
default:
|
||||||
|
@ -1568,7 +1618,7 @@ static uint8_t nf_read_spd_byte(uint8_t smbus_adr, uint8_t spd_adr)
|
||||||
// Start transaction
|
// Start transaction
|
||||||
__outb(NVSMBCNT_BYTE_DATA | NVSMBCNT_READ, NVSMBCNT);
|
__outb(NVSMBCNT_BYTE_DATA | NVSMBCNT_READ, NVSMBCNT);
|
||||||
|
|
||||||
// Wait until transction complete
|
// Wait until transaction complete
|
||||||
for (i = 500; i > 0; i--) {
|
for (i = 500; i > 0; i--) {
|
||||||
usleep(50);
|
usleep(50);
|
||||||
if (__inb(NVSMBCNT) == 0) {
|
if (__inb(NVSMBCNT) == 0) {
|
||||||
|
@ -1583,3 +1633,73 @@ static uint8_t nf_read_spd_byte(uint8_t smbus_adr, uint8_t spd_adr)
|
||||||
|
|
||||||
return __inb(NVSMBDAT(0));
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
* Provides functions for reading SPD via SMBUS
|
* Provides functions for reading SPD via SMBUS
|
||||||
*
|
*
|
||||||
* Copyright (C) 2004-2022 Samuel Demeulemeester.
|
* Copyright (C) 2004-2023 Sam Demeulemeester.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define I2C_WRITE 0
|
#define I2C_WRITE 0
|
||||||
|
@ -74,6 +74,28 @@
|
||||||
#define NVSMBSTS_RES 0x20
|
#define NVSMBSTS_RES 0x20
|
||||||
#define NVSMBSTS_STATUS 0x1f
|
#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
|
/** Rounding factors for timing computation
|
||||||
*
|
*
|
||||||
* These factors are used as a configurable CEIL() function
|
* These factors are used as a configurable CEIL() function
|
||||||
|
@ -85,6 +107,11 @@
|
||||||
|
|
||||||
#define SPD_SKU_LEN 32
|
#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 {
|
struct pci_smbus_controller {
|
||||||
unsigned vendor;
|
unsigned vendor;
|
||||||
unsigned device;
|
unsigned device;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "cpuid.h"
|
#include "cpuid.h"
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
|
#include "hwquirks.h"
|
||||||
#include "memrw32.h"
|
#include "memrw32.h"
|
||||||
#include "memsize.h"
|
#include "memsize.h"
|
||||||
#include "msr.h"
|
#include "msr.h"
|
||||||
|
@ -539,6 +540,12 @@ void smp_init(bool smp_enable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process SMP Quirks
|
||||||
|
if (quirk.type & QUIRK_TYPE_SMP) {
|
||||||
|
// quirk.process();
|
||||||
|
smp_enable = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (smp_enable) {
|
if (smp_enable) {
|
||||||
(void)(find_cpus_in_madt() || find_cpus_in_floating_mp_struct());
|
(void)(find_cpus_in_madt() || find_cpus_in_floating_mp_struct());
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
// Copyright (C) 2020-2022 Martin Whitaker.
|
// Copyright (C) 2020-2022 Martin Whitaker.
|
||||||
|
// Copyright (C) 2004-2023 Sam Demeulemeester.
|
||||||
//
|
//
|
||||||
// Derived from an extract of memtest86+ init.c:
|
// Derived from an extract of memtest86+ init.c:
|
||||||
//
|
//
|
||||||
|
@ -16,57 +17,120 @@
|
||||||
|
|
||||||
#include "cpuid.h"
|
#include "cpuid.h"
|
||||||
#include "cpuinfo.h"
|
#include "cpuinfo.h"
|
||||||
|
#include "hwquirks.h"
|
||||||
#include "msr.h"
|
#include "msr.h"
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
|
|
||||||
#include "temperature.h"
|
#include "temperature.h"
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Public Variables
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
float cpu_temp_offset = 0;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Public Functions
|
// 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)
|
int get_cpu_temperature(void)
|
||||||
{
|
{
|
||||||
|
uint32_t regl, regh;
|
||||||
|
|
||||||
// Intel CPU
|
// Intel CPU
|
||||||
if (cpuid_info.vendor_id.str[0] == 'G' && cpuid_info.max_cpuid >= 6) {
|
if (cpuid_info.vendor_id.str[0] == 'G' && cpuid_info.max_cpuid >= 6 && (cpuid_info.dts_pmp & 1)) {
|
||||||
if (cpuid_info.dts_pmp & 1) {
|
|
||||||
uint32_t msrl, msrh;
|
|
||||||
|
|
||||||
rdmsr(MSR_IA32_THERM_STATUS, msrl, msrh);
|
rdmsr(MSR_IA32_THERM_STATUS, regl, regh);
|
||||||
int Tabs = (msrl >> 16) & 0x7F;
|
int Tabs = (regl >> 16) & 0x7F;
|
||||||
|
|
||||||
rdmsr(MSR_IA32_TEMPERATURE_TARGET, msrl, msrh);
|
return TjMax - Tabs;
|
||||||
int Tjunc = (msrl >> 16) & 0x7F;
|
|
||||||
|
|
||||||
if (Tjunc < 50 || Tjunc > 125) {
|
|
||||||
Tjunc = 90;
|
|
||||||
}
|
|
||||||
return Tjunc - Tabs;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AMD CPU
|
// AMD CPU
|
||||||
if (cpuid_info.vendor_id.str[0] == 'A' && cpuid_info.version.extendedFamily > 0 && cpuid_info.version.extendedFamily < 8) {
|
else if (cpuid_info.vendor_id.str[0] == 'A' && cpuid_info.version.family == 0xF) { // Target only K8 & newer
|
||||||
|
|
||||||
// Untested yet
|
if (cpuid_info.version.extendedFamily >= 8) { // Target Zen µarch and newer. Use SMN to get temperature.
|
||||||
uint32_t rtcr = pci_config_read32(0, 24, 3, 0xA4);
|
|
||||||
int raw_temp = (rtcr >> 21) & 0x7FF;
|
|
||||||
|
|
||||||
return raw_temp / 8;
|
regl = amd_smn_read(SMN_THM_TCON_CUR_TMP);
|
||||||
|
|
||||||
} else if (cpuid_info.vendor_id.str[0] == 'A' && cpuid_info.version.extendedFamily >= 8) {
|
if ((regl >> 19) & 0x01) {
|
||||||
|
cpu_temp_offset = -49.0f;
|
||||||
|
}
|
||||||
|
|
||||||
// Grab CPU Temp. for ZEN CPUs using SNM
|
return cpu_temp_offset + 0.125f * (float)((regl >> 21) & 0x7FF);
|
||||||
uint32_t tval = amd_smn_read(SMN_THM_TCON_CUR_TMP);
|
|
||||||
|
|
||||||
float offset = 0;
|
} else if (cpuid_info.version.extendedFamily > 0) { // Target K10 to K15 (Bulldozer)
|
||||||
|
|
||||||
if((tval >> 19) & 0x01) {
|
regl = pci_config_read32(0, 24, 3, AMD_TEMP_REG_K10);
|
||||||
offset = -49.0f;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
return offset + 0.125f * (float)((tval >> 21) & 0x7FF);
|
rdmsr(msr_temp, regl, regh);
|
||||||
|
return (int)(regl & 0xffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -8,8 +8,22 @@
|
||||||
*
|
*
|
||||||
*//*
|
*//*
|
||||||
* Copyright (C) 2020-2022 Martin Whitaker.
|
* 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
|
* Returns the current temperature of the CPU. Returns 0 if
|
||||||
* the temperature cannot be read.
|
* the temperature cannot be read.
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
#define PIT_TICKS_50mS 59659 // PIT clock is 1.193182MHz
|
#define PIT_TICKS_50mS 59659 // PIT clock is 1.193182MHz
|
||||||
#define APIC_TICKS_50mS 178977 // APIC clock is 3.579545MHz
|
#define APIC_TICKS_50mS 178977 // APIC clock is 3.579545MHz
|
||||||
#define BENCH_MIN_START_ADR 0x1000000 // 16MB
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Private Functions
|
// Private Functions
|
||||||
|
@ -39,6 +38,9 @@ static void correct_tsc(void)
|
||||||
|
|
||||||
counter = inl(acpi_config.pm_addr);
|
counter = inl(acpi_config.pm_addr);
|
||||||
|
|
||||||
|
// Generate a dirty delay
|
||||||
|
for(volatile uint8_t i=0; i<100u; i++);
|
||||||
|
|
||||||
// Make sure counter is incrementing
|
// Make sure counter is incrementing
|
||||||
if (inl(acpi_config.pm_addr) > counter) {
|
if (inl(acpi_config.pm_addr) > counter) {
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "vmem.h"
|
||||||
|
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
@ -127,12 +129,20 @@ int test_own_addr1(int my_cpu)
|
||||||
|
|
||||||
int test_own_addr2(int my_cpu, int stage)
|
int test_own_addr2(int my_cpu, int stage)
|
||||||
{
|
{
|
||||||
static testword_t offset = 0;
|
|
||||||
static int last_stage = -1;
|
|
||||||
|
|
||||||
int ticks = 0;
|
int ticks = 0;
|
||||||
|
|
||||||
offset = (stage == last_stage) ? offset + 1 : 1;
|
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
|
||||||
|
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -145,6 +155,5 @@ int test_own_addr2(int my_cpu, int stage)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_stage = stage;
|
|
||||||
return ticks;
|
return ticks;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
test_pattern_t test_list[NUM_TEST_PATTERNS] = {
|
test_pattern_t test_list[NUM_TEST_PATTERNS] = {
|
||||||
// ena, cpu, stgs, itrs, errs, description
|
// ena, cpu, stgs, itrs, errs, description
|
||||||
{ true, SEQ, 1, 6, 0, "[Address test, walking ones, no cache] "},
|
{ true, SEQ, 1, 6, 0, "[Address test, walking ones, no cache] "},
|
||||||
{ true, SEQ, 1, 6, 0, "[Address test, own address in window] "},
|
{false, SEQ, 1, 6, 0, "[Address test, own address in window] "},
|
||||||
{ true, SEQ, 2, 6, 0, "[Address test, own address + window] "},
|
{ true, SEQ, 2, 6, 0, "[Address test, own address + window] "},
|
||||||
{ true, PAR, 1, 6, 0, "[Moving inversions, 1s & 0s] "},
|
{ true, PAR, 1, 6, 0, "[Moving inversions, 1s & 0s] "},
|
||||||
{ true, PAR, 1, 3, 0, "[Moving inversions, 8 bit pattern] "},
|
{ true, PAR, 1, 3, 0, "[Moving inversions, 8 bit pattern] "},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue