aboutsummaryrefslogtreecommitdiffstats
path: root/tools/patch-image/src/patch-dtb.c
blob: a94da3fa41577c398e1d3262fe4041cf94c8c48a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
 * patch-dtb.c - patch a dtb into an image
 *
 * Copyright (C) 2006 Felix Fietkau <nbd@nbd.name>
 * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * based on patch-cmdline.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>

#define DTB_MAX	(16 * 1024)

int main(int argc, char **argv)
{
	int fd, fddtb, found = 0, len, ret = -1;
	char *ptr, *ptrdtb, *p;
	struct stat s;
	unsigned int search_space , dtb_max_size;

	if (argc <= 2 || argc > 4) {
		fprintf(stderr, "Usage: %s <file> <dtb> [size]\n", argv[0]);
		goto err1;
	} else if (argc == 3) {
		fprintf(stdout, "DT size used is default of 16KB\n");
		search_space = dtb_max_size = DTB_MAX;
	} else {
		search_space = dtb_max_size = atoi(argv[3]);
	}

	if (stat(argv[2], &s)) {
		fprintf(stderr, "DTB not found\n");
		goto err1;
	}

	len = s.st_size;
	if (len + 8 > dtb_max_size) {
		fprintf(stderr, "DTB too big\n");
		goto err1;
	}

        if (((fddtb = open(argv[2], O_RDONLY)) < 0) ||
		(ptrdtb = (char *) mmap(0, dtb_max_size, PROT_READ, MAP_SHARED, fddtb, 0)) == (void *) (-1)) {
		fprintf(stderr, "Could not open DTB");
		goto err2;
	}

	if (((fd = open(argv[1], O_RDWR)) < 0) ||
		(ptr = (char *) mmap(0, search_space + dtb_max_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == (void *) (-1)) {
		fprintf(stderr, "Could not open kernel image");
		goto err3;
	}

	for (p = ptr; p < (ptr + search_space); p += 4) {
		if (memcmp(p, "OWRTDTB:", 8) == 0) {
			found = 1;
			p += 8;
			break;
		}
	}
	if (!found) {
		fprintf(stderr, "DTB marker not found!\n");
		goto err4;
	}

	memset(p, 0, dtb_max_size - 8);
	memcpy(p, ptrdtb, len);
	msync(p, len, MS_SYNC|MS_INVALIDATE);
	ret = 0;

err4:
	munmap((void *) ptr, len);
err3:
	if (fd > 0)
		close(fd);
	munmap((void *) ptrdtb, len);
err2:
	if (fddtb > 0)
		close(fddtb);
err1:
	return ret;
}
nto multiple nl_dump() calls. * nl_dump(params, "String: %s ", my_obj->my_string); * nl_dump(params, "String-2: %s\n", my_obj->another_string); * } * * struct nl_object_ops my_ops = { * ... * .oo_dump[NL_DUMP_FULL] = my_obj_dump_detailed, * }; * @endcode * * @par 4) Object Attributes * @code * // The concept of object attributes is optional but can ease the typical * // case of objects that have optional attributes, e.g. a route may have a * // nexthop assigned but it is not required to. * * // The first step to define your object specific bitmask listing all * // attributes * #define MY_ATTR_FOO (1<<0) * #define MY_ATTR_BAR (1<<1) * * // When assigning an optional attribute to the object, make sure * // to mark its availability. * my_obj->foo = 123123; * my_obj->ce_mask |= MY_ATTR_FOO; * * // At any time you may use this mask to check for the availability * // of the attribute, e.g. while dumping * if (my_obj->ce_mask & MY_ATTR_FOO) * nl_dump(params, "foo %d ", my_obj->foo); * * // One of the big advantages of this concept is that it allows for * // standardized comparisons which make it trivial for caches to * // identify unique objects by use of unified comparison functions. * // In order for it to work, your object implementation must provide * // a comparison function and define a list of attributes which * // combined together make an object unique. * * static int my_obj_compare(struct nl_object *_a, struct nl_object *_b, * uint32_t attrs, int flags) * { * struct my_obj *a = nl_object_priv(_a): * struct my_obj *b = nl_object_priv(_b): * int diff = 0; * * // We help ourselves in defining our own DIFF macro which will * // call ATTR_DIFF() on both objects which will make sure to only * // compare the attributes if required. * #define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MY_ATTR_##ATTR, a, b, EXPR) * * // Call our own diff macro for each attribute to build a bitmask * // representing the attributes which mismatch. * diff |= MY_DIFF(FOO, a->foo != b->foo) * diff |= MY_DIFF(BAR, strcmp(a->bar, b->bar)) * * return diff; * } * * // In order to identify identical objects with differing attributes * // you must specify the attributes required to uniquely identify * // your object. Make sure to not include too many attributes, this * // list is used when caches look for an old version of an object. * struct nl_object_ops my_ops = { * ... * .oo_id_attrs = MY_ATTR_FOO, * .oo_compare = my_obj_compare, * }; * @endcode * @{ */ /** * Common Object Header * * This macro must be included as first member in every object * definition to allow objects to be cached. */ #define NLHDR_COMMON \ int ce_refcnt; \ struct nl_object_ops * ce_ops; \ struct nl_cache * ce_cache; \ struct nl_list_head ce_list; \ int ce_msgtype; \ int ce_flags; \ uint32_t ce_mask; /** * Return true if attribute is available in both objects * @arg A an object * @arg B another object * @arg ATTR attribute bit * * @return True if the attribute is available, otherwise false is returned. */ #define AVAILABLE(A, B, ATTR) (((A)->ce_mask & (B)->ce_mask) & (ATTR)) /** * Return true if attributes mismatch * @arg A an object * @arg B another object * @arg ATTR attribute bit * @arg EXPR Comparison expression * * This function will check if the attribute in question is available * in both objects, if not this will count as a mismatch. * * If available the function will execute the expression which must * return true if the attributes mismatch. * * @return True if the attribute mismatch, or false if they match. */ #define ATTR_MISMATCH(A, B, ATTR, EXPR) (!AVAILABLE(A, B, ATTR) || (EXPR)) /** * Return attribute bit if attribute does not match * @arg LIST list of attributes to be compared * @arg ATTR attribute bit * @arg A an object * @arg B another object * @arg EXPR Comparison expression * * This function will check if the attribute in question is available * in both objects, if not this will count as a mismatch. * * If available the function will execute the expression which must * return true if the attributes mismatch. * * In case the attributes mismatch, the attribute is returned, otherwise * 0 is returned. * * @code * diff |= ATTR_DIFF(attrs, MY_ATTR_FOO, a, b, a->foo != b->foo); * @endcode */ #define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \ ({ int diff = 0; \ if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \ diff = ATTR; \ diff; }) /** * Object Operations */ struct nl_object; struct nl_object_ops { /** * Unique name of object type * * Must be in the form family/name, e.g. "route/addr" */ char * oo_name; /** Size of object including its header */ size_t oo_size; /* List of attributes needed to uniquely identify the object */ uint32_t oo_id_attrs; /** * Constructor function * * Will be called when a new object of this type is allocated. * Can be used to initialize members such as lists etc. */ void (*oo_constructor)(struct nl_object *); /** * Destructor function * * Will be called when an object is freed. Must free all * resources which may have been allocated as part of this * object. */ void (*oo_free_data)(struct nl_object *); /** * Cloning function * * Will be called when an object needs to be cloned. Please * note that the generic object code will make an exact * copy of the object first, therefore you only need to take * care of members which require reference counting etc. * * May return a negative error code to abort cloning. */ int (*oo_clone)(struct nl_object *, struct nl_object *); /** * Dumping functions * * Will be called when an object is dumped. The implementations * have to use nl_dump(), nl_dump_line(), and nl_new_line() to * dump objects. * * The functions must return the number of lines printed. */ void (*oo_dump[NL_DUMP_MAX+1])(struct nl_object *, struct nl_dump_params *); /** * Comparison function * * Will be called when two objects of the same type are * compared. It takes the two objects in question, an object * specific bitmask defining which attributes should be * compared and flags to control the behaviour. * * The function must return a bitmask with the relevant bit * set for each attribute that mismatches. */ int (*oo_compare)(struct nl_object *, struct nl_object *, uint32_t, int); char *(*oo_attrs2str)(int, char *, size_t); }; /** @} */ #ifdef __cplusplus } #endif #endif