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