const void *fdt_offset_ptr(const void *fdt, int offset, int len) { const char *p; if (fdt_version(fdt) >= 0x11) if (((offset + len) < offset) || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; p = _fdt_offset_ptr(fdt, offset); if (p + len < p) return NULL; return p; }
const struct fdt_property *fdt_get_property_namelen(const void *fdt, int nodeoffset, const char *name, int namelen, int *lenp) { uint32_t tag; const struct fdt_property *prop; int offset, nextoffset; int err; if (((err = fdt_check_header(fdt)) != 0) || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) goto fail; nextoffset = err; do { offset = nextoffset; tag = fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_END: if (nextoffset < 0) err = nextoffset; else /* FDT_END tag with unclosed nodes */ err = -FDT_ERR_BADSTRUCTURE; goto fail; case FDT_PROP: prop = _fdt_offset_ptr(fdt, offset); if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), name, namelen)) { /* Found it! */ if (lenp) *lenp = fdt32_to_cpu(prop->len); return prop; } break; } } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE)); err = -FDT_ERR_NOTFOUND; fail: if (lenp) *lenp = err; return NULL; }
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) { const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); int err; if (((err = fdt_check_header(fdt)) != 0) || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) goto fail; if (len) *len = strlen(nh->name); return nh->name; fail: if (len) *len = err; return NULL; }
const struct fdt_property *fdt_get_property_by_offset(const void *fdt, int offset, int *lenp) { int err; const struct fdt_property *prop; if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { if (lenp) *lenp = err; return NULL; } prop = _fdt_offset_ptr(fdt, offset); if (lenp) *lenp = fdt32_to_cpu(prop->len); return prop; }
/* * offset: propert의 offset * lenp: propert내의 value 길이 저장 * offset을 이용하여 property에 접근 및 property 구조체와, value 길이를 받아옴 */ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, int offset, int *lenp) { int err; const struct fdt_property *prop; // property의 유효성을 체크 if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { if (lenp) *lenp = err; return NULL; } // property 구조체를 가져옴 prop = _fdt_offset_ptr(fdt, offset); // property의 value의 길이 저장 if (lenp) *lenp = fdt32_to_cpu(prop->len); return prop; }
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) { const char *p; /* 0x11 = 17, Default version */ if (fdt_version(fdt) >= 0x11) /* 1. offset의 overflow체크? len은 unsigned int임. * 2. offset+len은 size_dt_struct보다 작거나 같아야만 한다. * * ex) dt_struct * +-------------+ + * | | | * | something | | dt_struct_size * | | | * +-------------+ <-- dt_struct_offset + * * _fdt_offset_ptr 내부에서 dt_struct_offset + offset을 한다. * 따라서, offset + len 이 dt_struct_size 보다 크면 안된다. * * 아래 if를 거꾸로 쓰면, * offset < offset + len < fdt_size_dt_struct(fdt) * * len이 unsigned!!! 절대 음수가 들어올 수 없음. * 따라서 오버플로우 방어코드라고 추정.. */ if (((offset + len) < offset) || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; /* offset은 Valid 검증된 이후 */ p = _fdt_offset_ptr(fdt, offset); if (p + len < p) return NULL; return p; }