xref: /haiku/src/libs/compat/freebsd_network/firmware.c (revision a76f629efad0ba4d6518d918a39dbcc6097fe536)
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 = 0;
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 	lseek(fileDescriptor, 0, SEEK_SET);
79 
80 	fbsdFirmwareNameCopy = strndup(fbsdFirmwareName,
81 		MAX_FBSD_FIRMWARE_NAME_CHARS);
82 	if (fbsdFirmwareNameCopy == NULL)
83 		goto cleanup;
84 
85 	firmware = (struct firmware*)malloc(sizeof(struct firmware));
86 	if (firmware == NULL)
87 		goto cleanup;
88 
89 	firmware->data = malloc(firmwareFileSize);
90 	if (firmware->data == NULL)
91 		goto cleanup;
92 
93 	readCount = read(fileDescriptor, (void*)firmware->data, firmwareFileSize);
94 	if (readCount == -1 || readCount < firmwareFileSize) {
95 		free((void*)firmware->data);
96 		goto cleanup;
97 	}
98 
99 	firmware->datasize = firmwareFileSize;
100 	firmware->name = fbsdFirmwareNameCopy;
101 	firmware->version = __haiku_firmware_version;
102 
103 	close(fileDescriptor);
104 	free(firmwarePath);
105 	return firmware;
106 
107 cleanup:
108 	if (firmware)
109 		free(firmware);
110 	if (fbsdFirmwareNameCopy)
111 		free(fbsdFirmwareNameCopy);
112 	if (firmwarePath)
113 		free(firmwarePath);
114 	if (fileDescriptor)
115 		close(fileDescriptor);
116 	return NULL;
117 }
118 
119 
120 void
121 firmware_put(const struct firmware* firmware, int flags)
122 {
123 	if (firmware == NULL)
124 		return;
125 
126 	if (firmware->data)
127 		free((void*)firmware->data);
128 	if (firmware->name)
129 		free((void*)firmware->name);
130 	free((void*)firmware);
131 }
132