Project

General

Profile

fw-remove-parent.patch

sucanjan@fit.cvut.cz, 05/25/2017 05:23 AM

Download (13.3 KB)

View differences:

share/examples/kld/firmware/wrap-fw_module.sh
70 70
  int error;
71 71
  switch (type) {
72 72
  case MOD_LOAD:
73
    fp = firmware_register("${MODNAME}", _binary_${FWSYM}_start , (size_t)(_binary_${FWSYM}_end - _binary_${FWSYM}_start), 0, NULL);
73
    fp = firmware_register("${MODNAME}", _binary_${FWSYM}_start , (size_t)(_binary_${FWSYM}_end - _binary_${FWSYM}_start), 0);
74 74
    if (fp == NULL)
75 75
      goto fail_0;
76 76
    return (0);
share/man/man9/firmware.9
51 51
.Fa "const void *data"
52 52
.Fa "size_t datasize"
53 53
.Fa "unsigned int version"
54
.Fa "const struct firmware *parent"
55 54
.Fc
56 55
.Ft int
57 56
.Fn firmware_unregister "const char *imagename"
......
195 194
.Nm kern.module_path
196 195
which on most systems defaults to
197 196
.Nm /boot/kernel;/boot/modules .
198
.Pp
199
Note that in case a module contains multiple images,
200
the caller should first request a
201
.Fn firmware_get
202
for the first image contained in the module, followed by requests
203
for the other images.
204 197
.Sh BUILDING FIRMWARE LOADABLE MODULES
205 198
A firmware module is built by embedding the
206 199
.Nm firmware image
......
219 212
        .include <bsd.kmod.mk>
220 213

  
221 214
.Ed
222
where KMOD is the basename of the module; FIRMWS is a list of
223
colon-separated tuples indicating the image_file's to be embedded
224
in the module, the imagename and version of each firmware image.
215
where KMOD is the basename of the module; FIRMWS is a colon-separated
216
tuple indicating the image_file to be embedded in the module, the
217
imagename and version of the firmware image.
225 218
.Pp
226 219
If you need to embed firmware images into a system, you should write
227 220
appropriate entries in the
sys/dev/disk/ispfw/ispfw.c
143 143
		break;							\
144 144
	if (firmware_register(#token, token##_risc_code,		\
145 145
	    token##_risc_code[3] * sizeof(token##_risc_code[3]),	\
146
	    ISPFW_VERSION, NULL) == NULL) {				\
146
	    ISPFW_VERSION) == NULL) {   				\
147 147
		kprintf("%s: unable to register firmware <%s>\n",	\
148 148
		    MODULE_NAME, #token);				\
149 149
		break;							\
sys/kern/subr_firmware.c
69 69
 *
70 70
 * In order for the above to work, the 'file' field must remain
71 71
 * unchanged in firmware_unregister().
72
 *
73
 * Images residing in the same module are linked to each other
74
 * through the 'parent' argument of firmware_register().
75
 * One image (typically, one with the same name as the module to let
76
 * the autoloading mechanism work) is considered the parent image for
77
 * all other images in the same module. Children affect the refcount
78
 * on the parent image preventing improper unloading of the image itself.
79 72
 */
80 73

  
81 74
struct priv_fw {
82 75
	int		refcnt;		/* reference count */
83 76

  
84
	/*
85
	 * parent entry, see above. Set on firmware_register(),
86
	 * cleared on firmware_unregister().
87
	 */
88
	struct priv_fw	*parent;
89

  
90 77
	int 		flags;	/* record FIRMWARE_UNLOAD requests */
91 78
#define FW_UNLOAD	0x100
92 79

  
......
165 152

  
166 153
/*
167 154
 * Register a firmware image with the specified name.  The
168
 * image name must not already be registered.  If this is a
169
 * subimage then parent refers to a previously registered
170
 * image that this should be associated with.
155
 * image name must not already be registered.
171 156
 */
172 157
const struct firmware *
173 158
firmware_register(const char *imagename, const void *data, size_t datasize,
174
    unsigned int version, const struct firmware *parent)
159
    unsigned int version)
175 160
{
176 161
	struct priv_fw *match, *frp;
177 162

  
......
197 182
	frp->fw.data = data;
198 183
	frp->fw.datasize = datasize;
199 184
	frp->fw.version = version;
200
	if (parent != NULL) {
201
		frp->parent = PRIV_FW(parent);
202
		frp->parent->refcnt++;
203
	}
185

  
204 186
	lockmgr(&firmware_lock, LK_RELEASE);
205 187
	if (bootverbose)
206 188
		kprintf("firmware: '%s' version %u: %zu bytes loaded at %p\n",
......
225 207
		/*
226 208
		 * It is ok for the lookup to fail; this can happen
227 209
		 * when a module is unloaded on last reference and the
228
		 * module unload handler unregister's each of it's
229
		 * firmware images.
210
		 * module unload handler unregisters it's firmware
211
		 * image.
230 212
		 */
231 213
		err = 0;
232 214
	} else if (fp->refcnt != 0) {	/* cannot unregister */
......
234 216
	}  else {
235 217
		linker_file_t x = fp->file;	/* save value */
236 218

  
237
		if (fp->parent != NULL)	/* release parent reference */
238
			fp->parent->refcnt--;
239 219
		/*
240 220
		 * Clear the whole entry with bzero to make sure we
241 221
		 * do not forget anything. Then restore 'file' which is
......
429 409
static void
430 410
unloadentry(void *unused1, int unused2)
431 411
{
432
	int limit = FIRMWARE_MAX;
433
	int i;	/* current cycle */
412
	int i;
434 413

  
435 414
	lockmgr(&firmware_lock, LK_EXCLUSIVE);
436
	/*
437
	 * Scan the table. limit is set to make sure we make another
438
	 * full sweep after matching an entry that requires unloading.
439
	 */
440
	for (i = 0; i < limit; i++) {
415
	/* Scan the table. */
416
	for (i = 0; i < FIRMWARE_MAX; i++) {
441 417
		struct priv_fw *fp;
442 418
		int err;
443 419

  
444
		fp = &firmware_table[i % FIRMWARE_MAX];
420
		fp = &firmware_table[i];
445 421
		if (fp->fw.name == NULL || fp->file == NULL ||
446 422
		    fp->refcnt != 0 || (fp->flags & FW_UNLOAD) == 0)
447 423
			continue;
448 424

  
449 425
		/*
450 426
		 * Found an entry. Now:
451
		 * 1. bump up limit to make sure we make another full round;
452
		 * 2. clear FW_UNLOAD so we don't try this entry again.
453
		 * 3. release the lock while trying to unload the module.
427
		 * 1. clear FW_UNLOAD so we don't try this entry again
428
		 *    if unloading will be unsuccessful.
429
		 * 2. release the lock while trying to unload the module.
454 430
		 * 'file' remains set so that the entry cannot be reused
455 431
		 * in the meantime (it also means that fp->file will
456 432
		 * not change while we release the lock).
457 433
		 */
458
		limit = i + FIRMWARE_MAX;	/* make another full round */
459 434
		fp->flags &= ~FW_UNLOAD;	/* do not try again */
460 435

  
461 436
		lockmgr(&firmware_lock, LK_RELEASE);
sys/sys/firmware.h
33 33
 * The firmware abstraction provides an interface for loading firmware
34 34
 * images into the kernel and making them available to clients.
35 35
 *
36
 * Firmware images are usually embedded in kernel loadable modules that can
37
 * be loaded on-demand or pre-loaded as desired.  Modules may contain
38
 * one or more firmware images that are stored as opaque data arrays
39
 * and registered with a unique string name. Clients request
40
 * firmware by name, and are returned a struct firmware * below on success.
41
 * The kernel keeps track of references to firmware images to allow/prevent
42
 * module/data unload.
36
 * Firmware images are usually embedded in kernel loadable modules
37
 * that can be loaded on-demand or pre-loaded as desired.  Modules may
38
 * contain one firmware image that is stored as opaque data array and
39
 * registered with a unique string name. Clients request firmware by
40
 * name, and are returned a struct firmware * below on success.  The
41
 * kernel keeps track of references to firmware images to
42
 * allow/prevent module/data unload.
43 43
 *
44
 * When multiple images are stored in one module, the first image is
45
 * treated as the master with the other images holding references
46
 * to it.  This means that to unload the module each dependent/subimage
47
 * must first have its references removed.
48 44
 * In order for automatic loading to work, the master image must have
49 45
 * the same name as the module it is embedded into.
50 46
 */
......
56 52
};
57 53

  
58 54
const struct firmware	*firmware_register(const char *,
59
	const void *, size_t, unsigned int, const struct firmware *);
55
	const void *, size_t, unsigned int);
60 56
int	 firmware_unregister(const char *);
61 57
const struct firmware *firmware_get(const char *);
62 58
#define	FIRMWARE_UNLOAD		0x0001	/* unload if unreferenced */
sys/tools/fw_stub.awk
33 33

  
34 34
function usage ()
35 35
{
36
	print "usage: fw_stub <firmware:name>* [-l name] [-m modname] [-c outfile]";
36
	print "usage: fw_stub <firmware:name> [-l name] [-m modname] [-c outfile]";
37 37
	exit 1;
38 38
}
39 39

  
......
98 98
			} else
99 99
				usage();
100 100
		}
101
	} else {
101
	} else if (num_files == 0) {
102 102
		split(ARGV[i], curr, ":");
103
		filenames[num_files] = curr[1];
103
		filename = curr[1];
104 104
		if (length(curr[2]) > 0)
105
			shortnames[num_files] = curr[2];
105
			shortname = curr[2];
106 106
		else
107
			shortnames[num_files] = curr[1];
107
			shortname = curr[1];
108 108
		if (length(curr[3]) > 0)
109
			versions[num_files] = int(curr[3]);
109
			version = int(curr[3]);
110 110
		else
111
			versions[num_files] = 0;
111
			version = 0;
112 112
		num_files++;
113
	} else {
114
		# The argument is a firmware image specification
115
		# but we already have one
116
		usage();
113 117
	}
114 118
}
115 119

  
......
133 137
	printc("static long " opt_l "_license_ack = 0;");
134 138
}
135 139

  
136
for (file_i = 0; file_i < num_files; file_i++) {
137
	symb = filenames[file_i];
138
	# '-', '.' and '/' are converted to '_' by ld/objcopy
139
	gsub(/-|\.|\//, "_", symb);
140
	printc("extern char _binary_" symb "_start[], _binary_" symb "_end[];");
141
}
140
symb = filename;
141
# '-', '.' and '/' are converted to '_' by ld/objcopy
142
gsub(/-|\.|\//, "_", symb);
143
printc("extern char _binary_" symb "_start[], _binary_" symb "_end[];");
142 144

  
143 145
printc("\nstatic int\n"\
144 146
modname "_fw_modevent(module_t mod, int type, void *unused)\
145 147
{\
146 148
	const struct firmware *fp;");
147 149

  
148
if (num_files > 1)
149
	printc("\tconst struct firmware *parent;");
150

  
151 150
printc("\tint error;\
152 151
	switch (type) {\
153 152
	case MOD_LOAD:\n");
......
162 161
		}\n");
163 162
}
164 163

  
165
for (file_i = 0; file_i < num_files; file_i++) {
166
	short = shortnames[file_i];
167
	symb = filenames[file_i];
168
	version = versions[file_i];
169
	# '-', '.' and '/' are converted to '_' by ld/objcopy
170
	gsub(/-|\.|\//, "_", symb);
164
short = shortname;
165
symb = filename;
166
version = version;
167
# '-', '.' and '/' are converted to '_' by ld/objcopy
168
gsub(/-|\.|\//, "_", symb);
171 169

  
172
	reg = "\t\tfp = ";
173
	reg = reg "firmware_register(\"" short "\", _binary_" symb "_start , ";
174
	reg = reg "(size_t)(_binary_" symb "_end - _binary_" symb "_start), ";
175
	reg = reg version ", ";
170
reg = "\t\tfp = ";
171
reg = reg "firmware_register(\"" short "\", _binary_" symb "_start , ";
172
reg = reg "(size_t)(_binary_" symb "_end - _binary_" symb "_start), ";
173
reg = reg version ");";
176 174

  
177
	if (file_i == 0)
178
		reg = reg "NULL);";
179
	else
180
		reg = reg "parent);";
175
printc(reg);
181 176

  
182
	printc(reg);
183

  
184
	printc("\t\tif (fp == NULL)");
185
	printc("\t\t\tgoto fail_" file_i ";");
186
	if (file_i == 0 && num_files > 1)
187
		printc("\t\tparent = fp;");
188
}
177
printc("\t\tif (fp == NULL)");
178
printc("\t\t\tgoto fail;");
189 179

  
190 180
printc("\t\treturn (0);");
191 181

  
192
for (file_i = num_files - 1; file_i > 0; file_i--) {
193
	printc("fail_" file_i ":")
194
	printc("\t\t(void)firmware_unregister(\"" shortnames[file_i - 1] "\");");
195
}
196

  
197
printc("\tfail_0:");
182
printc("\tfail:");
198 183
printc("\t\treturn (ENXIO);");
199 184

  
200 185
printc("\tcase MOD_UNLOAD:");
201 186

  
202
for (file_i = 1; file_i < num_files; file_i++) {
203
	printc("\t\terror = firmware_unregister(\"" shortnames[file_i] "\");");
204
	printc("\t\tif (error)");
205
	printc("\t\t\treturn (error);");
206
}
207

  
208
printc("\t\terror = firmware_unregister(\"" shortnames[0] "\");");
187
printc("\t\terror = firmware_unregister(\"" shortname "\");");
209 188

  
210 189
printc("\t\treturn (error);\
211 190
	}\
212
-