mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-29 18:41:30 +00:00
It is convenient to write a length value for preceding a block of data. Of course the length is not known or is hard to calculate a priori. So add a way to mark the start on a stack, so the length can be updated when known. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
86 lines
1.9 KiB
C
86 lines
1.9 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Generation of ACPI (Advanced Configuration and Power Interface) tables
|
|
*
|
|
* Copyright 2019 Google LLC
|
|
* Mostly taken from coreboot
|
|
*/
|
|
|
|
#define LOG_CATEGORY LOGC_ACPI
|
|
|
|
#include <common.h>
|
|
#include <dm.h>
|
|
#include <log.h>
|
|
#include <acpi/acpigen.h>
|
|
#include <dm/acpi.h>
|
|
|
|
u8 *acpigen_get_current(struct acpi_ctx *ctx)
|
|
{
|
|
return ctx->current;
|
|
}
|
|
|
|
void acpigen_emit_byte(struct acpi_ctx *ctx, uint data)
|
|
{
|
|
*(u8 *)ctx->current++ = data;
|
|
}
|
|
|
|
void acpigen_emit_word(struct acpi_ctx *ctx, uint data)
|
|
{
|
|
acpigen_emit_byte(ctx, data & 0xff);
|
|
acpigen_emit_byte(ctx, (data >> 8) & 0xff);
|
|
}
|
|
|
|
void acpigen_emit_dword(struct acpi_ctx *ctx, uint data)
|
|
{
|
|
/* Output the value in little-endian format */
|
|
acpigen_emit_byte(ctx, data & 0xff);
|
|
acpigen_emit_byte(ctx, (data >> 8) & 0xff);
|
|
acpigen_emit_byte(ctx, (data >> 16) & 0xff);
|
|
acpigen_emit_byte(ctx, (data >> 24) & 0xff);
|
|
}
|
|
|
|
/*
|
|
* Maximum length for an ACPI object generated by this code,
|
|
*
|
|
* If you need to change this, change acpigen_write_len_f(ctx) and
|
|
* acpigen_pop_len(ctx)
|
|
*/
|
|
#define ACPIGEN_MAXLEN 0xfffff
|
|
|
|
void acpigen_write_len_f(struct acpi_ctx *ctx)
|
|
{
|
|
assert(ctx->ltop < (ACPIGEN_LENSTACK_SIZE - 1));
|
|
ctx->len_stack[ctx->ltop++] = ctx->current;
|
|
acpigen_emit_byte(ctx, 0);
|
|
acpigen_emit_byte(ctx, 0);
|
|
acpigen_emit_byte(ctx, 0);
|
|
}
|
|
|
|
void acpigen_pop_len(struct acpi_ctx *ctx)
|
|
{
|
|
int len;
|
|
char *p;
|
|
|
|
assert(ctx->ltop > 0);
|
|
p = ctx->len_stack[--ctx->ltop];
|
|
len = ctx->current - (void *)p;
|
|
assert(len <= ACPIGEN_MAXLEN);
|
|
/* generate store length for 0xfffff max */
|
|
p[0] = ACPI_PKG_LEN_3_BYTES | (len & 0xf);
|
|
p[1] = len >> 4 & 0xff;
|
|
p[2] = len >> 12 & 0xff;
|
|
}
|
|
|
|
void acpigen_emit_stream(struct acpi_ctx *ctx, const char *data, int size)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < size; i++)
|
|
acpigen_emit_byte(ctx, data[i]);
|
|
}
|
|
|
|
void acpigen_emit_string(struct acpi_ctx *ctx, const char *str)
|
|
{
|
|
acpigen_emit_stream(ctx, str, str ? strlen(str) : 0);
|
|
acpigen_emit_byte(ctx, '\0');
|
|
}
|