aboutsummaryrefslogtreecommitdiff
path: root/sys/tools
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2006-06-16 21:06:03 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2006-06-16 21:06:03 +0000
commitc3e7da2b4cbe0250ec724f6ad9c32633435644db (patch)
tree9112b3cf1ea7278859f4bb0f9476eb0424135c9d /sys/tools
parent93ef14a74be3615c15d98e0282ab01d0ea000e55 (diff)
downloadsrc-c3e7da2b4cbe0250ec724f6ad9c32633435644db.tar.gz
src-c3e7da2b4cbe0250ec724f6ad9c32633435644db.zip
Check for errors when registering and unregistering firmware modules. This
prevents the unfortunate situation whereby one might kldload a firmware module by hand and later kldunload it while a driver still has an open reference to it. MFC after: 1 week Glanced at by: iedowse
Notes
Notes: svn path=/head/; revision=159670
Diffstat (limited to 'sys/tools')
-rw-r--r--sys/tools/fw_stub.awk37
1 files changed, 25 insertions, 12 deletions
diff --git a/sys/tools/fw_stub.awk b/sys/tools/fw_stub.awk
index e15501045e45..3e4463e268f9 100644
--- a/sys/tools/fw_stub.awk
+++ b/sys/tools/fw_stub.awk
@@ -125,7 +125,8 @@ for (file_i = 0; file_i < num_files; file_i++) {
printc("\nstatic int\n"\
opt_m "_fw_modevent(module_t mod, int type, void *unused)\
{\
- struct firmware *fp;\
+ struct firmware *fp, *parent;\
+ int error;\
switch (type) {\
case MOD_LOAD:");
@@ -136,11 +137,7 @@ for (file_i = 0; file_i < num_files; file_i++) {
# '-', '.' and '/' are converted to '_' by ld/objcopy
gsub(/-|\.|\//, "_", symb);
- if (file_i == 0)
- reg = "\t\tfp = ";
- else
- reg = "\t\t(void)";
-
+ reg = "\t\tfp = ";
reg = reg "firmware_register(\"" short "\", _binary_" symb "_start , ";
reg = reg "(size_t)(_binary_" symb "_end - _binary_" symb "_start), ";
reg = reg version ", ";
@@ -148,21 +145,37 @@ for (file_i = 0; file_i < num_files; file_i++) {
if (file_i == 0)
reg = reg "NULL);";
else
- reg = reg "fp);";
+ reg = reg "parent);";
printc(reg);
+
+ printc("\t\tif (fp == NULL)");
+ printc("\t\t\tgoto fail_" file_i ";");
+ if (file_i == 0)
+ printc("\t\tparent = fp;");
}
-printc("\t\treturn (0);\
- case MOD_UNLOAD:");
+printc("\t\treturn (0);");
+
+for (file_i = num_files - 1; file_i > 0; file_i--) {
+ printc("\tfail_" file_i ":")
+ printc("\t\t(void)firmware_unregister(\"" shortnames[file_i - 1] "\");");
+}
+
+printc("\tfail_0:");
+printc("\t\treturn (ENXIO);");
+
+printc("\tcase MOD_UNLOAD:");
for (file_i = 1; file_i < num_files; file_i++) {
- printc("\t\tfirmware_unregister(\"" shortnames[file_i] "\");");
+ printc("\t\terror = firmware_unregister(\"" shortnames[file_i] "\");");
+ printc("\t\tif (error)");
+ printc("\t\t\treturn (error);");
}
-printc("\t\tfirmware_unregister(\"" shortnames[0] "\");");
+printc("\t\terror = firmware_unregister(\"" shortnames[0] "\");");
-printc("\t\treturn (0);\
+printc("\t\treturn (error);\
}\
return (EINVAL);\
}\