]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - arch/x86/boot/memory.c
Merge tag 'auxdisplay-for-linus-v5.3-rc5' of git://github.com/ojeda/linux
[mirror_ubuntu-eoan-kernel.git] / arch / x86 / boot / memory.c
CommitLineData
97873a3d 1// SPDX-License-Identifier: GPL-2.0-only
449f2ab9
PA
2/* -*- linux-c -*- ------------------------------------------------------- *
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 * Copyright 2007 rPath, Inc. - All Rights Reserved
c549e71d 6 * Copyright 2009 Intel Corporation; author H. Peter Anvin
449f2ab9 7 *
449f2ab9
PA
8 * ----------------------------------------------------------------------- */
9
10/*
449f2ab9
PA
11 * Memory detection code
12 */
13
14#include "boot.h"
15
16#define SMAP 0x534d4150 /* ASCII "SMAP" */
17
e8eeb3c8 18static void detect_memory_e820(void)
449f2ab9 19{
2efa33f8 20 int count = 0;
df7699c5 21 struct biosregs ireg, oreg;
7410aa1c
IM
22 struct boot_e820_entry *desc = boot_params.e820_table;
23 static struct boot_e820_entry buf; /* static so it is zeroed */
449f2ab9 24
df7699c5
PA
25 initregs(&ireg);
26 ireg.ax = 0xe820;
0e96f31e 27 ireg.cx = sizeof(buf);
df7699c5
PA
28 ireg.edx = SMAP;
29 ireg.di = (size_t)&buf;
30
cd670599 31 /*
bca23dba
PA
32 * Note: at least one BIOS is known which assumes that the
33 * buffer pointed to by one e820 call is the same one as
34 * the previous call, and only changes modified fields. Therefore,
35 * we use a temporary buffer and copy the results entry by entry.
36 *
37 * This routine deliberately does not try to account for
38 * ACPI 3+ extended attributes. This is because there are
39 * BIOSes in the field which report zero for the valid bit for
40 * all ranges, and we don't currently make any use of the
41 * other attribute bits. Revisit this if we see the extended
42 * attribute bits deployed in a meaningful way in the future.
cd670599 43 */
cd670599 44
449f2ab9 45 do {
df7699c5
PA
46 intcall(0x15, &ireg, &oreg);
47 ireg.ebx = oreg.ebx; /* for next iteration... */
449f2ab9 48
829157be
PA
49 /* BIOSes which terminate the chain with CF = 1 as opposed
50 to %ebx = 0 don't always report the SMAP signature on
51 the final, failing, probe. */
df7699c5 52 if (oreg.eflags & X86_EFLAGS_CF)
829157be
PA
53 break;
54
2efa33f8
PA
55 /* Some BIOSes stop returning SMAP in the middle of
56 the search loop. We don't know exactly how the BIOS
57 screwed up the map at that point, we might have a
58 partial map, the full map, or complete garbage, so
59 just return failure. */
df7699c5 60 if (oreg.eax != SMAP) {
2efa33f8 61 count = 0;
449f2ab9 62 break;
2efa33f8 63 }
449f2ab9 64
bca23dba 65 *desc++ = buf;
2efa33f8 66 count++;
61a50101 67 } while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_table));
449f2ab9 68
e8eeb3c8 69 boot_params.e820_entries = count;
449f2ab9
PA
70}
71
e8eeb3c8 72static void detect_memory_e801(void)
449f2ab9 73{
df7699c5 74 struct biosregs ireg, oreg;
449f2ab9 75
df7699c5
PA
76 initregs(&ireg);
77 ireg.ax = 0xe801;
78 intcall(0x15, &ireg, &oreg);
449f2ab9 79
df7699c5 80 if (oreg.eflags & X86_EFLAGS_CF)
e8eeb3c8 81 return;
449f2ab9
PA
82
83 /* Do we really need to do this? */
df7699c5
PA
84 if (oreg.cx || oreg.dx) {
85 oreg.ax = oreg.cx;
86 oreg.bx = oreg.dx;
449f2ab9
PA
87 }
88
df7699c5 89 if (oreg.ax > 15*1024) {
e8eeb3c8 90 return; /* Bogus! */
df7699c5 91 } else if (oreg.ax == 15*1024) {
39b68976 92 boot_params.alt_mem_k = (oreg.bx << 6) + oreg.ax;
df7699c5
PA
93 } else {
94 /*
95 * This ignores memory above 16MB if we have a memory
96 * hole there. If someone actually finds a machine
97 * with a memory hole at 16MB and no support for
98 * 0E820h they should probably generate a fake e820
99 * map.
100 */
101 boot_params.alt_mem_k = oreg.ax;
102 }
449f2ab9
PA
103}
104
e8eeb3c8 105static void detect_memory_88(void)
449f2ab9 106{
df7699c5 107 struct biosregs ireg, oreg;
449f2ab9 108
df7699c5
PA
109 initregs(&ireg);
110 ireg.ah = 0x88;
111 intcall(0x15, &ireg, &oreg);
449f2ab9 112
df7699c5 113 boot_params.screen_info.ext_mem_k = oreg.ax;
449f2ab9
PA
114}
115
e8eeb3c8 116void detect_memory(void)
449f2ab9 117{
e8eeb3c8 118 detect_memory_e820();
2efa33f8 119
e8eeb3c8 120 detect_memory_e801();
449f2ab9 121
e8eeb3c8 122 detect_memory_88();
449f2ab9 123}