Initial label support. Also switch to glr-parser mode and get rid of
hacks that were necessary without it.main
parent
fc14dad769
commit
4102d840d9
10
Makefile
10
Makefile
|
@ -1,8 +1,10 @@
|
||||||
TARGETS = dtc
|
TARGETS = dtc
|
||||||
CFLAGS = -Wall -g
|
CFLAGS = -Wall -g
|
||||||
|
|
||||||
|
BISON = bison
|
||||||
|
|
||||||
OBJS = dtc.o livetree.o flattree.o data.o treesource.o fstree.o \
|
OBJS = dtc.o livetree.o flattree.o data.o treesource.o fstree.o \
|
||||||
y.tab.o lex.yy.o
|
dtc-parser.tab.o lex.yy.o
|
||||||
|
|
||||||
all: $(TARGETS)
|
all: $(TARGETS)
|
||||||
|
|
||||||
|
@ -11,13 +13,13 @@ dtc: $(OBJS)
|
||||||
|
|
||||||
$(OBJS): dtc.h
|
$(OBJS): dtc.h
|
||||||
|
|
||||||
y.tab.c y.tab.h: dtc-parser.y
|
dtc-parser.tab.c dtc-parser.tab.h dtc-parser.output: dtc-parser.y
|
||||||
$(YACC) -d $<
|
$(BISON) -d -v $<
|
||||||
|
|
||||||
lex.yy.c: dtc-lexer.l
|
lex.yy.c: dtc-lexer.l
|
||||||
$(LEX) $<
|
$(LEX) $<
|
||||||
|
|
||||||
lex.yy.o: lex.yy.c y.tab.h
|
lex.yy.o: lex.yy.c dtc-parser.tab.h
|
||||||
|
|
||||||
dtc-parser.c: dtc-lexer.c
|
dtc-parser.c: dtc-lexer.c
|
||||||
|
|
||||||
|
|
2
TODO
2
TODO
|
@ -4,8 +4,6 @@
|
||||||
* Report line/column numbers for syntax errors
|
* Report line/column numbers for syntax errors
|
||||||
* Better categorization of errors into severity levels
|
* Better categorization of errors into severity levels
|
||||||
- Generate mem reserve map
|
- Generate mem reserve map
|
||||||
* Command line options to place a number of blank entries to be
|
|
||||||
filled in by bootloader
|
|
||||||
* memory reserve section in source
|
* memory reserve section in source
|
||||||
- Testsuite
|
- Testsuite
|
||||||
- Actually number releases, revision control, all that kind of jazz
|
- Actually number releases, revision control, all that kind of jazz
|
||||||
|
|
|
@ -31,5 +31,8 @@
|
||||||
/** try this */
|
/** try this */
|
||||||
prop9;
|
prop9;
|
||||||
/* and this **/
|
/* and this **/
|
||||||
|
prop10;
|
||||||
|
child /* finally */ {
|
||||||
|
};
|
||||||
};
|
};
|
||||||
/* final comment */
|
/* final comment */
|
||||||
|
|
29
dtc-lexer.l
29
dtc-lexer.l
|
@ -32,9 +32,9 @@ WS [ \t\n]
|
||||||
%{
|
%{
|
||||||
#include "dtc.h"
|
#include "dtc.h"
|
||||||
|
|
||||||
#include "y.tab.h"
|
#include "dtc-parser.tab.h"
|
||||||
|
|
||||||
#undef LEXDEBUG 1
|
/*#define LEXDEBUG 1 */
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
@ -83,14 +83,6 @@ WS [ \t\n]
|
||||||
return ']';
|
return ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
{PROPCHAR}+(@{UNITCHAR}+)?/{WS}*\{ {
|
|
||||||
#ifdef LEXDEBUG
|
|
||||||
fprintf(stderr, "NodeName: %s\n", yytext);
|
|
||||||
#endif
|
|
||||||
yylval.str = strdup(yytext);
|
|
||||||
return DT_NODENAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
{PROPCHAR}+ {
|
{PROPCHAR}+ {
|
||||||
#ifdef LEXDEBUG
|
#ifdef LEXDEBUG
|
||||||
fprintf(stderr, "PropName: %s\n", yytext);
|
fprintf(stderr, "PropName: %s\n", yytext);
|
||||||
|
@ -99,6 +91,23 @@ WS [ \t\n]
|
||||||
return DT_PROPNAME;
|
return DT_PROPNAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{PROPCHAR}+(@{UNITCHAR}+)? {
|
||||||
|
#ifdef LEXDEBUG
|
||||||
|
fprintf(stderr, "NodeName: %s\n", yytext);
|
||||||
|
#endif
|
||||||
|
yylval.str = strdup(yytext);
|
||||||
|
return DT_NODENAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[a-zA-Z_][a-zA-Z0-9_]*: {
|
||||||
|
#ifdef LEXDEBUG
|
||||||
|
fprintf(stderr, "Label: %s\n", yytext);
|
||||||
|
#endif
|
||||||
|
yylval.str = strdup(yytext);
|
||||||
|
yylval.str[yyleng-1] = '\0';
|
||||||
|
return DT_LABEL;
|
||||||
|
}
|
||||||
|
|
||||||
<*>{WS}+ /* eat whitespace */
|
<*>{WS}+ /* eat whitespace */
|
||||||
|
|
||||||
|
|
25
dtc-parser.y
25
dtc-parser.y
|
@ -47,6 +47,7 @@ extern struct node *device_tree;
|
||||||
%token <byte> DT_BYTE
|
%token <byte> DT_BYTE
|
||||||
%token <data> DT_STRING
|
%token <data> DT_STRING
|
||||||
%token <str> DT_UNIT
|
%token <str> DT_UNIT
|
||||||
|
%token <str> DT_LABEL
|
||||||
|
|
||||||
%type <data> propdata
|
%type <data> propdata
|
||||||
%type <data> celllist
|
%type <data> celllist
|
||||||
|
@ -57,12 +58,16 @@ extern struct node *device_tree;
|
||||||
%type <node> nodedef
|
%type <node> nodedef
|
||||||
%type <node> subnode
|
%type <node> subnode
|
||||||
%type <nodelist> subnodes
|
%type <nodelist> subnodes
|
||||||
|
%type <str> label
|
||||||
|
%type <str> nodename
|
||||||
|
|
||||||
|
%glr-parser
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
devicetree: {
|
devicetree: {
|
||||||
assert(device_tree == NULL);
|
assert(device_tree == NULL);
|
||||||
} '/' nodedef { device_tree = name_node($3, ""); }
|
} '/' nodedef { device_tree = name_node($3, "", NULL); }
|
||||||
;
|
;
|
||||||
|
|
||||||
nodedef: '{' proplist subnodes '}' ';' {
|
nodedef: '{' proplist subnodes '}' ';' {
|
||||||
|
@ -78,11 +83,11 @@ proplist: propdef proplist {
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
propdef: DT_PROPNAME '=' propdata ';' {
|
propdef: label DT_PROPNAME '=' propdata ';' {
|
||||||
$$ = build_property($1, $3);
|
$$ = build_property($2, $4, $1);
|
||||||
}
|
}
|
||||||
| DT_PROPNAME ';' {
|
| label DT_PROPNAME ';' {
|
||||||
$$ = build_empty_property($1);
|
$$ = build_empty_property($2, $1);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -105,7 +110,15 @@ subnodes: subnode subnodes {
|
||||||
| /* empty */ { $$ = NULL; }
|
| /* empty */ { $$ = NULL; }
|
||||||
;
|
;
|
||||||
|
|
||||||
subnode: DT_NODENAME nodedef { $$ = name_node($2, $1); }
|
subnode: label nodename nodedef { $$ = name_node($3, $2, $1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
nodename: DT_NODENAME { $$ = $1; }
|
||||||
|
| DT_PROPNAME { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
label: DT_LABEL { $$ = $1; }
|
||||||
|
| /* empty */ { $$ = NULL; }
|
||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
10
dtc.h
10
dtc.h
|
@ -115,6 +115,8 @@ struct property {
|
||||||
struct data val;
|
struct data val;
|
||||||
|
|
||||||
struct property *next;
|
struct property *next;
|
||||||
|
|
||||||
|
char *label;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct node {
|
struct node {
|
||||||
|
@ -130,6 +132,8 @@ struct node {
|
||||||
|
|
||||||
cell_t phandle;
|
cell_t phandle;
|
||||||
int addr_cells, size_cells;
|
int addr_cells, size_cells;
|
||||||
|
|
||||||
|
char *label;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define for_each_property(n, p) \
|
#define for_each_property(n, p) \
|
||||||
|
@ -138,12 +142,12 @@ struct node {
|
||||||
#define for_each_child(n, c) \
|
#define for_each_child(n, c) \
|
||||||
for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
|
for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
|
||||||
|
|
||||||
struct property *build_property(char *name, struct data val);
|
struct property *build_property(char *name, struct data val, char *label);
|
||||||
struct property *build_empty_property(char *name);
|
struct property *build_empty_property(char *name, char *label);
|
||||||
struct property *chain_property(struct property *first, struct property *list);
|
struct property *chain_property(struct property *first, struct property *list);
|
||||||
|
|
||||||
struct node *build_node(struct property *proplist, struct node *children);
|
struct node *build_node(struct property *proplist, struct node *children);
|
||||||
struct node *name_node(struct node *node, char *name);
|
struct node *name_node(struct node *node, char *name, char *label);
|
||||||
struct node *chain_node(struct node *first, struct node *list);
|
struct node *chain_node(struct node *first, struct node *list);
|
||||||
|
|
||||||
void add_property(struct node *node, struct property *prop);
|
void add_property(struct node *node, struct property *prop);
|
||||||
|
|
54
flattree.c
54
flattree.c
|
@ -80,9 +80,9 @@ struct emitter {
|
||||||
void (*string)(void *, char *, int);
|
void (*string)(void *, char *, int);
|
||||||
void (*align)(void *, int);
|
void (*align)(void *, int);
|
||||||
void (*data)(void *, struct data);
|
void (*data)(void *, struct data);
|
||||||
void (*beginnode)(void *);
|
void (*beginnode)(void *, char *);
|
||||||
void (*endnode)(void *);
|
void (*endnode)(void *, char *);
|
||||||
void (*property)(void *);
|
void (*property)(void *, char *);
|
||||||
};
|
};
|
||||||
|
|
||||||
static void bin_emit_cell(void *e, cell_t val)
|
static void bin_emit_cell(void *e, cell_t val)
|
||||||
|
@ -117,17 +117,17 @@ static void bin_emit_data(void *e, struct data d)
|
||||||
*dtbuf = data_append_data(*dtbuf, d.val, d.len);
|
*dtbuf = data_append_data(*dtbuf, d.val, d.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bin_emit_beginnode(void *e)
|
static void bin_emit_beginnode(void *e, char *label)
|
||||||
{
|
{
|
||||||
bin_emit_cell(e, OF_DT_BEGIN_NODE);
|
bin_emit_cell(e, OF_DT_BEGIN_NODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bin_emit_endnode(void *e)
|
static void bin_emit_endnode(void *e, char *label)
|
||||||
{
|
{
|
||||||
bin_emit_cell(e, OF_DT_END_NODE);
|
bin_emit_cell(e, OF_DT_END_NODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bin_emit_property(void *e)
|
static void bin_emit_property(void *e, char *label)
|
||||||
{
|
{
|
||||||
bin_emit_cell(e, OF_DT_PROP);
|
bin_emit_cell(e, OF_DT_PROP);
|
||||||
}
|
}
|
||||||
|
@ -142,6 +142,13 @@ struct emitter bin_emitter = {
|
||||||
.property = bin_emit_property,
|
.property = bin_emit_property,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void emit_label(FILE *f, char *prefix, char *label)
|
||||||
|
{
|
||||||
|
fprintf(f, "\t.globl\t%s_%s\n", prefix, label);
|
||||||
|
fprintf(f, "%s_%s:\n", prefix, label);
|
||||||
|
fprintf(f, "_%s_%s:\n", prefix, label);
|
||||||
|
}
|
||||||
|
|
||||||
static void asm_emit_cell(void *e, cell_t val)
|
static void asm_emit_cell(void *e, cell_t val)
|
||||||
{
|
{
|
||||||
FILE *f = e;
|
FILE *f = e;
|
||||||
|
@ -199,24 +206,36 @@ static void asm_emit_data(void *e, struct data d)
|
||||||
assert(off == d.len);
|
assert(off == d.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_emit_beginnode(void *e)
|
static void asm_emit_beginnode(void *e, char *label)
|
||||||
{
|
{
|
||||||
FILE *f = e;
|
FILE *f = e;
|
||||||
|
|
||||||
|
if (label) {
|
||||||
|
fprintf(f, "\t.globl\t%s\n", label);
|
||||||
|
fprintf(f, "%s:\n", label);
|
||||||
|
}
|
||||||
fprintf(f, "\t.long\tOF_DT_BEGIN_NODE\n");
|
fprintf(f, "\t.long\tOF_DT_BEGIN_NODE\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_emit_endnode(void *e)
|
static void asm_emit_endnode(void *e, char *label)
|
||||||
{
|
{
|
||||||
FILE *f = e;
|
FILE *f = e;
|
||||||
|
|
||||||
fprintf(f, "\t.long\tOF_DT_END_NODE\n");
|
fprintf(f, "\t.long\tOF_DT_END_NODE\n");
|
||||||
|
if (label) {
|
||||||
|
fprintf(f, "\t.globl\t%s_end\n", label);
|
||||||
|
fprintf(f, "%s_end:\n", label);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_emit_property(void *e)
|
static void asm_emit_property(void *e, char *label)
|
||||||
{
|
{
|
||||||
FILE *f = e;
|
FILE *f = e;
|
||||||
|
|
||||||
|
if (label) {
|
||||||
|
fprintf(f, "\t.globl\t%s\n", label);
|
||||||
|
fprintf(f, "%s:\n", label);
|
||||||
|
}
|
||||||
fprintf(f, "\t.long\tOF_DT_PROP\n");
|
fprintf(f, "\t.long\tOF_DT_PROP\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +272,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
|
||||||
struct node *child;
|
struct node *child;
|
||||||
int seen_name_prop = 0;
|
int seen_name_prop = 0;
|
||||||
|
|
||||||
emit->beginnode(etarget);
|
emit->beginnode(etarget, tree->label);
|
||||||
|
|
||||||
if (vi->flags & FTF_FULLPATH)
|
if (vi->flags & FTF_FULLPATH)
|
||||||
emit->string(etarget, tree->fullpath, 0);
|
emit->string(etarget, tree->fullpath, 0);
|
||||||
|
@ -270,7 +289,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
|
||||||
|
|
||||||
nameoff = stringtable_insert(strbuf, prop->name);
|
nameoff = stringtable_insert(strbuf, prop->name);
|
||||||
|
|
||||||
emit->property(etarget);
|
emit->property(etarget, prop->label);
|
||||||
emit->cell(etarget, prop->val.len);
|
emit->cell(etarget, prop->val.len);
|
||||||
emit->cell(etarget, nameoff);
|
emit->cell(etarget, nameoff);
|
||||||
|
|
||||||
|
@ -282,7 +301,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) {
|
if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) {
|
||||||
emit->property(etarget);
|
emit->property(etarget, NULL);
|
||||||
emit->cell(etarget, tree->basenamelen+1);
|
emit->cell(etarget, tree->basenamelen+1);
|
||||||
emit->cell(etarget, stringtable_insert(strbuf, "name"));
|
emit->cell(etarget, stringtable_insert(strbuf, "name"));
|
||||||
|
|
||||||
|
@ -296,7 +315,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
|
||||||
flatten_tree(child, emit, etarget, strbuf, vi);
|
flatten_tree(child, emit, etarget, strbuf, vi);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit->endnode(etarget);
|
emit->endnode(etarget, tree->label);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void make_bph(struct boot_param_header *bph,
|
static void make_bph(struct boot_param_header *bph,
|
||||||
|
@ -377,13 +396,6 @@ void dump_stringtable_asm(FILE *f, struct data strbuf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_label(FILE *f, char *prefix, char *label)
|
|
||||||
{
|
|
||||||
fprintf(f, "\t.globl\t%s_%s\n", prefix, label);
|
|
||||||
fprintf(f, "%s_%s:\n", prefix, label);
|
|
||||||
fprintf(f, "_%s_%s:\n", prefix, label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_dt_asm(FILE *f, struct node *tree, int version, int reservenum)
|
void write_dt_asm(FILE *f, struct node *tree, int version, int reservenum)
|
||||||
{
|
{
|
||||||
struct version_info *vi = NULL;
|
struct version_info *vi = NULL;
|
||||||
|
@ -566,7 +578,7 @@ struct property *flat_read_property(struct inbuf *dtbuf, struct inbuf *strbuf,
|
||||||
|
|
||||||
val = flat_read_data(dtbuf, proplen);
|
val = flat_read_data(dtbuf, proplen);
|
||||||
|
|
||||||
return build_property(name, val);
|
return build_property(name, val, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *nodename_from_path(char *ppath, char *cpath)
|
static char *nodename_from_path(char *ppath, char *cpath)
|
||||||
|
|
8
fstree.c
8
fstree.c
|
@ -60,7 +60,8 @@ static struct node *read_fstree(char *dirname)
|
||||||
} else {
|
} else {
|
||||||
prop = build_property(strdup(de->d_name),
|
prop = build_property(strdup(de->d_name),
|
||||||
data_copy_file(pfile,
|
data_copy_file(pfile,
|
||||||
st.st_size));
|
st.st_size),
|
||||||
|
NULL);
|
||||||
add_property(tree, prop);
|
add_property(tree, prop);
|
||||||
fclose(pfile);
|
fclose(pfile);
|
||||||
}
|
}
|
||||||
|
@ -68,7 +69,8 @@ static struct node *read_fstree(char *dirname)
|
||||||
struct node *newchild;
|
struct node *newchild;
|
||||||
|
|
||||||
newchild = read_fstree(tmpnam);
|
newchild = read_fstree(tmpnam);
|
||||||
newchild = name_node(newchild, strdup(de->d_name));
|
newchild = name_node(newchild, strdup(de->d_name),
|
||||||
|
NULL);
|
||||||
add_child(tree, newchild);
|
add_child(tree, newchild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +85,7 @@ struct node *dt_from_fs(char *dirname)
|
||||||
struct node *tree;
|
struct node *tree;
|
||||||
|
|
||||||
tree = read_fstree(dirname);
|
tree = read_fstree(dirname);
|
||||||
tree = name_node(tree, "");
|
tree = name_node(tree, "", NULL);
|
||||||
|
|
||||||
fill_fullpaths(tree, "");
|
fill_fullpaths(tree, "");
|
||||||
|
|
||||||
|
|
13
livetree.c
13
livetree.c
|
@ -24,7 +24,7 @@
|
||||||
* Tree building functions
|
* Tree building functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct property *build_property(char *name, struct data val)
|
struct property *build_property(char *name, struct data val, char *label)
|
||||||
{
|
{
|
||||||
struct property *new = xmalloc(sizeof(*new));
|
struct property *new = xmalloc(sizeof(*new));
|
||||||
|
|
||||||
|
@ -33,10 +33,12 @@ struct property *build_property(char *name, struct data val)
|
||||||
|
|
||||||
new->next = NULL;
|
new->next = NULL;
|
||||||
|
|
||||||
|
new->label = label;
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct property *build_empty_property(char *name)
|
struct property *build_empty_property(char *name, char *label)
|
||||||
{
|
{
|
||||||
struct property *new = xmalloc(sizeof(*new));
|
struct property *new = xmalloc(sizeof(*new));
|
||||||
|
|
||||||
|
@ -46,6 +48,8 @@ struct property *build_empty_property(char *name)
|
||||||
|
|
||||||
new->next = NULL;
|
new->next = NULL;
|
||||||
|
|
||||||
|
new->label = label;
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,11 +78,14 @@ struct node *build_node(struct property *proplist, struct node *children)
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node *name_node(struct node *node, char *name)
|
struct node *name_node(struct node *node, char *name, char * label)
|
||||||
{
|
{
|
||||||
assert(node->name == NULL);
|
assert(node->name == NULL);
|
||||||
|
|
||||||
node->name = name;
|
node->name = name;
|
||||||
|
|
||||||
|
node->label = label;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
8
test.dts
8
test.dts
|
@ -2,9 +2,9 @@
|
||||||
model = "MyBoardName";
|
model = "MyBoardName";
|
||||||
compatible = "MyBoardFamilyName";
|
compatible = "MyBoardFamilyName";
|
||||||
#address-cells = <2>;
|
#address-cells = <2>;
|
||||||
#size-cells = <2>;
|
label1: #size-cells = <2>;
|
||||||
|
|
||||||
cpus {
|
label2: cpus {
|
||||||
linux,phandle = <1>;
|
linux,phandle = <1>;
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
@ -15,12 +15,14 @@
|
||||||
clock-frequency = <5f5e1000>;
|
clock-frequency = <5f5e1000>;
|
||||||
linux,boot-cpu;
|
linux,boot-cpu;
|
||||||
linux,phandle = <2>;
|
linux,phandle = <2>;
|
||||||
|
i-cache-size = <10000>;
|
||||||
|
d-cache-size = <8000>;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
randomnode {
|
randomnode {
|
||||||
string = "\xff\0stuffstuff\t\t\t\n\n\n\n";
|
string = "\xff\0stuffstuff\t\t\t\n\n\n";
|
||||||
blob = [0a 0b 0c 0d de ea ad be ef];
|
blob = [0a 0b 0c 0d de ea ad be ef];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue