* Find a file which contains given module and load it, if "parent" is not * NULL, register a reference to it. */
| 2084 | * NULL, register a reference to it. |
| 2085 | */ |
| 2086 | static int |
| 2087 | linker_load_module(const char *kldname, const char *modname, |
| 2088 | struct linker_file *parent, const struct mod_depend *verinfo, |
| 2089 | struct linker_file **lfpp) |
| 2090 | { |
| 2091 | linker_file_t lfdep; |
| 2092 | const char *filename; |
| 2093 | char *pathname; |
| 2094 | int error; |
| 2095 | |
| 2096 | sx_assert(&kld_sx, SA_XLOCKED); |
| 2097 | if (modname == NULL) { |
| 2098 | /* |
| 2099 | * We have to load KLD |
| 2100 | */ |
| 2101 | KASSERT(verinfo == NULL, ("linker_load_module: verinfo" |
| 2102 | " is not NULL")); |
| 2103 | if (!linker_root_mounted()) |
| 2104 | return (ENXIO); |
| 2105 | pathname = linker_search_kld(kldname); |
| 2106 | } else { |
| 2107 | if (modlist_lookup2(modname, verinfo) != NULL) |
| 2108 | return (EEXIST); |
| 2109 | if (!linker_root_mounted()) |
| 2110 | return (ENXIO); |
| 2111 | if (kldname != NULL) |
| 2112 | pathname = strdup(kldname, M_LINKER); |
| 2113 | else |
| 2114 | /* |
| 2115 | * Need to find a KLD with required module |
| 2116 | */ |
| 2117 | pathname = linker_search_module(modname, |
| 2118 | strlen(modname), verinfo); |
| 2119 | } |
| 2120 | if (pathname == NULL) |
| 2121 | return (ENOENT); |
| 2122 | |
| 2123 | /* |
| 2124 | * Can't load more than one file with the same basename XXX: |
| 2125 | * Actually it should be possible to have multiple KLDs with |
| 2126 | * the same basename but different path because they can |
| 2127 | * provide different versions of the same modules. |
| 2128 | */ |
| 2129 | filename = linker_basename(pathname); |
| 2130 | if (linker_find_file_by_name(filename)) |
| 2131 | error = EEXIST; |
| 2132 | else do { |
| 2133 | error = linker_load_file(pathname, &lfdep); |
| 2134 | if (error) |
| 2135 | break; |
| 2136 | if (modname && verinfo && |
| 2137 | modlist_lookup2(modname, verinfo) == NULL) { |
| 2138 | linker_file_unload(lfdep, LINKER_UNLOAD_FORCE); |
| 2139 | error = ENOENT; |
| 2140 | break; |
| 2141 | } |
| 2142 | if (parent) { |
| 2143 | error = linker_file_add_dependency(parent, lfdep); |
no test coverage detected