xref: /haiku/src/libs/compat/freebsd_network/firmware.c (revision dba28784c21beab5d397068303881fe024a76859)
1 /*
2  * Copyright 2009-2010, Colin Günther, coling@gmx.de.
3  * All Rights Reserved. Distributed under the terms of the MIT License.
4  *
5  */
6 
7 
8 #include <posix/sys/mman.h>
9 
10 #include <compat/sys/param.h>
11 #include <compat/sys/firmware.h>
12 #include <compat/sys/haiku-module.h>
13 
14 #include <stdlib.h>
15 #include <string.h>
16 
17 #include <FindDirectory.h>
18 #include <StorageDefs.h>
19 #include <SupportDefs.h>
20 
21 #include <device.h>
22 
23 
24 #define MAX_FBSD_FIRMWARE_NAME_CHARS 64
25 	// For strndup, beeing cautious in kernel code is a good thing.
26 	// NB: This constant doesn't exist in FreeBSD.
27 
28 
29 static const char*
getHaikuFirmwareName(const char * fbsdFirmwareName,const char * unknownFirmwareName)30 getHaikuFirmwareName(const char* fbsdFirmwareName,
31 	const char* unknownFirmwareName)
32 {
33 	int i;
34 
35 	if (__haiku_firmware_name_map == NULL)
36 		return unknownFirmwareName;
37 
38 	for (i = 0; i < __haiku_firmware_parts_count; i++) {
39 		if (strcmp(__haiku_firmware_name_map[i][0], fbsdFirmwareName) == 0)
40 			return __haiku_firmware_name_map[i][1];
41 	}
42 	return unknownFirmwareName;
43 }
44 
45 
46 const struct firmware*
firmware_get(const char * fbsdFirmwareName)47 firmware_get(const char* fbsdFirmwareName)
48 {
49 	char*				fbsdFirmwareNameCopy = NULL;
50 	int					fileDescriptor = -1;
51 	struct firmware*	firmware = NULL;
52 	int32				firmwareFileSize;
53 	char*				firmwarePath = NULL;
54 	const char*			haikuFirmwareName = NULL;
55 	ssize_t				readCount = 0;
56 	directory_which		checkDirs[] = { B_SYSTEM_NONPACKAGED_DATA_DIRECTORY,
57 							B_SYSTEM_DATA_DIRECTORY };
58 	size_t				numCheckDirs
59 							= sizeof(checkDirs) / sizeof(checkDirs[0]);
60 	size_t				i = 0;
61 
62 	haikuFirmwareName = getHaikuFirmwareName(fbsdFirmwareName,
63 		fbsdFirmwareName);
64 
65 	firmwarePath = (char*)malloc(B_PATH_NAME_LENGTH);
66 	if (firmwarePath == NULL)
67 		goto cleanup;
68 
69 
70 	for (; i < numCheckDirs; i++) {
71 		if (find_directory(checkDirs[i], -1, false, firmwarePath,
72 				B_PATH_NAME_LENGTH) != B_OK) {
73 			continue;
74 		}
75 
76 		strlcat(firmwarePath, "/firmware/", B_PATH_NAME_LENGTH);
77 		strlcat(firmwarePath, gDriverName, B_PATH_NAME_LENGTH);
78 		strlcat(firmwarePath, "/", B_PATH_NAME_LENGTH);
79 		strlcat(firmwarePath, haikuFirmwareName, B_PATH_NAME_LENGTH);
80 
81 		fileDescriptor = open(firmwarePath, B_READ_ONLY);
82 		if (fileDescriptor >= 0)
83 			break;
84 	}
85 
86 	if (fileDescriptor < 0)
87 		goto cleanup;
88 
89 	firmwareFileSize = lseek(fileDescriptor, 0, SEEK_END);
90 	if (firmwareFileSize == -1)
91 		goto cleanup;
92 
93 	lseek(fileDescriptor, 0, SEEK_SET);
94 
95 	fbsdFirmwareNameCopy = strndup(fbsdFirmwareName,
96 		MAX_FBSD_FIRMWARE_NAME_CHARS);
97 	if (fbsdFirmwareNameCopy == NULL)
98 		goto cleanup;
99 
100 	firmware = (struct firmware*)malloc(sizeof(struct firmware));
101 	if (firmware == NULL)
102 		goto cleanup;
103 
104 	firmware->data = malloc(firmwareFileSize);
105 	if (firmware->data == NULL)
106 		goto cleanup;
107 
108 	readCount = read(fileDescriptor, (void*)firmware->data, firmwareFileSize);
109 	if (readCount == -1 || readCount < firmwareFileSize) {
110 		free((void*)firmware->data);
111 		goto cleanup;
112 	}
113 
114 	firmware->datasize = firmwareFileSize;
115 	firmware->name = fbsdFirmwareNameCopy;
116 	firmware->version = __haiku_firmware_version;
117 
118 	close(fileDescriptor);
119 	free(firmwarePath);
120 	return firmware;
121 
122 cleanup:
123 	if (firmware)
124 		free(firmware);
125 	if (fbsdFirmwareNameCopy)
126 		free(fbsdFirmwareNameCopy);
127 	if (firmwarePath)
128 		free(firmwarePath);
129 	if (fileDescriptor >= 0)
130 		close(fileDescriptor);
131 	return NULL;
132 }
133 
134 
135 void
firmware_put(const struct firmware * firmware,int flags)136 firmware_put(const struct firmware* firmware, int flags)
137 {
138 	if (firmware == NULL)
139 		return;
140 
141 	if (firmware->data)
142 		free((void*)firmware->data);
143 	if (firmware->name)
144 		free((void*)firmware->name);
145 	free((void*)firmware);
146 }
147