Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
E
ezynq
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Elphel
ezynq
Commits
857f62fe
Commit
857f62fe
authored
Dec 26, 2018
by
Oleg Dzhimiev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fdt & fit
parent
de50fa99
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
1470 additions
and
0 deletions
+1470
-0
fdt_host.h
u-boot-tree/tools/fdt_host.h
+33
-0
fdtgrep.c
u-boot-tree/tools/fdtgrep.c
+1231
-0
fit_check_sign.c
u-boot-tree/tools/fit_check_sign.c
+97
-0
fit_info.c
u-boot-tree/tools/fit_info.c
+109
-0
No files found.
u-boot-tree/tools/fdt_host.h
0 → 100644
View file @
857f62fe
/*
* (C) Copyright 2008 Semihalf
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __FDT_HOST_H__
#define __FDT_HOST_H__
/* Make sure to include u-boot version of libfdt include files */
#include "../include/libfdt.h"
#include "../include/fdt_support.h"
/**
* fdt_remove_unused_strings() - Remove any unused strings from an FDT
*
* This creates a new device tree in @new with unused strings removed. The
* called can then use fdt_pack() to minimise the space consumed.
*
* @old: Old device tree blog
* @new: Place to put new device tree blob, which must be as large as
* @old
* @return
* 0, on success
* -FDT_ERR_BADOFFSET, corrupt device tree
* -FDT_ERR_NOSPACE, out of space, which should not happen unless there
* is something very wrong with the device tree input
*/
int
fdt_remove_unused_strings
(
const
void
*
old
,
void
*
new
);
int
fit_check_sign
(
const
void
*
working_fdt
,
const
void
*
key
);
#endif
/* __FDT_HOST_H__ */
u-boot-tree/tools/fdtgrep.c
0 → 100644
View file @
857f62fe
/*
* Copyright (c) 2013, Google Inc.
* Written by Simon Glass <sjg@chromium.org>
*
* SPDX-License-Identifier: GPL-2.0+
*
* Perform a grep of an FDT either displaying the source subset or producing
* a new .dtb subset which can be used as required.
*/
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "fdt_host.h"
#include "libfdt_internal.h"
/* Define DEBUG to get some debugging output on stderr */
#ifdef DEBUG
#define debug(a, b...) fprintf(stderr, a, ## b)
#else
#define debug(a, b...)
#endif
/* A linked list of values we are grepping for */
struct
value_node
{
int
type
;
/* Types this value matches (FDT_IS... mask) */
int
include
;
/* 1 to include matches, 0 to exclude */
const
char
*
string
;
/* String to match */
struct
value_node
*
next
;
/* Pointer to next node, or NULL */
};
/* Output formats we support */
enum
output_t
{
OUT_DTS
,
/* Device tree source */
OUT_DTB
,
/* Valid device tree binary */
OUT_BIN
,
/* Fragment of .dtb, for hashing */
};
/* Holds information which controls our output and options */
struct
display_info
{
enum
output_t
output
;
/* Output format */
int
add_aliases
;
/* Add aliases node to output */
int
all
;
/* Display all properties/nodes */
int
colour
;
/* Display output in ANSI colour */
int
region_list
;
/* Output a region list */
int
flags
;
/* Flags (FDT_REG_...) */
int
list_strings
;
/* List strings in string table */
int
show_offset
;
/* Show offset */
int
show_addr
;
/* Show address */
int
header
;
/* Output an FDT header */
int
diff
;
/* Show +/- diff markers */
int
include_root
;
/* Include the root node and all properties */
int
remove_strings
;
/* Remove unused strings */
int
show_dts_version
;
/* Put '/dts-v1/;' on the first line */
int
types_inc
;
/* Mask of types that we include (FDT_IS...) */
int
types_exc
;
/* Mask of types that we exclude (FDT_IS...) */
int
invert
;
/* Invert polarity of match */
struct
value_node
*
value_head
;
/* List of values to match */
const
char
*
output_fname
;
/* Output filename */
FILE
*
fout
;
/* File to write dts/dtb output */
};
static
void
report_error
(
const
char
*
where
,
int
err
)
{
fprintf
(
stderr
,
"Error at '%s': %s
\n
"
,
where
,
fdt_strerror
(
err
));
}
/* Supported ANSI colours */
enum
{
COL_BLACK
,
COL_RED
,
COL_GREEN
,
COL_YELLOW
,
COL_BLUE
,
COL_MAGENTA
,
COL_CYAN
,
COL_WHITE
,
COL_NONE
=
-
1
,
};
/**
* print_ansi_colour() - Print out the ANSI sequence for a colour
*
* @fout: Output file
* @col: Colour to output (COL_...), or COL_NONE to reset colour
*/
static
void
print_ansi_colour
(
FILE
*
fout
,
int
col
)
{
if
(
col
==
COL_NONE
)
fprintf
(
fout
,
"
\033
[0m"
);
else
fprintf
(
fout
,
"
\033
[1;%dm"
,
col
+
30
);
}
/**
* value_add() - Add a new value to our list of things to grep for
*
* @disp: Display structure, holding info about our options
* @headp: Pointer to header pointer of list
* @type: Type of this value (FDT_IS_...)
* @include: 1 if we want to include matches, 0 to exclude
* @str: String value to match
*/
static
int
value_add
(
struct
display_info
*
disp
,
struct
value_node
**
headp
,
int
type
,
int
include
,
const
char
*
str
)
{
struct
value_node
*
node
;
/*
* Keep track of which types we are excluding/including. We don't
* allow both including and excluding things, because it doesn't make
* sense. 'Including' means that everything not mentioned is
* excluded. 'Excluding' means that everything not mentioned is
* included. So using the two together would be meaningless.
*/
if
(
include
)
disp
->
types_inc
|=
type
;
else
disp
->
types_exc
|=
type
;
if
(
disp
->
types_inc
&
disp
->
types_exc
&
type
)
{
fprintf
(
stderr
,
"Cannot use both include and exclude for '%s'
\n
"
,
str
);
return
-
1
;
}
str
=
strdup
(
str
);
node
=
malloc
(
sizeof
(
*
node
));
if
(
!
str
||
!
node
)
{
fprintf
(
stderr
,
"Out of memory
\n
"
);
return
-
1
;
}
node
->
next
=
*
headp
;
node
->
type
=
type
;
node
->
include
=
include
;
node
->
string
=
str
;
*
headp
=
node
;
return
0
;
}
static
bool
util_is_printable_string
(
const
void
*
data
,
int
len
)
{
const
char
*
s
=
data
;
const
char
*
ss
,
*
se
;
/* zero length is not */
if
(
len
==
0
)
return
0
;
/* must terminate with zero */
if
(
s
[
len
-
1
]
!=
'\0'
)
return
0
;
se
=
s
+
len
;
while
(
s
<
se
)
{
ss
=
s
;
while
(
s
<
se
&&
*
s
&&
isprint
((
unsigned
char
)
*
s
))
s
++
;
/* not zero, or not done yet */
if
(
*
s
!=
'\0'
||
s
==
ss
)
return
0
;
s
++
;
}
return
1
;
}
static
void
utilfdt_print_data
(
const
char
*
data
,
int
len
)
{
int
i
;
const
char
*
p
=
data
;
const
char
*
s
;
/* no data, don't print */
if
(
len
==
0
)
return
;
if
(
util_is_printable_string
(
data
,
len
))
{
printf
(
" = "
);
s
=
data
;
do
{
printf
(
"
\"
%s
\"
"
,
s
);
s
+=
strlen
(
s
)
+
1
;
if
(
s
<
data
+
len
)
printf
(
", "
);
}
while
(
s
<
data
+
len
);
}
else
if
((
len
%
4
)
==
0
)
{
const
uint32_t
*
cell
=
(
const
uint32_t
*
)
data
;
printf
(
" = <"
);
for
(
i
=
0
,
len
/=
4
;
i
<
len
;
i
++
)
printf
(
"0x%08x%s"
,
fdt32_to_cpu
(
cell
[
i
]),
i
<
(
len
-
1
)
?
" "
:
""
);
printf
(
">"
);
}
else
{
printf
(
" = ["
);
for
(
i
=
0
;
i
<
len
;
i
++
)
printf
(
"%02x%s"
,
*
p
++
,
i
<
len
-
1
?
" "
:
""
);
printf
(
"]"
);
}
}
/**
* display_fdt_by_regions() - Display regions of an FDT source
*
* This dumps an FDT as source, but only certain regions of it. This is the
* final stage of the grep - we have a list of regions we want to display,
* and this function displays them.
*
* @disp: Display structure, holding info about our options
* @blob: FDT blob to display
* @region: List of regions to display
* @count: Number of regions
*/
static
int
display_fdt_by_regions
(
struct
display_info
*
disp
,
const
void
*
blob
,
struct
fdt_region
region
[],
int
count
)
{
struct
fdt_region
*
reg
=
region
,
*
reg_end
=
region
+
count
;
uint32_t
off_mem_rsvmap
=
fdt_off_mem_rsvmap
(
blob
);
int
base
=
fdt_off_dt_struct
(
blob
);
int
version
=
fdt_version
(
blob
);
int
offset
,
nextoffset
;
int
tag
,
depth
,
shift
;
FILE
*
f
=
disp
->
fout
;
uint64_t
addr
,
size
;
int
in_region
;
int
file_ofs
;
int
i
;
if
(
disp
->
show_dts_version
)
fprintf
(
f
,
"/dts-v1/;
\n
"
);
if
(
disp
->
header
)
{
fprintf
(
f
,
"// magic:
\t\t
0x%x
\n
"
,
fdt_magic
(
blob
));
fprintf
(
f
,
"// totalsize:
\t\t
0x%x (%d)
\n
"
,
fdt_totalsize
(
blob
),
fdt_totalsize
(
blob
));
fprintf
(
f
,
"// off_dt_struct:
\t
0x%x
\n
"
,
fdt_off_dt_struct
(
blob
));
fprintf
(
f
,
"// off_dt_strings:
\t
0x%x
\n
"
,
fdt_off_dt_strings
(
blob
));
fprintf
(
f
,
"// off_mem_rsvmap:
\t
0x%x
\n
"
,
off_mem_rsvmap
);
fprintf
(
f
,
"// version:
\t\t
%d
\n
"
,
version
);
fprintf
(
f
,
"// last_comp_version:
\t
%d
\n
"
,
fdt_last_comp_version
(
blob
));
if
(
version
>=
2
)
{
fprintf
(
f
,
"// boot_cpuid_phys:
\t
0x%x
\n
"
,
fdt_boot_cpuid_phys
(
blob
));
}
if
(
version
>=
3
)
{
fprintf
(
f
,
"// size_dt_strings:
\t
0x%x
\n
"
,
fdt_size_dt_strings
(
blob
));
}
if
(
version
>=
17
)
{
fprintf
(
f
,
"// size_dt_struct:
\t
0x%x
\n
"
,
fdt_size_dt_struct
(
blob
));
}
fprintf
(
f
,
"
\n
"
);
}
if
(
disp
->
flags
&
FDT_REG_ADD_MEM_RSVMAP
)
{
const
struct
fdt_reserve_entry
*
p_rsvmap
;
p_rsvmap
=
(
const
struct
fdt_reserve_entry
*
)
((
const
char
*
)
blob
+
off_mem_rsvmap
);
for
(
i
=
0
;
;
i
++
)
{
addr
=
fdt64_to_cpu
(
p_rsvmap
[
i
].
address
);
size
=
fdt64_to_cpu
(
p_rsvmap
[
i
].
size
);
if
(
addr
==
0
&&
size
==
0
)
break
;
fprintf
(
f
,
"/memreserve/ %llx %llx;
\n
"
,
(
unsigned
long
long
)
addr
,
(
unsigned
long
long
)
size
);
}
}
depth
=
0
;
nextoffset
=
0
;
shift
=
4
;
/* 4 spaces per indent */
do
{
const
struct
fdt_property
*
prop
;
const
char
*
name
;
int
show
;
int
len
;
offset
=
nextoffset
;
/*
* Work out the file offset of this offset, and decide
* whether it is in the region list or not
*/
file_ofs
=
base
+
offset
;
if
(
reg
<
reg_end
&&
file_ofs
>=
reg
->
offset
+
reg
->
size
)
reg
++
;
in_region
=
reg
<
reg_end
&&
file_ofs
>=
reg
->
offset
&&
file_ofs
<
reg
->
offset
+
reg
->
size
;
tag
=
fdt_next_tag
(
blob
,
offset
,
&
nextoffset
);
if
(
tag
==
FDT_END
)
break
;
show
=
in_region
||
disp
->
all
;
if
(
show
&&
disp
->
diff
)
fprintf
(
f
,
"%c"
,
in_region
?
'+'
:
'-'
);
if
(
!
show
)
{
/* Do this here to avoid 'if (show)' in every 'case' */
if
(
tag
==
FDT_BEGIN_NODE
)
depth
++
;
else
if
(
tag
==
FDT_END_NODE
)
depth
--
;
continue
;
}
if
(
tag
!=
FDT_END
)
{
if
(
disp
->
show_addr
)
fprintf
(
f
,
"%4x: "
,
file_ofs
);
if
(
disp
->
show_offset
)
fprintf
(
f
,
"%4x: "
,
file_ofs
-
base
);
}
/* Green means included, red means excluded */
if
(
disp
->
colour
)
print_ansi_colour
(
f
,
in_region
?
COL_GREEN
:
COL_RED
);
switch
(
tag
)
{
case
FDT_PROP
:
prop
=
fdt_get_property_by_offset
(
blob
,
offset
,
NULL
);
name
=
fdt_string
(
blob
,
fdt32_to_cpu
(
prop
->
nameoff
));
fprintf
(
f
,
"%*s%s"
,
depth
*
shift
,
""
,
name
);
utilfdt_print_data
(
prop
->
data
,
fdt32_to_cpu
(
prop
->
len
));
fprintf
(
f
,
";"
);
break
;
case
FDT_NOP
:
fprintf
(
f
,
"%*s// [NOP]"
,
depth
*
shift
,
""
);
break
;
case
FDT_BEGIN_NODE
:
name
=
fdt_get_name
(
blob
,
offset
,
&
len
);
fprintf
(
f
,
"%*s%s {"
,
depth
++
*
shift
,
""
,
*
name
?
name
:
"/"
);
break
;
case
FDT_END_NODE
:
fprintf
(
f
,
"%*s};"
,
--
depth
*
shift
,
""
);
break
;
}
/* Reset colour back to normal before end of line */
if
(
disp
->
colour
)
print_ansi_colour
(
f
,
COL_NONE
);
fprintf
(
f
,
"
\n
"
);
}
while
(
1
);
/* Print a list of strings if requested */
if
(
disp
->
list_strings
)
{
const
char
*
str
;
int
str_base
=
fdt_off_dt_strings
(
blob
);
for
(
offset
=
0
;
offset
<
fdt_size_dt_strings
(
blob
);
offset
+=
strlen
(
str
)
+
1
)
{
str
=
fdt_string
(
blob
,
offset
);
int
len
=
strlen
(
str
)
+
1
;
int
show
;
/* Only print strings that are in the region */
file_ofs
=
str_base
+
offset
;
in_region
=
reg
<
reg_end
&&
file_ofs
>=
reg
->
offset
&&
file_ofs
+
len
<
reg
->
offset
+
reg
->
size
;
show
=
in_region
||
disp
->
all
;
if
(
show
&&
disp
->
diff
)
printf
(
"%c"
,
in_region
?
'+'
:
'-'
);
if
(
disp
->
show_addr
)
printf
(
"%4x: "
,
file_ofs
);
if
(
disp
->
show_offset
)
printf
(
"%4x: "
,
offset
);
printf
(
"%s
\n
"
,
str
);
}
}
return
0
;
}
/**
* dump_fdt_regions() - Dump regions of an FDT as binary data
*
* This dumps an FDT as binary, but only certain regions of it. This is the
* final stage of the grep - we have a list of regions we want to dump,
* and this function dumps them.
*
* The output of this function may or may not be a valid FDT. To ensure it
* is, these disp->flags must be set:
*
* FDT_REG_SUPERNODES: ensures that subnodes are preceded by their
* parents. Without this option, fragments of subnode data may be
* output without the supernodes above them. This is useful for
* hashing but cannot produce a valid FDT.
* FDT_REG_ADD_STRING_TAB: Adds a string table to the end of the FDT.
* Without this none of the properties will have names
* FDT_REG_ADD_MEM_RSVMAP: Adds a mem_rsvmap table - an FDT is invalid
* without this.
*
* @disp: Display structure, holding info about our options
* @blob: FDT blob to display
* @region: List of regions to display
* @count: Number of regions
* @out: Output destination
*/
static
int
dump_fdt_regions
(
struct
display_info
*
disp
,
const
void
*
blob
,
struct
fdt_region
region
[],
int
count
,
char
*
out
)
{
struct
fdt_header
*
fdt
;
int
size
,
struct_start
;
int
ptr
;
int
i
;
/* Set up a basic header (even if we don't actually write it) */
fdt
=
(
struct
fdt_header
*
)
out
;
memset
(
fdt
,
'\0'
,
sizeof
(
*
fdt
));
fdt_set_magic
(
fdt
,
FDT_MAGIC
);
struct_start
=
FDT_ALIGN
(
sizeof
(
struct
fdt_header
),
sizeof
(
struct
fdt_reserve_entry
));
fdt_set_off_mem_rsvmap
(
fdt
,
struct_start
);
fdt_set_version
(
fdt
,
FDT_LAST_SUPPORTED_VERSION
);
fdt_set_last_comp_version
(
fdt
,
FDT_FIRST_SUPPORTED_VERSION
);
/*
* Calculate the total size of the regions we are writing out. The
* first will be the mem_rsvmap if the FDT_REG_ADD_MEM_RSVMAP flag
* is set. The last will be the string table if FDT_REG_ADD_STRING_TAB
* is set.
*/
for
(
i
=
size
=
0
;
i
<
count
;
i
++
)
size
+=
region
[
i
].
size
;
/* Bring in the mem_rsvmap section from the old file if requested */
if
(
count
>
0
&&
(
disp
->
flags
&
FDT_REG_ADD_MEM_RSVMAP
))
{
struct_start
+=
region
[
0
].
size
;
size
-=
region
[
0
].
size
;
}
fdt_set_off_dt_struct
(
fdt
,
struct_start
);
/* Update the header to have the correct offsets/sizes */
if
(
count
>=
2
&&
(
disp
->
flags
&
FDT_REG_ADD_STRING_TAB
))
{
int
str_size
;
str_size
=
region
[
count
-
1
].
size
;
fdt_set_size_dt_struct
(
fdt
,
size
-
str_size
);
fdt_set_off_dt_strings
(
fdt
,
struct_start
+
size
-
str_size
);
fdt_set_size_dt_strings
(
fdt
,
str_size
);
fdt_set_totalsize
(
fdt
,
struct_start
+
size
);
}
/* Write the header if required */
ptr
=
0
;
if
(
disp
->
header
)
{
ptr
=
sizeof
(
*
fdt
);
while
(
ptr
<
fdt_off_mem_rsvmap
(
fdt
))
out
[
ptr
++
]
=
'\0'
;
}
/* Output all the nodes including any mem_rsvmap/string table */
for
(
i
=
0
;
i
<
count
;
i
++
)
{
struct
fdt_region
*
reg
=
&
region
[
i
];
memcpy
(
out
+
ptr
,
(
const
char
*
)
blob
+
reg
->
offset
,
reg
->
size
);
ptr
+=
reg
->
size
;
}
return
ptr
;
}
/**
* show_region_list() - Print out a list of regions
*
* The list includes the region offset (absolute offset from start of FDT
* blob in bytes) and size
*
* @reg: List of regions to print
* @count: Number of regions
*/
static
void
show_region_list
(
struct
fdt_region
*
reg
,
int
count
)
{
int
i
;
printf
(
"Regions: %d
\n
"
,
count
);
for
(
i
=
0
;
i
<
count
;
i
++
,
reg
++
)
{
printf
(
"%d: %-10x %-10x
\n
"
,
i
,
reg
->
offset
,
reg
->
offset
+
reg
->
size
);
}
}
static
int
check_type_include
(
void
*
priv
,
int
type
,
const
char
*
data
,
int
size
)
{
struct
display_info
*
disp
=
priv
;
struct
value_node
*
val
;
int
match
,
none_match
=
FDT_IS_ANY
;
/* If none of our conditions mention this type, we know nothing */
debug
(
"type=%x, data=%s
\n
"
,
type
,
data
?
data
:
"(null)"
);
if
(
!
((
disp
->
types_inc
|
disp
->
types_exc
)
&
type
))
{
debug
(
" - not in any condition
\n
"
);
return
-
1
;
}
/*
* Go through the list of conditions. For inclusive conditions, we
* return 1 at the first match. For exclusive conditions, we must
* check that there are no matches.
*/
if
(
data
)
{
for
(
val
=
disp
->
value_head
;
val
;
val
=
val
->
next
)
{
if
(
!
(
type
&
val
->
type
))
continue
;
match
=
fdt_stringlist_contains
(
data
,
size
,
val
->
string
);
debug
(
" - val->type=%x, str='%s', match=%d
\n
"
,
val
->
type
,
val
->
string
,
match
);
if
(
match
&&
val
->
include
)
{
debug
(
" - match inc %s
\n
"
,
val
->
string
);
return
1
;
}
if
(
match
)
none_match
&=
~
val
->
type
;
}
}
/*
* If this is an exclusive condition, and nothing matches, then we
* should return 1.
*/
if
((
type
&
disp
->
types_exc
)
&&
(
none_match
&
type
))
{
debug
(
" - match exc
\n
"
);
/*
* Allow FDT_IS_COMPAT to make the final decision in the
* case where there is no specific type
*/
if
(
type
==
FDT_IS_NODE
&&
disp
->
types_exc
==
FDT_ANY_GLOBAL
)
{
debug
(
" - supressed exc node
\n
"
);
return
-
1
;
}
return
1
;
}
/*
* Allow FDT_IS_COMPAT to make the final decision in the
* case where there is no specific type (inclusive)
*/
if
(
type
==
FDT_IS_NODE
&&
disp
->
types_inc
==
FDT_ANY_GLOBAL
)
return
-
1
;
debug
(
" - no match, types_inc=%x, types_exc=%x, none_match=%x
\n
"
,
disp
->
types_inc
,
disp
->
types_exc
,
none_match
);
return
0
;
}
/**
* h_include() - Include handler function for fdt_find_regions()
*
* This function decides whether to include or exclude a node, property or
* compatible string. The function is defined by fdt_find_regions().
*
* The algorithm is documented in the code - disp->invert is 0 for normal
* operation, and 1 to invert the sense of all matches.
*
* See
*/
static
int
h_include
(
void
*
priv
,
const
void
*
fdt
,
int
offset
,
int
type
,
const
char
*
data
,
int
size
)
{
struct
display_info
*
disp
=
priv
;
int
inc
,
len
;
inc
=
check_type_include
(
priv
,
type
,
data
,
size
);
if
(
disp
->
include_root
&&
type
==
FDT_IS_PROP
&&
offset
==
0
&&
inc
)
return
1
;
/*
* If the node name does not tell us anything, check the
* compatible string
*/
if
(
inc
==
-
1
&&
type
==
FDT_IS_NODE
)
{
debug
(
" - checking compatible2
\n
"
);
data
=
fdt_getprop
(
fdt
,
offset
,
"compatible"
,
&
len
);
inc
=
check_type_include
(
priv
,
FDT_IS_COMPAT
,
data
,
len
);
}
/* If we still have no idea, check for properties in the node */
if
(
inc
!=
1
&&
type
==
FDT_IS_NODE
&&
(
disp
->
types_inc
&
FDT_NODE_HAS_PROP
))
{
debug
(
" - checking node '%s'
\n
"
,
fdt_get_name
(
fdt
,
offset
,
NULL
));
for
(
offset
=
fdt_first_property_offset
(
fdt
,
offset
);
offset
>
0
&&
inc
!=
1
;
offset
=
fdt_next_property_offset
(
fdt
,
offset
))
{
const
struct
fdt_property
*
prop
;
const
char
*
str
;
prop
=
fdt_get_property_by_offset
(
fdt
,
offset
,
NULL
);
if
(
!
prop
)
continue
;
str
=
fdt_string
(
fdt
,
fdt32_to_cpu
(
prop
->
nameoff
));
inc
=
check_type_include
(
priv
,
FDT_NODE_HAS_PROP
,
str
,
strlen
(
str
));
}
if
(
inc
==
-
1
)
inc
=
0
;
}
switch
(
inc
)
{
case
1
:
inc
=
!
disp
->
invert
;
break
;
case
0
:
inc
=
disp
->
invert
;
break
;
}
debug
(
" - returning %d
\n
"
,
inc
);
return
inc
;
}
static
int
h_cmp_region
(
const
void
*
v1
,
const
void
*
v2
)
{
const
struct
fdt_region
*
region1
=
v1
,
*
region2
=
v2
;
return
region1
->
offset
-
region2
->
offset
;
}
static
int
fdtgrep_find_regions
(
const
void
*
fdt
,
int
(
*
include_func
)(
void
*
priv
,
const
void
*
fdt
,
int
offset
,
int
type
,
const
char
*
data
,
int
size
),
struct
display_info
*
disp
,
struct
fdt_region
*
region
,
int
max_regions
,
char
*
path
,
int
path_len
,
int
flags
)
{
struct
fdt_region_state
state
;
int
count
;
int
ret
;
count
=
0
;
ret
=
fdt_first_region
(
fdt
,
include_func
,
disp
,
&
region
[
count
++
],
path
,
path_len
,
disp
->
flags
,
&
state
);
while
(
ret
==
0
)
{
ret
=
fdt_next_region
(
fdt
,
include_func
,
disp
,
count
<
max_regions
?
&
region
[
count
]
:
NULL
,
path
,
path_len
,
disp
->
flags
,
&
state
);
if
(
!
ret
)
count
++
;
}
if
(
ret
&&
ret
!=
-
FDT_ERR_NOTFOUND
)
return
ret
;
/* Find all the aliases and add those regions back in */
if
(
disp
->
add_aliases
&&
count
<
max_regions
)
{
int
new_count
;
new_count
=
fdt_add_alias_regions
(
fdt
,
region
,
count
,
max_regions
,
&
state
);
if
(
new_count
==
-
FDT_ERR_NOTFOUND
)
{
/* No alias node found */
}
else
if
(
new_count
<
0
)
{
return
new_count
;
}
else
if
(
new_count
<=
max_regions
)
{
/*
* The alias regions will now be at the end of the list.
* Sort the regions by offset to get things into the
* right order
*/
count
=
new_count
;
qsort
(
region
,
count
,
sizeof
(
struct
fdt_region
),
h_cmp_region
);
}
}
return
count
;
}
int
utilfdt_read_err_len
(
const
char
*
filename
,
char
**
buffp
,
off_t
*
len
)
{
int
fd
=
0
;
/* assume stdin */
char
*
buf
=
NULL
;
off_t
bufsize
=
1024
,
offset
=
0
;
int
ret
=
0
;
*
buffp
=
NULL
;
if
(
strcmp
(
filename
,
"-"
)
!=
0
)
{
fd
=
open
(
filename
,
O_RDONLY
);
if
(
fd
<
0
)
return
errno
;
}
/* Loop until we have read everything */
buf
=
malloc
(
bufsize
);
if
(
!
buf
)
return
-
ENOMEM
;
do
{
/* Expand the buffer to hold the next chunk */
if
(
offset
==
bufsize
)
{
bufsize
*=
2
;
buf
=
realloc
(
buf
,
bufsize
);
if
(
!
buf
)
return
-
ENOMEM
;
}
ret
=
read
(
fd
,
&
buf
[
offset
],
bufsize
-
offset
);
if
(
ret
<
0
)
{
ret
=
errno
;
break
;
}
offset
+=
ret
;
}
while
(
ret
!=
0
);
/* Clean up, including closing stdin; return errno on error */
close
(
fd
);
if
(
ret
)
free
(
buf
);
else
*
buffp
=
buf
;
*
len
=
bufsize
;
return
ret
;
}
int
utilfdt_read_err
(
const
char
*
filename
,
char
**
buffp
)
{
off_t
len
;
return
utilfdt_read_err_len
(
filename
,
buffp
,
&
len
);
}
char
*
utilfdt_read_len
(
const
char
*
filename
,
off_t
*
len
)
{
char
*
buff
;
int
ret
=
utilfdt_read_err_len
(
filename
,
&
buff
,
len
);
if
(
ret
)
{
fprintf
(
stderr
,
"Couldn't open blob from '%s': %s
\n
"
,
filename
,
strerror
(
ret
));
return
NULL
;
}
/* Successful read */
return
buff
;
}
char
*
utilfdt_read
(
const
char
*
filename
)
{
off_t
len
;
return
utilfdt_read_len
(
filename
,
&
len
);
}
/**
* Run the main fdtgrep operation, given a filename and valid arguments
*
* @param disp Display information / options
* @param filename Filename of blob file
* @param return 0 if ok, -ve on error
*/
static
int
do_fdtgrep
(
struct
display_info
*
disp
,
const
char
*
filename
)
{
struct
fdt_region
*
region
;
int
max_regions
;
int
count
=
100
;
char
path
[
1024
];
char
*
blob
;
int
i
,
ret
;
blob
=
utilfdt_read
(
filename
);
if
(
!
blob
)
return
-
1
;
ret
=
fdt_check_header
(
blob
);
if
(
ret
)
{
fprintf
(
stderr
,
"Error: %s
\n
"
,
fdt_strerror
(
ret
));
return
ret
;
}
/* Allow old files, but they are untested */
if
(
fdt_version
(
blob
)
<
17
&&
disp
->
value_head
)
{
fprintf
(
stderr
,
"Warning: fdtgrep does not fully support version %d files
\n
"
,
fdt_version
(
blob
));
}
/*
* We do two passes, since we don't know how many regions we need.
* The first pass will count the regions, but if it is too many,
* we do another pass to actually record them.
*/
for
(
i
=
0
;
i
<
3
;
i
++
)
{
region
=
malloc
(
count
*
sizeof
(
struct
fdt_region
));
if
(
!
region
)
{
fprintf
(
stderr
,
"Out of memory for %d regions
\n
"
,
count
);
return
-
1
;
}
max_regions
=
count
;
count
=
fdtgrep_find_regions
(
blob
,
h_include
,
disp
,
region
,
max_regions
,
path
,
sizeof
(
path
),
disp
->
flags
);
if
(
count
<
0
)
{
report_error
(
"fdt_find_regions"
,
count
);
return
-
1
;
}
if
(
count
<=
max_regions
)
break
;
free
(
region
);
}
/* Optionally print a list of regions */
if
(
disp
->
region_list
)
show_region_list
(
region
,
count
);
/* Output either source .dts or binary .dtb */
if
(
disp
->
output
==
OUT_DTS
)
{
ret
=
display_fdt_by_regions
(
disp
,
blob
,
region
,
count
);
}
else
{
void
*
fdt
;
/* Allow reserved memory section to expand slightly */
int
size
=
fdt_totalsize
(
blob
)
+
16
;
fdt
=
malloc
(
size
);
if
(
!
fdt
)
{
fprintf
(
stderr
,
"Out_of_memory
\n
"
);
ret
=
-
1
;
goto
err
;
}
size
=
dump_fdt_regions
(
disp
,
blob
,
region
,
count
,
fdt
);
if
(
disp
->
remove_strings
)
{
void
*
out
;
out
=
malloc
(
size
);
if
(
!
out
)
{
fprintf
(
stderr
,
"Out_of_memory
\n
"
);
ret
=
-
1
;
goto
err
;
}
ret
=
fdt_remove_unused_strings
(
fdt
,
out
);
if
(
ret
<
0
)
{
fprintf
(
stderr
,
"Failed to remove unused strings: err=%d
\n
"
,
ret
);
goto
err
;
}
free
(
fdt
);
fdt
=
out
;
ret
=
fdt_pack
(
fdt
);
if
(
ret
<
0
)
{
fprintf
(
stderr
,
"Failed to pack: err=%d
\n
"
,
ret
);
goto
err
;
}
size
=
fdt_totalsize
(
fdt
);
}
if
(
size
!=
fwrite
(
fdt
,
1
,
size
,
disp
->
fout
))
{
fprintf
(
stderr
,
"Write failure, %d bytes
\n
"
,
size
);
free
(
fdt
);
ret
=
1
;
goto
err
;
}
free
(
fdt
);
}
err:
free
(
blob
);
free
(
region
);
return
ret
;
}
static
const
char
usage_synopsis
[]
=
"fdtgrep - extract portions from device tree
\n
"
"
\n
"
"Usage:
\n
"
" fdtgrep <options> <dt file>|-
\n\n
"
"Output formats are:
\n
"
"
\t
dts - device tree soure text
\n
"
"
\t
dtb - device tree blob (sets -Hmt automatically)
\n
"
"
\t
bin - device tree fragment (may not be a valid .dtb)"
;
/* Helper for usage_short_opts string constant */
#define USAGE_COMMON_SHORT_OPTS "hV"
/* Helper for aligning long_opts array */
#define a_argument required_argument
/* Helper for usage_long_opts option array */
#define USAGE_COMMON_LONG_OPTS \
{"help", no_argument, NULL, 'h'}, \
{"version", no_argument, NULL, 'V'}, \
{NULL, no_argument, NULL, 0x0}
/* Helper for usage_opts_help array */
#define USAGE_COMMON_OPTS_HELP \
"Print this help and exit", \
"Print version and exit", \
NULL
/* Helper for getopt case statements */
#define case_USAGE_COMMON_FLAGS \
case 'h': usage(NULL); \
case 'V': util_version(); \
case '?': usage("unknown option");
static
const
char
usage_short_opts
[]
=
"haAc:b:C:defg:G:HIlLmn:N:o:O:p:P:rRsStTv"
USAGE_COMMON_SHORT_OPTS
;
static
struct
option
const
usage_long_opts
[]
=
{
{
"show-address"
,
no_argument
,
NULL
,
'a'
},
{
"colour"
,
no_argument
,
NULL
,
'A'
},
{
"include-node-with-prop"
,
a_argument
,
NULL
,
'b'
},
{
"include-compat"
,
a_argument
,
NULL
,
'c'
},
{
"exclude-compat"
,
a_argument
,
NULL
,
'C'
},
{
"diff"
,
no_argument
,
NULL
,
'd'
},
{
"enter-node"
,
no_argument
,
NULL
,
'e'
},
{
"show-offset"
,
no_argument
,
NULL
,
'f'
},
{
"include-match"
,
a_argument
,
NULL
,
'g'
},
{
"exclude-match"
,
a_argument
,
NULL
,
'G'
},
{
"show-header"
,
no_argument
,
NULL
,
'H'
},
{
"show-version"
,
no_argument
,
NULL
,
'I'
},
{
"list-regions"
,
no_argument
,
NULL
,
'l'
},
{
"list-strings"
,
no_argument
,
NULL
,
'L'
},
{
"include-mem"
,
no_argument
,
NULL
,
'm'
},
{
"include-node"
,
a_argument
,
NULL
,
'n'
},
{
"exclude-node"
,
a_argument
,
NULL
,
'N'
},
{
"include-prop"
,
a_argument
,
NULL
,
'p'
},
{
"exclude-prop"
,
a_argument
,
NULL
,
'P'
},
{
"remove-strings"
,
no_argument
,
NULL
,
'r'
},
{
"include-root"
,
no_argument
,
NULL
,
'R'
},
{
"show-subnodes"
,
no_argument
,
NULL
,
's'
},
{
"skip-supernodes"
,
no_argument
,
NULL
,
'S'
},
{
"show-stringtab"
,
no_argument
,
NULL
,
't'
},
{
"show-aliases"
,
no_argument
,
NULL
,
'T'
},
{
"out"
,
a_argument
,
NULL
,
'o'
},
{
"out-format"
,
a_argument
,
NULL
,
'O'
},
{
"invert-match"
,
no_argument
,
NULL
,
'v'
},
USAGE_COMMON_LONG_OPTS
,
};
static
const
char
*
const
usage_opts_help
[]
=
{
"Display address"
,
"Show all nodes/tags, colour those that match"
,
"Include contains containing property"
,
"Compatible nodes to include in grep"
,
"Compatible nodes to exclude in grep"
,
"Diff: Mark matching nodes with +, others with -"
,
"Enter direct subnode names of matching nodes"
,
"Display offset"
,
"Node/property/compatible string to include in grep"
,
"Node/property/compatible string to exclude in grep"
,
"Output a header"
,
"Put
\"
/dts-v1/;
\"
on first line of dts output"
,
"Output a region list"
,
"List strings in string table"
,
"Include mem_rsvmap section in binary output"
,
"Node to include in grep"
,
"Node to exclude in grep"
,
"Property to include in grep"
,
"Property to exclude in grep"
,
"Remove unused strings from string table"
,
"Include root node and all properties"
,
"Show all subnodes matching nodes"
,
"Don't include supernodes of matching nodes"
,
"Include string table in binary output"
,
"Include matching aliases in output"
,
"-o <output file>"
,
"-O <output format>"
,
"Invert the sense of matching (select non-matching lines)"
,
USAGE_COMMON_OPTS_HELP
};
/**
* Call getopt_long() with standard options
*
* Since all util code runs getopt in the same way, provide a helper.
*/
#define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \
usage_long_opts, NULL)
void
util_usage
(
const
char
*
errmsg
,
const
char
*
synopsis
,
const
char
*
short_opts
,
struct
option
const
long_opts
[],
const
char
*
const
opts_help
[])
{
FILE
*
fp
=
errmsg
?
stderr
:
stdout
;
const
char
a_arg
[]
=
"<arg>"
;
size_t
a_arg_len
=
strlen
(
a_arg
)
+
1
;
size_t
i
;
int
optlen
;
fprintf
(
fp
,
"Usage: %s
\n
"
"
\n
"
"Options: -[%s]
\n
"
,
synopsis
,
short_opts
);
/* prescan the --long opt length to auto-align */
optlen
=
0
;
for
(
i
=
0
;
long_opts
[
i
].
name
;
++
i
)
{
/* +1 is for space between --opt and help text */
int
l
=
strlen
(
long_opts
[
i
].
name
)
+
1
;
if
(
long_opts
[
i
].
has_arg
==
a_argument
)
l
+=
a_arg_len
;
if
(
optlen
<
l
)
optlen
=
l
;
}
for
(
i
=
0
;
long_opts
[
i
].
name
;
++
i
)
{
/* helps when adding new applets or options */
assert
(
opts_help
[
i
]
!=
NULL
);
/* first output the short flag if it has one */
if
(
long_opts
[
i
].
val
>
'~'
)
fprintf
(
fp
,
" "
);
else
fprintf
(
fp
,
" -%c, "
,
long_opts
[
i
].
val
);
/* then the long flag */
if
(
long_opts
[
i
].
has_arg
==
no_argument
)
{
fprintf
(
fp
,
"--%-*s"
,
optlen
,
long_opts
[
i
].
name
);
}
else
{
fprintf
(
fp
,
"--%s %s%*s"
,
long_opts
[
i
].
name
,
a_arg
,
(
int
)(
optlen
-
strlen
(
long_opts
[
i
].
name
)
-
a_arg_len
),
""
);
}
/* finally the help text */
fprintf
(
fp
,
"%s
\n
"
,
opts_help
[
i
]);
}
if
(
errmsg
)
{
fprintf
(
fp
,
"
\n
Error: %s
\n
"
,
errmsg
);
exit
(
EXIT_FAILURE
);
}
else
{
exit
(
EXIT_SUCCESS
);
}
}
/**
* Show usage and exit
*
* If you name all your usage variables with usage_xxx, then you can call this
* help macro rather than expanding all arguments yourself.
*
* @param errmsg If non-NULL, an error message to display
*/
#define usage(errmsg) \
util_usage(errmsg, usage_synopsis, usage_short_opts, \
usage_long_opts, usage_opts_help)
void
util_version
(
void
)
{
printf
(
"Version: %s
\n
"
,
"(U-Boot)"
);
exit
(
0
);
}
static
void
scan_args
(
struct
display_info
*
disp
,
int
argc
,
char
*
argv
[])
{
int
opt
;
while
((
opt
=
util_getopt_long
())
!=
EOF
)
{
int
type
=
0
;
int
inc
=
1
;
switch
(
opt
)
{
case_USAGE_COMMON_FLAGS
case
'a'
:
disp
->
show_addr
=
1
;
break
;
case
'A'
:
disp
->
all
=
1
;
break
;
case
'b'
:
type
=
FDT_NODE_HAS_PROP
;
break
;
case
'C'
:
inc
=
0
;
/* no break */
case
'c'
:
type
=
FDT_IS_COMPAT
;
break
;
case
'd'
:
disp
->
diff
=
1
;
break
;
case
'e'
:
disp
->
flags
|=
FDT_REG_DIRECT_SUBNODES
;
break
;
case
'f'
:
disp
->
show_offset
=
1
;
break
;
case
'G'
:
inc
=
0
;
/* no break */
case
'g'
:
type
=
FDT_ANY_GLOBAL
;
break
;
case
'H'
:
disp
->
header
=
1
;
break
;
case
'l'
:
disp
->
region_list
=
1
;
break
;
case
'L'
:
disp
->
list_strings
=
1
;
break
;
case
'm'
:
disp
->
flags
|=
FDT_REG_ADD_MEM_RSVMAP
;
break
;
case
'N'
:
inc
=
0
;
/* no break */
case
'n'
:
type
=
FDT_IS_NODE
;
break
;
case
'o'
:
disp
->
output_fname
=
optarg
;
break
;
case
'O'
:
if
(
!
strcmp
(
optarg
,
"dtb"
))
disp
->
output
=
OUT_DTB
;
else
if
(
!
strcmp
(
optarg
,
"dts"
))
disp
->
output
=
OUT_DTS
;
else
if
(
!
strcmp
(
optarg
,
"bin"
))
disp
->
output
=
OUT_BIN
;
else
usage
(
"Unknown output format"
);
break
;
case
'P'
:
inc
=
0
;
/* no break */
case
'p'
:
type
=
FDT_IS_PROP
;
break
;
case
'r'
:
disp
->
remove_strings
=
1
;
break
;
case
'R'
:
disp
->
include_root
=
1
;
break
;
case
's'
:
disp
->
flags
|=
FDT_REG_ALL_SUBNODES
;
break
;
case
'S'
:
disp
->
flags
&=
~
FDT_REG_SUPERNODES
;
break
;
case
't'
:
disp
->
flags
|=
FDT_REG_ADD_STRING_TAB
;
break
;
case
'T'
:
disp
->
add_aliases
=
1
;
break
;
case
'v'
:
disp
->
invert
=
1
;
break
;
case
'I'
:
disp
->
show_dts_version
=
1
;
break
;
}
if
(
type
&&
value_add
(
disp
,
&
disp
->
value_head
,
type
,
inc
,
optarg
))
usage
(
"Cannot add value"
);
}
if
(
disp
->
invert
&&
disp
->
types_exc
)
usage
(
"-v has no meaning when used with 'exclude' conditions"
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
char
*
filename
=
NULL
;
struct
display_info
disp
;
int
ret
;
/* set defaults */
memset
(
&
disp
,
'\0'
,
sizeof
(
disp
));
disp
.
flags
=
FDT_REG_SUPERNODES
;
/* Default flags */
scan_args
(
&
disp
,
argc
,
argv
);
/* Show matched lines in colour if we can */
disp
.
colour
=
disp
.
all
&&
isatty
(
0
);
/* Any additional arguments can match anything, just like -g */
while
(
optind
<
argc
-
1
)
{
if
(
value_add
(
&
disp
,
&
disp
.
value_head
,
FDT_IS_ANY
,
1
,
argv
[
optind
++
]))
usage
(
"Cannot add value"
);
}
if
(
optind
<
argc
)
filename
=
argv
[
optind
++
];
if
(
!
filename
)
usage
(
"Missing filename"
);
/* If a valid .dtb is required, set flags to ensure we get one */
if
(
disp
.
output
==
OUT_DTB
)
{
disp
.
header
=
1
;
disp
.
flags
|=
FDT_REG_ADD_MEM_RSVMAP
|
FDT_REG_ADD_STRING_TAB
;
}
if
(
disp
.
output_fname
)
{
disp
.
fout
=
fopen
(
disp
.
output_fname
,
"w"
);
if
(
!
disp
.
fout
)
usage
(
"Cannot open output file"
);
}
else
{
disp
.
fout
=
stdout
;
}
/* Run the grep and output the results */
ret
=
do_fdtgrep
(
&
disp
,
filename
);
if
(
disp
.
output_fname
)
fclose
(
disp
.
fout
);
if
(
ret
)
return
1
;
return
0
;
}
u-boot-tree/tools/fit_check_sign.c
0 → 100644
View file @
857f62fe
/*
* (C) Copyright 2014
* DENX Software Engineering
* Heiko Schocher <hs@denx.de>
*
* Based on:
* (C) Copyright 2008 Semihalf
*
* (C) Copyright 2000-2004
* DENX Software Engineering
* Wolfgang Denk, wd@denx.de
*
* Updated-by: Prafulla Wadaskar <prafulla@marvell.com>
* FIT image specific code abstracted from mkimage.c
* some functions added to address abstraction
*
* All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include "mkimage.h"
#include "fit_common.h"
#include <image.h>
#include <u-boot/crc.h>
void
usage
(
char
*
cmdname
)
{
fprintf
(
stderr
,
"Usage: %s -f fit file -k key file
\n
"
" -f ==> set fit file which should be checked'
\n
"
" -k ==> set key file which contains the key'
\n
"
,
cmdname
);
exit
(
EXIT_FAILURE
);
}
int
main
(
int
argc
,
char
**
argv
)
{
int
ffd
=
-
1
;
int
kfd
=
-
1
;
struct
stat
fsbuf
;
struct
stat
ksbuf
;
void
*
fit_blob
;
char
*
fdtfile
=
NULL
;
char
*
keyfile
=
NULL
;
char
cmdname
[
256
];
int
ret
;
void
*
key_blob
;
int
c
;
strncpy
(
cmdname
,
*
argv
,
sizeof
(
cmdname
)
-
1
);
cmdname
[
sizeof
(
cmdname
)
-
1
]
=
'\0'
;
while
((
c
=
getopt
(
argc
,
argv
,
"f:k:"
))
!=
-
1
)
switch
(
c
)
{
case
'f'
:
fdtfile
=
optarg
;
break
;
case
'k'
:
keyfile
=
optarg
;
break
;
default:
usage
(
cmdname
);
break
;
}
if
(
!
fdtfile
)
{
fprintf
(
stderr
,
"%s: Missing fdt file
\n
"
,
*
argv
);
usage
(
*
argv
);
}
if
(
!
keyfile
)
{
fprintf
(
stderr
,
"%s: Missing key file
\n
"
,
*
argv
);
usage
(
*
argv
);
}
ffd
=
mmap_fdt
(
cmdname
,
fdtfile
,
0
,
&
fit_blob
,
&
fsbuf
,
false
);
if
(
ffd
<
0
)
return
EXIT_FAILURE
;
kfd
=
mmap_fdt
(
cmdname
,
keyfile
,
0
,
&
key_blob
,
&
ksbuf
,
false
);
if
(
kfd
<
0
)
return
EXIT_FAILURE
;
image_set_host_blob
(
key_blob
);
ret
=
fit_check_sign
(
fit_blob
,
key_blob
);
if
(
!
ret
)
{
ret
=
EXIT_SUCCESS
;
fprintf
(
stderr
,
"Signature check OK
\n
"
);
}
else
{
ret
=
EXIT_FAILURE
;
fprintf
(
stderr
,
"Signature check Bad (error %d)
\n
"
,
ret
);
}
(
void
)
munmap
((
void
*
)
fit_blob
,
fsbuf
.
st_size
);
(
void
)
munmap
((
void
*
)
key_blob
,
ksbuf
.
st_size
);
close
(
ffd
);
close
(
kfd
);
exit
(
ret
);
}
u-boot-tree/tools/fit_info.c
0 → 100644
View file @
857f62fe
/*
* (C) Copyright 2014
* DENX Software Engineering
* Heiko Schocher <hs@denx.de>
*
* fit_info: print the offset and the len of a property from
* node in a fit file.
*
* Based on:
* (C) Copyright 2008 Semihalf
*
* (C) Copyright 2000-2004
* DENX Software Engineering
* Wolfgang Denk, wd@denx.de
*
* Updated-by: Prafulla Wadaskar <prafulla@marvell.com>
* FIT image specific code abstracted from mkimage.c
* some functions added to address abstraction
*
* All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include "mkimage.h"
#include "fit_common.h"
#include <image.h>
#include <u-boot/crc.h>
void
usage
(
char
*
cmdname
)
{
fprintf
(
stderr
,
"Usage: %s -f fit file -n node -p property
\n
"
" -f ==> set fit file which is used'
\n
"
" -n ==> set node name'
\n
"
" -p ==> set property name'
\n
"
,
cmdname
);
exit
(
EXIT_FAILURE
);
}
int
main
(
int
argc
,
char
**
argv
)
{
int
ffd
=
-
1
;
struct
stat
fsbuf
;
void
*
fit_blob
;
int
len
;
int
nodeoffset
;
/* node offset from libfdt */
const
void
*
nodep
;
/* property node pointer */
char
*
fdtfile
=
NULL
;
char
*
nodename
=
NULL
;
char
*
propertyname
=
NULL
;
char
cmdname
[
256
];
int
c
;
strncpy
(
cmdname
,
*
argv
,
sizeof
(
cmdname
)
-
1
);
cmdname
[
sizeof
(
cmdname
)
-
1
]
=
'\0'
;
while
((
c
=
getopt
(
argc
,
argv
,
"f:n:p:"
))
!=
-
1
)
switch
(
c
)
{
case
'f'
:
fdtfile
=
optarg
;
break
;
case
'n'
:
nodename
=
optarg
;
break
;
case
'p'
:
propertyname
=
optarg
;
break
;
default:
usage
(
cmdname
);
break
;
}
if
(
!
fdtfile
)
{
fprintf
(
stderr
,
"%s: Missing fdt file
\n
"
,
*
argv
);
usage
(
*
argv
);
}
if
(
!
nodename
)
{
fprintf
(
stderr
,
"%s: Missing node name
\n
"
,
*
argv
);
usage
(
*
argv
);
}
if
(
!
propertyname
)
{
fprintf
(
stderr
,
"%s: Missing property name
\n
"
,
*
argv
);
usage
(
*
argv
);
}
ffd
=
mmap_fdt
(
cmdname
,
fdtfile
,
0
,
&
fit_blob
,
&
fsbuf
,
false
);
if
(
ffd
<
0
)
{
printf
(
"Could not open %s
\n
"
,
fdtfile
);
exit
(
EXIT_FAILURE
);
}
nodeoffset
=
fdt_path_offset
(
fit_blob
,
nodename
);
if
(
nodeoffset
<
0
)
{
printf
(
"%s not found."
,
nodename
);
exit
(
EXIT_FAILURE
);
}
nodep
=
fdt_getprop
(
fit_blob
,
nodeoffset
,
propertyname
,
&
len
);
if
(
len
==
0
)
{
printf
(
"len == 0 %s
\n
"
,
propertyname
);
exit
(
EXIT_FAILURE
);
}
printf
(
"NAME: %s
\n
"
,
fit_get_name
(
fit_blob
,
nodeoffset
,
NULL
));
printf
(
"LEN: %d
\n
"
,
len
);
printf
(
"OFF: %d
\n
"
,
(
int
)(
nodep
-
fit_blob
));
(
void
)
munmap
((
void
*
)
fit_blob
,
fsbuf
.
st_size
);
close
(
ffd
);
exit
(
EXIT_SUCCESS
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment