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