xref: /haiku/src/libs/compat/freebsd_network/firmware.c (revision 7749d0bb0c358a3279b1b9cc76d8376e900130a5)
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*
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*
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 
57 	haikuFirmwareName = getHaikuFirmwareName(fbsdFirmwareName,
58 		fbsdFirmwareName);
59 
60 	firmwarePath = (char*)malloc(B_PATH_NAME_LENGTH);
61 	if (firmwarePath == NULL)
62 		goto cleanup;
63 
64 	if (find_directory(B_SYSTEM_DATA_DIRECTORY, -1, false,
65 		firmwarePath, B_PATH_NAME_LENGTH) != B_OK)
66 		goto cleanup;
67 
68 	strlcat(firmwarePath, "/firmware/", B_PATH_NAME_LENGTH);
69 	strlcat(firmwarePath, gDriverName, B_PATH_NAME_LENGTH);
70 	strlcat(firmwarePath, "/", B_PATH_NAME_LENGTH);
71 	strlcat(firmwarePath, haikuFirmwareName, B_PATH_NAME_LENGTH);
72 
73 	fileDescriptor = open(firmwarePath, B_READ_ONLY);
74 	if (fileDescriptor == -1)
75 		goto cleanup;
76 
77 	firmwareFileSize = lseek(fileDescriptor, 0, SEEK_END);
78 	if (firmwareFileSize == -1)
79 		goto cleanup;
80 
81 	lseek(fileDescriptor, 0, SEEK_SET);
82 
83 	fbsdFirmwareNameCopy = strndup(fbsdFirmwareName,
84 		MAX_FBSD_FIRMWARE_NAME_CHARS);
85 	if (fbsdFirmwareNameCopy == NULL)
86 		goto cleanup;
87 
88 	firmware = (struct firmware*)malloc(sizeof(struct firmware));
89 	if (firmware == NULL)
90 		goto cleanup;
91 
92 	firmware->data = malloc(firmwareFileSize);
93 	if (firmware->data == NULL)
94 		goto cleanup;
95 
96 	readCount = read(fileDescriptor, (void*)firmware->data, firmwareFileSize);
97 	if (readCount == -1 || readCount < firmwareFileSize) {
98 		free((void*)firmware->data);
99 		goto cleanup;
100 	}
101 
102 	firmware->datasize = firmwareFileSize;
103 	firmware->name = fbsdFirmwareNameCopy;
104 	firmware->version = __haiku_firmware_version;
105 
106 	close(fileDescriptor);
107 	free(firmwarePath);
108 	return firmware;
109 
110 cleanup:
111 	if (firmware)
112 		free(firmware);
113 	if (fbsdFirmwareNameCopy)
114 		free(fbsdFirmwareNameCopy);
115 	if (firmwarePath)
116 		free(firmwarePath);
117 	if (fileDescriptor >= 0)
118 		close(fileDescriptor);
119 	return NULL;
120 }
121 
122 
123 void
124 firmware_put(const struct firmware* firmware, int flags)
125 {
126 	if (firmware == NULL)
127 		return;
128 
129 	if (firmware->data)
130 		free((void*)firmware->data);
131 	if (firmware->name)
132 		free((void*)firmware->name);
133 	free((void*)firmware);
134 }
135