mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
A simple rewrite of biossmap.c:
- Do not iterate int 15h, function e820h twice. Instead, we use STAILQ to store each return buffer and copy all at once. - Export optional extended attributes defined in ACPI 3.0 as separate metadata. Currently, there are only two bits defined in the specification. For example, if the descriptor has extended attributes and it is not enabled, it has to be ignored by OS. We may implement it in the kernel later if it is necessary and proven correct in reality. - Check return buffer size strictly as suggested in ACPI 3.0. Reviewed by: jhb
This commit is contained in:
parent
b0089534da
commit
cebe9dc98a
5 changed files with 97 additions and 44 deletions
|
|
@ -30,5 +30,6 @@
|
|||
#define _MACHINE_METADATA_H_
|
||||
|
||||
#define MODINFOMD_SMAP 0x1001
|
||||
#define MODINFOMD_SMAP_XATTR 0x1002
|
||||
|
||||
#endif /* !_MACHINE_METADATA_H_ */
|
||||
|
|
|
|||
|
|
@ -48,6 +48,10 @@ extern u_int32_t bios_sigsearch(u_int32_t start, u_char *sig, int siglen,
|
|||
#define SMAP_TYPE_ACPI_NVS 4
|
||||
#define SMAP_TYPE_ACPI_ERROR 5
|
||||
|
||||
#define SMAP_XATTR_ENABLED 0x00000001
|
||||
#define SMAP_XATTR_NON_VOLATILE 0x00000002
|
||||
#define SMAP_XATTR_MASK (SMAP_XATTR_ENABLED | SMAP_XATTR_NON_VOLATILE)
|
||||
|
||||
struct bios_smap {
|
||||
u_int64_t base;
|
||||
u_int64_t length;
|
||||
|
|
|
|||
|
|
@ -33,74 +33,107 @@ __FBSDID("$FreeBSD$");
|
|||
#include <stand.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/stddef.h>
|
||||
#include <machine/metadata.h>
|
||||
#include <machine/psl.h>
|
||||
#include <machine/pc/bios.h>
|
||||
#include "bootstrap.h"
|
||||
#include "libi386.h"
|
||||
#include "btxv86.h"
|
||||
|
||||
static struct {
|
||||
struct bios_smap _smap_entry;
|
||||
char pad[8]; /* Bad BIOS writer, no cookie! */
|
||||
} smap;
|
||||
#define V86_CY(x) ((x) & PSL_C)
|
||||
|
||||
static struct bios_smap *smapbase;
|
||||
static int smaplen;
|
||||
struct smap_buf {
|
||||
struct bios_smap smap;
|
||||
uint32_t xattr; /* Extended attribute from ACPI 3.0 */
|
||||
STAILQ_ENTRY(smap_buf) bufs;
|
||||
};
|
||||
|
||||
#define SMAP_BUFSIZE offsetof(struct smap_buf, bufs)
|
||||
|
||||
static struct bios_smap *smapbase;
|
||||
static uint32_t *smapattr;
|
||||
static u_int smaplen;
|
||||
|
||||
void
|
||||
bios_getsmap(void)
|
||||
{
|
||||
int n;
|
||||
struct smap_buf buf;
|
||||
STAILQ_HEAD(smap_head, smap_buf) head =
|
||||
STAILQ_HEAD_INITIALIZER(head);
|
||||
struct smap_buf *cur, *next;
|
||||
u_int n, x;
|
||||
|
||||
STAILQ_INIT(&head);
|
||||
n = 0;
|
||||
smaplen = 0;
|
||||
/* Count up segments in system memory map */
|
||||
x = 0;
|
||||
v86.ebx = 0;
|
||||
do {
|
||||
v86.ctl = V86_FLAGS;
|
||||
v86.addr = 0x15; /* int 0x15 function 0xe820*/
|
||||
v86.eax = 0xe820;
|
||||
v86.ecx = sizeof(struct bios_smap);
|
||||
v86.addr = 0x15;
|
||||
v86.eax = 0xe820; /* int 0x15 function 0xe820 */
|
||||
v86.ecx = SMAP_BUFSIZE;
|
||||
v86.edx = SMAP_SIG;
|
||||
v86.es = VTOPSEG(&smap);
|
||||
v86.edi = VTOPOFF(&smap);
|
||||
v86.es = VTOPSEG(&buf);
|
||||
v86.edi = VTOPOFF(&buf);
|
||||
v86int();
|
||||
if ((v86.efl & 1) || (v86.eax != SMAP_SIG))
|
||||
if (V86_CY(v86.efl) || v86.eax != SMAP_SIG ||
|
||||
v86.ecx < sizeof(buf.smap) || v86.ecx > SMAP_BUFSIZE)
|
||||
break;
|
||||
|
||||
next = malloc(sizeof(*next));
|
||||
if (next == NULL)
|
||||
break;
|
||||
next->smap = buf.smap;
|
||||
if (v86.ecx == SMAP_BUFSIZE) {
|
||||
next->xattr = buf.xattr;
|
||||
x++;
|
||||
}
|
||||
STAILQ_INSERT_TAIL(&head, next, bufs);
|
||||
n++;
|
||||
} while (v86.ebx != 0);
|
||||
if (n == 0)
|
||||
return;
|
||||
n += 10; /* spare room */
|
||||
smapbase = malloc(n * sizeof(*smapbase));
|
||||
smaplen = n;
|
||||
|
||||
/* Save system memory map */
|
||||
v86.ebx = 0;
|
||||
do {
|
||||
v86.ctl = V86_FLAGS;
|
||||
v86.addr = 0x15; /* int 0x15 function 0xe820*/
|
||||
v86.eax = 0xe820;
|
||||
v86.ecx = sizeof(struct bios_smap);
|
||||
v86.edx = SMAP_SIG;
|
||||
v86.es = VTOPSEG(&smap);
|
||||
v86.edi = VTOPOFF(&smap);
|
||||
v86int();
|
||||
bcopy(&smap, &smapbase[smaplen], sizeof(struct bios_smap));
|
||||
smaplen++;
|
||||
if ((v86.efl & 1) || (v86.eax != SMAP_SIG))
|
||||
break;
|
||||
} while (v86.ebx != 0 && smaplen < n);
|
||||
if (smaplen > 0) {
|
||||
smapbase = malloc(smaplen * sizeof(*smapbase));
|
||||
if (smapbase != NULL) {
|
||||
n = 0;
|
||||
STAILQ_FOREACH(cur, &head, bufs)
|
||||
smapbase[n++] = cur->smap;
|
||||
}
|
||||
if (smaplen == x) {
|
||||
smapattr = malloc(smaplen * sizeof(*smapattr));
|
||||
if (smapattr != NULL) {
|
||||
n = 0;
|
||||
STAILQ_FOREACH(cur, &head, bufs)
|
||||
smapattr[n++] = cur->xattr &
|
||||
SMAP_XATTR_MASK;
|
||||
}
|
||||
} else
|
||||
smapattr = NULL;
|
||||
cur = STAILQ_FIRST(&head);
|
||||
while (cur != NULL) {
|
||||
next = STAILQ_NEXT(cur, bufs);
|
||||
free(cur);
|
||||
cur = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bios_addsmapdata(struct preloaded_file *kfp)
|
||||
{
|
||||
int len;
|
||||
size_t size;
|
||||
|
||||
if (smapbase == 0 || smaplen == 0)
|
||||
if (smapbase == NULL || smaplen == 0)
|
||||
return;
|
||||
len = smaplen * sizeof(*smapbase);
|
||||
file_addmetadata(kfp, MODINFOMD_SMAP, len, smapbase);
|
||||
size = smaplen * sizeof(*smapbase);
|
||||
file_addmetadata(kfp, MODINFOMD_SMAP, size, smapbase);
|
||||
if (smapattr != NULL) {
|
||||
size = smaplen * sizeof(*smapattr);
|
||||
file_addmetadata(kfp, MODINFOMD_SMAP_XATTR, size, smapattr);
|
||||
}
|
||||
}
|
||||
|
||||
COMMAND_SET(smap, "smap", "show BIOS SMAP", command_smap);
|
||||
|
|
@ -108,12 +141,22 @@ COMMAND_SET(smap, "smap", "show BIOS SMAP", command_smap);
|
|||
static int
|
||||
command_smap(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
u_int i;
|
||||
|
||||
if (smapbase == 0 || smaplen == 0)
|
||||
if (smapbase == NULL || smaplen == 0)
|
||||
return (CMD_ERROR);
|
||||
for (i = 0; i < smaplen; i++)
|
||||
printf("SMAP type=%02x base=%016llx len=%016llx\n",
|
||||
smapbase[i].type, smapbase[i].base, smapbase[i].length);
|
||||
if (smapattr != NULL)
|
||||
for (i = 0; i < smaplen; i++)
|
||||
printf("SMAP type=%02x base=%016llx len=%016llx attr=%02x\n",
|
||||
(unsigned int)smapbase[i].type,
|
||||
(unsigned long long)smapbase[i].base,
|
||||
(unsigned long long)smapbase[i].length,
|
||||
(unsigned int)smapattr[i]);
|
||||
else
|
||||
for (i = 0; i < smaplen; i++)
|
||||
printf("SMAP type=%02x base=%016llx len=%016llx\n",
|
||||
(unsigned int)smapbase[i].type,
|
||||
(unsigned long long)smapbase[i].base,
|
||||
(unsigned long long)smapbase[i].length);
|
||||
return (CMD_OK);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,5 +30,6 @@
|
|||
#define _MACHINE_METADATA_H_
|
||||
|
||||
#define MODINFOMD_SMAP 0x1001
|
||||
#define MODINFOMD_SMAP_XATTR 0x1002
|
||||
|
||||
#endif /* !_MACHINE_METADATA_H_ */
|
||||
|
|
|
|||
|
|
@ -281,6 +281,10 @@ struct PIR_table
|
|||
#define SMAP_TYPE_ACPI_NVS 4
|
||||
#define SMAP_TYPE_ACPI_ERROR 5
|
||||
|
||||
#define SMAP_XATTR_ENABLED 0x00000001
|
||||
#define SMAP_XATTR_NON_VOLATILE 0x00000002
|
||||
#define SMAP_XATTR_MASK (SMAP_XATTR_ENABLED | SMAP_XATTR_NON_VOLATILE)
|
||||
|
||||
struct bios_smap {
|
||||
u_int64_t base;
|
||||
u_int64_t length;
|
||||
|
|
|
|||
Loading…
Reference in a new issue