blob: 46037411ae9c71f85143397c81c7a3b02c916d44 [file] [log] [blame]
/* adapter_firmware.c
*
* Kernel-space implementation of Interface for obtaining the firmware image.
* Read from file system using Linux firmware API.
*/
/*****************************************************************************
* Copyright (c) 2016-2020 by Rambus, Inc. and/or its subsidiaries.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
/*----------------------------------------------------------------------------
* This module implements (provides) the following interface(s):
*/
#include "adapter_firmware.h"
/*----------------------------------------------------------------------------
* This module uses (requires) the following interface(s):
*/
#include "c_adapter_firmware.h"
// Driver Framework Basic Defs API
#include "basic_defs.h"
#include <linux/firmware.h>
#include "adapter_alloc.h"
// Logging API
#include "log.h"
#include "device_mgmt.h" // Device_GetReference()
/*----------------------------------------------------------------------------
* Adapter_Firmware_NULL
*
*/
const Adapter_Firmware_t Adapter_Firmware_NULL = NULL;
/*----------------------------------------------------------------------------
* Adapter_Firmware_Acquire
*/
Adapter_Firmware_t
Adapter_Firmware_Acquire(
const char * Firmware_Name_p,
const uint32_t ** Firmware_p,
unsigned int * Firmware_Word32Count)
{
uint32_t * Firmware_Data_p;
const struct firmware *firmware;
int rc;
unsigned int i;
LOG_CRIT("Adapter_Firmware_Acquire for %s\n",Firmware_Name_p);
// Initialize output parameters.
*Firmware_p = NULL;
*Firmware_Word32Count = 0;
// Request firmware via kernel API.
rc = request_firmware(&firmware,
Firmware_Name_p,
Device_GetReference(NULL, NULL));
if (rc < 0)
{
LOG_CRIT("Adapter_Firmware_Acquire request of %s failed, rc=%d\n",
Firmware_Name_p, rc);
return NULL;
}
if (firmware->data == NULL ||
firmware->size == 0 ||
firmware->size >= 256*1024 ||
firmware->size % sizeof(uint32_t) != 0)
{
LOG_CRIT("Adapter_Firmware_Acquire: Invalid image size %d\n",
(int)firmware->size);
release_firmware(firmware);
return NULL;
}
// Allocate buffer for data
Firmware_Data_p = Adapter_Alloc(firmware->size);
if (Firmware_Data_p == NULL)
{
LOG_CRIT("Adapter_Firmware_Acquire: Failed to allocate\n");
release_firmware(firmware);
return NULL;
}
// Convert bytes from file to array of 32-bit words.
{
const uint8_t *p = firmware->data;
for (i=0; i<firmware->size / sizeof(uint32_t); i++)
{
Firmware_Data_p[i] = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
p += sizeof(uint32_t);
}
}
// Pass results to caller
*Firmware_p = Firmware_Data_p;
*Firmware_Word32Count = firmware->size / sizeof(uint32_t);
// Release firmware data structure.
release_firmware(firmware);
return (Adapter_Firmware_t)Firmware_Data_p;
}
/*----------------------------------------------------------------------------
* Adapter_Firmware_Release
*/
void
Adapter_Firmware_Release(
Adapter_Firmware_t FirmwareHandle)
{
LOG_CRIT("Adapter_Firmware_Release\n");
Adapter_Free((void*)FirmwareHandle);
}
/* end of file adapter_firmware.c */