mirror of https://github.com/ipxe/ipxe.git
[fdt] Allow for parsing device trees where the length is known in advance
Allow for parsing device trees where an external factor (such as a downloaded image length) determines the maximum length, which must be validated against the length within the device tree header. Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/1437/head
parent
2399c79980
commit
3860313dd5
|
@ -123,6 +123,7 @@ _sbi_start:
|
||||||
/* Register device tree */
|
/* Register device tree */
|
||||||
la a0, sysfdt
|
la a0, sysfdt
|
||||||
mv a1, s1
|
mv a1, s1
|
||||||
|
li a2, -1
|
||||||
call fdt_parse
|
call fdt_parse
|
||||||
|
|
||||||
/* Call main program */
|
/* Call main program */
|
||||||
|
|
|
@ -82,7 +82,7 @@ static int fdt_traverse ( struct fdt *fdt,
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
assert ( pos->offset < fdt->len );
|
assert ( pos->offset <= fdt->len );
|
||||||
assert ( ( pos->offset & ( FDT_STRUCTURE_ALIGN - 1 ) ) == 0 );
|
assert ( ( pos->offset & ( FDT_STRUCTURE_ALIGN - 1 ) ) == 0 );
|
||||||
|
|
||||||
/* Clear descriptor */
|
/* Clear descriptor */
|
||||||
|
@ -453,14 +453,28 @@ int fdt_mac ( struct fdt *fdt, unsigned int offset,
|
||||||
*
|
*
|
||||||
* @v fdt Device tree
|
* @v fdt Device tree
|
||||||
* @v hdr Device tree header
|
* @v hdr Device tree header
|
||||||
|
* @v max_len Maximum device tree length
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
int fdt_parse ( struct fdt *fdt, const struct fdt_header *hdr ) {
|
int fdt_parse ( struct fdt *fdt, const struct fdt_header *hdr,
|
||||||
|
size_t max_len ) {
|
||||||
const uint8_t *end;
|
const uint8_t *end;
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
if ( sizeof ( fdt ) > max_len ) {
|
||||||
|
DBGC ( fdt, "FDT length %#zx too short for header\n",
|
||||||
|
max_len );
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Record device tree location */
|
/* Record device tree location */
|
||||||
fdt->hdr = hdr;
|
fdt->hdr = hdr;
|
||||||
fdt->len = be32_to_cpu ( hdr->totalsize );
|
fdt->len = be32_to_cpu ( hdr->totalsize );
|
||||||
|
if ( fdt->len > max_len ) {
|
||||||
|
DBGC ( fdt, "FDT has invalid length %#zx / %#zx\n",
|
||||||
|
fdt->len, max_len );
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
DBGC ( fdt, "FDT version %d at %p+%#04zx\n",
|
DBGC ( fdt, "FDT version %d at %p+%#04zx\n",
|
||||||
be32_to_cpu ( hdr->version ), fdt->hdr, fdt->len );
|
be32_to_cpu ( hdr->version ), fdt->hdr, fdt->len );
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,7 @@ extern int fdt_u64 ( struct fdt *fdt, unsigned int offset, const char *name,
|
||||||
uint64_t *value );
|
uint64_t *value );
|
||||||
extern int fdt_mac ( struct fdt *fdt, unsigned int offset,
|
extern int fdt_mac ( struct fdt *fdt, unsigned int offset,
|
||||||
struct net_device *netdev );
|
struct net_device *netdev );
|
||||||
extern int fdt_parse ( struct fdt *fdt, const struct fdt_header *hdr );
|
extern int fdt_parse ( struct fdt *fdt, const struct fdt_header *hdr,
|
||||||
|
size_t max_len );
|
||||||
|
|
||||||
#endif /* _IPXE_FDT_H */
|
#endif /* _IPXE_FDT_H */
|
||||||
|
|
|
@ -54,7 +54,7 @@ static void efi_fdt_init ( void ) {
|
||||||
DBGC ( &efi_fdt, "EFIFDT configuration table at %p\n", efi_fdt );
|
DBGC ( &efi_fdt, "EFIFDT configuration table at %p\n", efi_fdt );
|
||||||
|
|
||||||
/* Parse as system device tree */
|
/* Parse as system device tree */
|
||||||
if ( ( rc = fdt_parse ( &sysfdt, efi_fdt ) ) != 0 ) {
|
if ( ( rc = fdt_parse ( &sysfdt, efi_fdt, -1UL ) ) != 0 ) {
|
||||||
DBGC ( &efi_fdt, "EFIFDT could not parse: %s\n",
|
DBGC ( &efi_fdt, "EFIFDT could not parse: %s\n",
|
||||||
strerror ( rc ) );
|
strerror ( rc ) );
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue