Changeset View
Changeset View
Standalone View
Standalone View
sys/contrib/libfdt/fdt.c
Show First 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
#include "libfdt_env.h" | #include "libfdt_env.h" | ||||
#include <fdt.h> | #include <fdt.h> | ||||
#include <libfdt.h> | #include <libfdt.h> | ||||
#include "libfdt_internal.h" | #include "libfdt_internal.h" | ||||
int fdt_check_header(const void *fdt) | /* | ||||
* Minimal sanity check for a read-only tree. fdt_ro_probe_() checks | |||||
* that the given buffer contains what appears to be a flattened | |||||
* device tree with sane information in its header. | |||||
*/ | |||||
int fdt_ro_probe_(const void *fdt) | |||||
{ | { | ||||
if (fdt_magic(fdt) == FDT_MAGIC) { | if (fdt_magic(fdt) == FDT_MAGIC) { | ||||
/* Complete tree */ | /* Complete tree */ | ||||
if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) | if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) | ||||
return -FDT_ERR_BADVERSION; | return -FDT_ERR_BADVERSION; | ||||
if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) | if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) | ||||
return -FDT_ERR_BADVERSION; | return -FDT_ERR_BADVERSION; | ||||
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) { | } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { | ||||
/* Unfinished sequential-write blob */ | /* Unfinished sequential-write blob */ | ||||
if (fdt_size_dt_struct(fdt) == 0) | if (fdt_size_dt_struct(fdt) == 0) | ||||
return -FDT_ERR_BADSTATE; | return -FDT_ERR_BADSTATE; | ||||
} else { | } else { | ||||
return -FDT_ERR_BADMAGIC; | return -FDT_ERR_BADMAGIC; | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off) | |||||
{ | |||||
return (off >= hdrsize) && (off <= totalsize); | |||||
} | |||||
static int check_block_(uint32_t hdrsize, uint32_t totalsize, | |||||
uint32_t base, uint32_t size) | |||||
{ | |||||
if (!check_off_(hdrsize, totalsize, base)) | |||||
return 0; /* block start out of bounds */ | |||||
if ((base + size) < base) | |||||
return 0; /* overflow */ | |||||
if (!check_off_(hdrsize, totalsize, base + size)) | |||||
return 0; /* block end out of bounds */ | |||||
return 1; | |||||
} | |||||
size_t fdt_header_size_(uint32_t version) | |||||
{ | |||||
if (version <= 1) | |||||
return FDT_V1_SIZE; | |||||
else if (version <= 2) | |||||
return FDT_V2_SIZE; | |||||
else if (version <= 3) | |||||
return FDT_V3_SIZE; | |||||
else if (version <= 16) | |||||
return FDT_V16_SIZE; | |||||
else | |||||
return FDT_V17_SIZE; | |||||
} | |||||
int fdt_check_header(const void *fdt) | |||||
{ | |||||
size_t hdrsize; | |||||
if (fdt_magic(fdt) != FDT_MAGIC) | |||||
return -FDT_ERR_BADMAGIC; | |||||
hdrsize = fdt_header_size(fdt); | |||||
if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) | |||||
|| (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)) | |||||
return -FDT_ERR_BADVERSION; | |||||
if (fdt_version(fdt) < fdt_last_comp_version(fdt)) | |||||
return -FDT_ERR_BADVERSION; | |||||
if ((fdt_totalsize(fdt) < hdrsize) | |||||
|| (fdt_totalsize(fdt) > INT_MAX)) | |||||
return -FDT_ERR_TRUNCATED; | |||||
/* Bounds check memrsv block */ | |||||
if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt))) | |||||
return -FDT_ERR_TRUNCATED; | |||||
/* Bounds check structure block */ | |||||
if (fdt_version(fdt) < 17) { | |||||
if (!check_off_(hdrsize, fdt_totalsize(fdt), | |||||
fdt_off_dt_struct(fdt))) | |||||
return -FDT_ERR_TRUNCATED; | |||||
} else { | |||||
if (!check_block_(hdrsize, fdt_totalsize(fdt), | |||||
fdt_off_dt_struct(fdt), | |||||
fdt_size_dt_struct(fdt))) | |||||
return -FDT_ERR_TRUNCATED; | |||||
} | |||||
/* Bounds check strings block */ | |||||
if (!check_block_(hdrsize, fdt_totalsize(fdt), | |||||
fdt_off_dt_strings(fdt), fdt_size_dt_strings(fdt))) | |||||
return -FDT_ERR_TRUNCATED; | |||||
return 0; | |||||
} | |||||
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) | const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) | ||||
{ | { | ||||
unsigned absoffset = offset + fdt_off_dt_struct(fdt); | unsigned absoffset = offset + fdt_off_dt_struct(fdt); | ||||
if ((absoffset < offset) | if ((absoffset < offset) | ||||
|| ((absoffset + len) < absoffset) | || ((absoffset + len) < absoffset) | ||||
|| (absoffset + len) > fdt_totalsize(fdt)) | || (absoffset + len) > fdt_totalsize(fdt)) | ||||
return NULL; | return NULL; | ||||
▲ Show 20 Lines • Show All 154 Lines • ▼ Show 20 Lines | const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) | ||||
for (p = strtab; p <= last; p++) | for (p = strtab; p <= last; p++) | ||||
if (memcmp(p, s, len) == 0) | if (memcmp(p, s, len) == 0) | ||||
return p; | return p; | ||||
return NULL; | return NULL; | ||||
} | } | ||||
int fdt_move(const void *fdt, void *buf, int bufsize) | int fdt_move(const void *fdt, void *buf, int bufsize) | ||||
{ | { | ||||
FDT_CHECK_HEADER(fdt); | FDT_RO_PROBE(fdt); | ||||
if (fdt_totalsize(fdt) > bufsize) | if (fdt_totalsize(fdt) > bufsize) | ||||
return -FDT_ERR_NOSPACE; | return -FDT_ERR_NOSPACE; | ||||
memmove(buf, fdt, fdt_totalsize(fdt)); | memmove(buf, fdt, fdt_totalsize(fdt)); | ||||
return 0; | return 0; | ||||
} | } |