summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig12
-rw-r--r--lib/efi_loader/Kconfig9
-rw-r--r--lib/efi_loader/efi_tcg2.c15
-rw-r--r--lib/tpm-v2.c259
-rw-r--r--lib/tpm_api.c4
-rw-r--r--lib/tpm_tcg2.c111
6 files changed, 332 insertions, 78 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index 0a295161385..b27965fc480 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -514,6 +514,18 @@ config VPL_TPM
for the low-level TPM interface, but only one TPM is supported at
a time by the TPM library.
+config TPM_PCR_ALLOCATE
+ bool "Re-configurate TPM algorithms in run-time (PCR allocate)"
+ depends on TPM_V2 && (MEASURED_BOOT || EFI_TCG2_PROTOCOL)
+ help
+ This enables a detection for the dismatches of algorithms among TPM
+ device, eventlog from previous boot stage and U-Boot support.
+ A PCR allocate command will be sent to reconfigurate the TPM device
+ in run-time to make sure algorithms in TPM device, eventlog and
+ U-Boot are aligned with each other.
+ A system reboot will be proceeded after then to activate the new
+ algorithms.
+
endmenu
menu "Android Verified Boot"
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index ad0bbdd8a77..d4f6b56afaa 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -438,15 +438,6 @@ config EFI_TCG2_PROTOCOL
Provide a EFI_TCG2_PROTOCOL implementation using the TPM hardware
of the platform.
-config EFI_TCG2_PROTOCOL_EVENTLOG_SIZE
- int "EFI_TCG2_PROTOCOL EventLog size"
- depends on EFI_TCG2_PROTOCOL
- default 65536
- help
- Define the size of the EventLog for EFI_TCG2_PROTOCOL. Note that
- this is going to be allocated twice. One for the eventlog it self
- and one for the configuration table that is required from the spec
-
config EFI_TCG2_PROTOCOL_MEASURE_DTB
bool "Measure DTB with EFI_TCG2_PROTOCOL"
depends on EFI_TCG2_PROTOCOL
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index c697b53441a..210a846ebc8 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -112,7 +112,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
/* if ExitBootServices hasn't been called update the normal log */
if (!event_log.ebs_called) {
if (event_log.truncated ||
- event_log.pos + event_size > TPM2_EVENT_LOG_SIZE) {
+ event_log.pos + event_size > CONFIG_TPM2_EVENT_LOG_SIZE) {
event_log.truncated = true;
return EFI_VOLUME_FULL;
}
@@ -125,7 +125,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
return ret;
/* if GetEventLog has been called update FinalEventLog as well */
- if (event_log.final_pos + event_size > TPM2_EVENT_LOG_SIZE)
+ if (event_log.final_pos + event_size > CONFIG_TPM2_EVENT_LOG_SIZE)
return EFI_VOLUME_FULL;
log = (void *)((uintptr_t)event_log.final_buffer + event_log.final_pos);
@@ -823,12 +823,12 @@ static efi_status_t create_final_event(void)
* EFI_TCG2_GET_EVENT_LOGS need to be stored in an instance of an
* EFI_CONFIGURATION_TABLE
*/
- ret = efi_allocate_pool(EFI_ACPI_MEMORY_NVS, TPM2_EVENT_LOG_SIZE,
+ ret = efi_allocate_pool(EFI_ACPI_MEMORY_NVS, CONFIG_TPM2_EVENT_LOG_SIZE,
&event_log.final_buffer);
if (ret != EFI_SUCCESS)
goto out;
- memset(event_log.final_buffer, 0xff, TPM2_EVENT_LOG_SIZE);
+ memset(event_log.final_buffer, 0xff, CONFIG_TPM2_EVENT_LOG_SIZE);
final_event = event_log.final_buffer;
final_event->number_of_events = 0;
final_event->version = EFI_TCG2_FINAL_EVENTS_TABLE_VERSION;
@@ -914,7 +914,8 @@ static efi_status_t efi_init_event_log(void)
if (tcg2_platform_get_tpm2(&dev))
return EFI_DEVICE_ERROR;
- ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, TPM2_EVENT_LOG_SIZE,
+ ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA,
+ CONFIG_TPM2_EVENT_LOG_SIZE,
(void **)&event_log.buffer);
if (ret != EFI_SUCCESS)
return ret;
@@ -923,7 +924,7 @@ static efi_status_t efi_init_event_log(void)
* initialize log area as 0xff so the OS can easily figure out the
* last log entry
*/
- memset(event_log.buffer, 0xff, TPM2_EVENT_LOG_SIZE);
+ memset(event_log.buffer, 0xff, CONFIG_TPM2_EVENT_LOG_SIZE);
/*
* The log header is defined to be in SHA1 event log entry format.
@@ -940,7 +941,7 @@ static efi_status_t efi_init_event_log(void)
* platforms can use different ways to do so.
*/
elog.log = event_log.buffer;
- elog.log_size = TPM2_EVENT_LOG_SIZE;
+ elog.log_size = CONFIG_TPM2_EVENT_LOG_SIZE;
rc = tcg2_log_prepare_buffer(dev, &elog, false);
if (rc) {
ret = (rc == -ENOBUFS) ? EFI_BUFFER_TOO_SMALL : EFI_DEVICE_ERROR;
diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index bc750b7ca19..9ca7933c094 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -44,12 +44,134 @@ static int tpm2_update_active_banks(struct udevice *dev)
return 0;
}
-u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
+static void tpm2_print_selected_algorithm_name(u32 selected)
{
+ size_t i;
+ const char *str;
+
+ for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {
+ const struct digest_info *algo = &hash_algo_list[i];
+
+ if (!(selected & algo->hash_mask))
+ continue;
+
+ str = tpm2_algorithm_name(algo->hash_alg);
+ if (str)
+ log_info("%s\n", str);
+ }
+}
+
+int tpm2_scan_masks(struct udevice *dev, u32 log_active, u32 *mask)
+{
+ struct tpml_pcr_selection pcrs;
+ u32 active = 0;
+ u32 supported = 0;
+ int rc, i;
+
+ *mask = 0;
+
+ rc = tpm2_get_pcr_info(dev, &pcrs);
+ if (rc)
+ return rc;
+
+ for (i = 0; i < pcrs.count; i++) {
+ struct tpms_pcr_selection *sel = &pcrs.selection[i];
+ size_t j;
+ u32 hash_mask = 0;
+
+ for (j = 0; j < ARRAY_SIZE(hash_algo_list); j++) {
+ if (hash_algo_list[j].hash_alg == sel->hash)
+ hash_mask = hash_algo_list[j].hash_mask;
+ }
+
+ if (tpm2_algorithm_supported(sel->hash))
+ supported |= hash_mask;
+
+ if (tpm2_is_active_bank(sel))
+ active |= hash_mask;
+ }
+
+ /* All eventlog algorithm(s) must be supported */
+ if (log_active & ~supported) {
+ log_err("EventLog contains U-Boot unsupported algorithm(s)\n");
+ tpm2_print_selected_algorithm_name(log_active & ~supported);
+ rc = -1;
+ }
+ if (log_active && active & ~log_active) {
+ log_warning("TPM active algorithm(s) not exist in eventlog\n");
+ tpm2_print_selected_algorithm_name(active & ~log_active);
+ *mask = log_active;
+ }
+
+ /* Any active algorithm(s) which are not supported must be removed */
+ if (active & ~supported) {
+ log_warning("TPM active algorithm(s) unsupported by u-boot\n");
+ tpm2_print_selected_algorithm_name(active & ~supported);
+ if (*mask)
+ *mask = active & supported & *mask;
+ else
+ *mask = active & supported;
+ }
+
+ return rc;
+}
+
+static int tpm2_pcr_allocate(struct udevice *dev, u32 algo_mask)
+{
+ struct tpml_pcr_selection pcr = { 0 };
+ u32 pcr_len = 0;
+ int rc;
+
+ rc = tpm2_get_pcr_info(dev, &pcr);
+ if (rc)
+ return rc;
+
+ rc = tpm2_pcr_config_algo(dev, algo_mask, &pcr, &pcr_len);
+ if (rc)
+ return rc;
+
+ /* Assume no password */
+ rc = tpm2_send_pcr_allocate(dev, NULL, 0, &pcr, pcr_len);
+ if (rc)
+ return rc;
+
+ /* Send TPM2_Shutdown, assume mode = TPM2_SU_CLEAR */
+ return tpm2_startup(dev, false, TPM2_SU_CLEAR);
+}
+
+int tpm2_activate_banks(struct udevice *dev, u32 log_active)
+{
+ u32 algo_mask = 0;
+ int rc;
+
+ rc = tpm2_scan_masks(dev, log_active, &algo_mask);
+ if (rc)
+ return rc;
+
+ if (algo_mask) {
+ if (!IS_ENABLED(CONFIG_TPM_PCR_ALLOCATE))
+ return -1;
+
+ rc = tpm2_pcr_allocate(dev, algo_mask);
+ if (rc)
+ return rc;
+
+ log_info("PCR allocate done, shutdown TPM and reboot\n");
+ do_reset(NULL, 0, 0, NULL);
+ log_err("reset does not work!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+u32 tpm2_startup(struct udevice *dev, bool bon, enum tpm2_startup_types mode)
+{
+ int op = bon ? TPM2_CC_STARTUP : TPM2_CC_SHUTDOWN;
const u8 command_v2[12] = {
tpm_u16(TPM2_ST_NO_SESSIONS),
tpm_u32(12),
- tpm_u32(TPM2_CC_STARTUP),
+ tpm_u32(op),
tpm_u16(mode),
};
int ret;
@@ -59,7 +181,7 @@ u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
* but will return RC_INITIALIZE otherwise.
*/
ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
- if (ret && ret != TPM2_RC_INITIALIZE)
+ if ((ret && ret != TPM2_RC_INITIALIZE) || !bon)
return ret;
return tpm2_update_active_banks(dev);
@@ -84,7 +206,7 @@ u32 tpm2_auto_start(struct udevice *dev)
rc = tpm2_self_test(dev, TPMI_YES);
if (rc == TPM2_RC_INITIALIZE) {
- rc = tpm2_startup(dev, TPM2_SU_CLEAR);
+ rc = tpm2_startup(dev, true, TPM2_SU_CLEAR);
if (rc)
return rc;
@@ -222,7 +344,10 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
if (!tpm2_check_active_banks(dev)) {
log_err("Cannot extend PCRs if all the TPM enabled algorithms are not supported\n");
- return -EINVAL;
+
+ ret = tpm2_pcr_allocate(dev, 0);
+ if (ret)
+ return -EINVAL;
}
/*
* Fill the command structure starting from the first buffer:
@@ -399,6 +524,130 @@ u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
return 0;
}
+u32 tpm2_pcr_config_algo(struct udevice *dev, u32 algo_mask,
+ struct tpml_pcr_selection *pcr, u32 *pcr_len)
+{
+ int i;
+
+ if (pcr->count > TPM2_NUM_PCR_BANKS)
+ return TPM_LIB_ERROR;
+
+ *pcr_len = sizeof(pcr->count);
+
+ for (i = 0; i < pcr->count; i++) {
+ struct tpms_pcr_selection *sel = &pcr->selection[i];
+ u8 pad = 0;
+ int j;
+
+ if (sel->size_of_select > TPM2_PCR_SELECT_MAX)
+ return TPM_LIB_ERROR;
+
+ /*
+ * Found the algorithm (bank) that matches, and enable all PCR
+ * bits.
+ * TODO: only select the bits needed
+ */
+ for (j = 0; j < ARRAY_SIZE(hash_algo_list); j++) {
+ if (hash_algo_list[j].hash_alg != sel->hash)
+ continue;
+
+ if (algo_mask & hash_algo_list[j].hash_mask)
+ pad = 0xff;
+ }
+
+ for (j = 0; j < sel->size_of_select; j++)
+ sel->pcr_select[j] = pad;
+
+ log_info("set bank[%d] %s %s\n", i,
+ tpm2_algorithm_name(sel->hash),
+ tpm2_is_active_bank(sel) ? "on" : "off");
+
+ *pcr_len += sizeof(sel->hash) + sizeof(sel->size_of_select) +
+ sel->size_of_select;
+ }
+
+ return 0;
+}
+
+u32 tpm2_send_pcr_allocate(struct udevice *dev, const char *pw,
+ const ssize_t pw_sz, struct tpml_pcr_selection *pcr,
+ u32 pcr_len)
+{
+ /* Length of the message header, up to start of password */
+ uint offset = 27;
+ u8 command_v2[COMMAND_BUFFER_SIZE] = {
+ tpm_u16(TPM2_ST_SESSIONS), /* TAG */
+ tpm_u32(offset + pw_sz + pcr_len), /* Length */
+ tpm_u32(TPM2_CC_PCR_ALLOCATE), /* Command code */
+
+ /* handles 4 bytes */
+ tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
+
+ /* AUTH_SESSION */
+ tpm_u32(9 + pw_sz), /* Authorization size */
+ tpm_u32(TPM2_RS_PW), /* Session handle */
+ tpm_u16(0), /* Size of <nonce> */
+ /* <nonce> (if any) */
+ 0, /* Attributes: Cont/Excl/Rst */
+ tpm_u16(pw_sz), /* Size of <hmac/password> */
+ /* STRING(pw) <hmac/password> (if any) */
+
+ /* TPML_PCR_SELECTION */
+ };
+ u8 response[COMMAND_BUFFER_SIZE];
+ size_t response_len = COMMAND_BUFFER_SIZE;
+ u32 i;
+ int ret;
+
+ /*
+ * Fill the command structure starting from the first buffer:
+ * the password (if any)
+ */
+ if (pack_byte_string(command_v2, sizeof(command_v2), "s", offset, pw,
+ pw_sz))
+ return TPM_LIB_ERROR;
+
+ offset += pw_sz;
+
+ /* Pack the count field */
+ if (pack_byte_string(command_v2, sizeof(command_v2), "d", offset, pcr->count))
+ return TPM_LIB_ERROR;
+
+ offset += sizeof(pcr->count);
+
+ /* Pack each tpms_pcr_selection */
+ for (i = 0; i < pcr->count; i++) {
+ struct tpms_pcr_selection *sel = &pcr->selection[i];
+
+ /* Pack hash (16-bit) */
+ if (pack_byte_string(command_v2, sizeof(command_v2), "w", offset,
+ sel->hash))
+ return TPM_LIB_ERROR;
+
+ offset += sizeof(sel->hash);
+
+ /* Pack size_of_select (8-bit) */
+ if (pack_byte_string(command_v2, sizeof(command_v2), "b", offset,
+ sel->size_of_select))
+ return TPM_LIB_ERROR;
+
+ offset += sizeof(sel->size_of_select);
+
+ /* Pack pcr_select array */
+ if (pack_byte_string(command_v2, sizeof(command_v2), "s", offset,
+ sel->pcr_select, sel->size_of_select))
+ return TPM_LIB_ERROR;
+
+ offset += sel->size_of_select;
+ }
+
+ ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
+ if (!ret)
+ tpm_init(dev);
+
+ return ret;
+}
+
static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
{
u8 response[(sizeof(struct tpms_capability_data) -
diff --git a/lib/tpm_api.c b/lib/tpm_api.c
index 39a5121e302..576d601e5ff 100644
--- a/lib/tpm_api.c
+++ b/lib/tpm_api.c
@@ -28,7 +28,7 @@ u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
case TPM_ST_DEACTIVATED:
return -EINVAL;
}
- return tpm2_startup(dev, type);
+ return tpm2_startup(dev, true, type);
} else {
return -ENOSYS;
}
@@ -60,7 +60,7 @@ u32 tpm_resume(struct udevice *dev)
if (tpm_is_v1(dev))
return tpm1_startup(dev, TPM_ST_STATE);
else if (tpm_is_v2(dev))
- return tpm2_startup(dev, TPM2_SU_STATE);
+ return tpm2_startup(dev, true, TPM2_SU_STATE);
else
return -ENOSYS;
}
diff --git a/lib/tpm_tcg2.c b/lib/tpm_tcg2.c
index 4134d93a358..c314b401d0b 100644
--- a/lib/tpm_tcg2.c
+++ b/lib/tpm_tcg2.c
@@ -19,6 +19,7 @@
#include <linux/unaligned/generic.h>
#include <linux/unaligned/le_byteshift.h>
#include "tpm-utils.h"
+#include <bloblist.h>
int tcg2_get_pcr_info(struct udevice *dev, u32 *supported_bank, u32 *active_bank,
u32 *bank_num)
@@ -358,12 +359,12 @@ static int tcg2_replay_eventlog(struct tcg2_event_log *elog,
return 0;
}
-static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
+static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog,
+ u32 *log_active)
{
struct tpml_digest_values digest_list;
struct tcg_efi_spec_id_event *event;
struct tcg_pcr_event *log;
- u32 log_active;
u32 calc_size;
u32 active;
u32 count;
@@ -374,6 +375,8 @@ static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
int rc;
u32 i;
+ *log_active = 0;
+
if (elog->log_size <= offsetof(struct tcg_pcr_event, event))
return 0;
@@ -419,7 +422,6 @@ static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
* algorithms, so just check the EvenLog against the TPM active ones.
*/
digest_list.count = 0;
- log_active = 0;
for (i = 0; i < count; ++i) {
algo = get_unaligned_le16(&event->digest_sizes[i].algorithm_id);
mask = tcg2_algorithm_to_mask(algo);
@@ -445,17 +447,15 @@ static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
algo);
return -1;
}
- log_active |= mask;
+ *log_active |= mask;
}
rc = tcg2_get_active_pcr_banks(dev, &active);
if (rc)
return rc;
/* If the EventLog and active algorithms don't match exit */
- if (log_active != active) {
- log_err("EventLog doesn't contain all active PCR banks\n");
- return -1;
- }
+ if (*log_active != active)
+ return -ERESTARTSYS;
/* Read PCR0 to check if previous firmware extended the PCRs or not. */
rc = tcg2_pcr_read(dev, 0, &digest_list);
@@ -552,43 +552,21 @@ int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog,
bool ignore_existing_log)
{
struct tcg2_event_log log;
- int rc, i;
+ int rc;
+ u32 log_active = 0;
elog->log_position = 0;
elog->found = false;
- /*
- * Make sure U-Boot is compiled with all the active PCRs
- * since we are about to create an EventLog and we won't
- * measure anything if the PCR banks don't match
- */
- if (!tpm2_check_active_banks(dev)) {
- log_err("Cannot create EventLog\n");
- log_err("Mismatch between U-Boot and TPM hash algos\n");
- log_info("TPM:\n");
- tpm2_print_active_banks(dev);
- log_info("U-Boot:\n");
- for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {
- const struct digest_info *algo = &hash_algo_list[i];
- const char *str;
-
- if (!algo->supported)
- continue;
-
- str = tpm2_algorithm_name(algo->hash_alg);
- if (str)
- log_info("%s\n", str);
- }
- return -EINVAL;
- }
-
rc = tcg2_platform_get_log(dev, (void **)&log.log, &log.log_size);
if (!rc) {
log.log_position = 0;
log.found = false;
if (!ignore_existing_log) {
- rc = tcg2_log_parse(dev, &log);
+ rc = tcg2_log_parse(dev, &log, &log_active);
+ if (rc == -ERESTARTSYS && log_active)
+ goto pcr_allocate;
if (rc)
return rc;
}
@@ -615,6 +593,11 @@ int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog,
elog->found = log.found;
}
+pcr_allocate:
+ rc = tpm2_activate_banks(dev, log_active);
+ if (rc)
+ return rc;
+
/*
* Initialize the log buffer if no log was discovered and the buffer is
* valid. User's can pass in their own buffer as a fallback if no
@@ -672,21 +655,42 @@ void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
__weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size)
{
- const __be32 *addr_prop;
- const __be32 *size_prop;
+ const __be32 *addr_prop = NULL;
+ const __be32 *size_prop = NULL;
int asize;
int ssize;
+ struct ofnode_phandle_args args;
+ phys_addr_t a;
+ fdt_size_t s;
*addr = NULL;
*size = 0;
- addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize);
- if (!addr_prop)
- addr_prop = dev_read_prop(dev, "linux,sml-base", &asize);
+ *addr = bloblist_get_blob(BLOBLISTT_TPM_EVLOG, size);
+ if (*addr && *size) {
+ *addr = map_physmem((uintptr_t)(*addr), *size, MAP_NOCACHE);
+ return 0;
+ }
- size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize);
- if (!size_prop)
+ /*
+ * TODO:
+ * Replace BLOBLIST with a new kconfig for handoff all components
+ * (fdt, tpm event log, etc...) from previous boot stage via bloblist
+ * mandatorily following Firmware Handoff spec.
+ */
+ if (!CONFIG_IS_ENABLED(BLOBLIST)) {
+ addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize);
+ size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize);
+ }
+
+ /*
+ * If no eventlog was observed, a sml buffer is required for the kernel
+ * to discover the eventlog.
+ */
+ if (!addr_prop || !size_prop) {
+ addr_prop = dev_read_prop(dev, "linux,sml-base", &asize);
size_prop = dev_read_prop(dev, "linux,sml-size", &ssize);
+ }
if (addr_prop && size_prop) {
u64 a = of_read_number(addr_prop, asize / sizeof(__be32));
@@ -694,22 +698,19 @@ __weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size)
*addr = map_physmem(a, s, MAP_NOCACHE);
*size = (u32)s;
- } else {
- struct ofnode_phandle_args args;
- phys_addr_t a;
- fdt_size_t s;
- if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0,
- 0, &args))
- return -ENODEV;
+ return 0;
+ }
- a = ofnode_get_addr_size(args.node, "reg", &s);
- if (a == FDT_ADDR_T_NONE)
- return -ENOMEM;
+ if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0, 0, &args))
+ return -ENODEV;
- *addr = map_physmem(a, s, MAP_NOCACHE);
- *size = (u32)s;
- }
+ a = ofnode_get_addr_size(args.node, "reg", &s);
+ if (a == FDT_ADDR_T_NONE)
+ return -ENOMEM;
+
+ *addr = map_physmem(a, s, MAP_NOCACHE);
+ *size = (u32)s;
return 0;
}