5be7a73c3a
git-svn-id: svn://kolibrios.org@1413 a494cfbc-eb01-0410-851d-a64ba20cac60
121 lines
2.9 KiB
C
121 lines
2.9 KiB
C
|
|
#include <linux/kernel.h>
|
|
#include <linux/byteorder/little_endian.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/firmware.h>
|
|
|
|
extern struct builtin_fw __start_builtin_fw[];
|
|
extern struct builtin_fw __end_builtin_fw[];
|
|
|
|
/* Intel HEX files actually limit the length to 256 bytes, but we have
|
|
drivers which would benefit from using separate records which are
|
|
longer than that, so we extend to 16 bits of length */
|
|
struct ihex_binrec {
|
|
__be32 addr;
|
|
__be16 len;
|
|
uint8_t data[0];
|
|
} __attribute__((packed));
|
|
|
|
/* Find the next record, taking into account the 4-byte alignment */
|
|
static inline const struct ihex_binrec *
|
|
ihex_next_binrec(const struct ihex_binrec *rec)
|
|
{
|
|
int next = ((be16_to_cpu(rec->len) + 5) & ~3) - 2;
|
|
rec = (void *)&rec->data[next];
|
|
|
|
return be16_to_cpu(rec->len) ? rec : NULL;
|
|
}
|
|
|
|
int
|
|
request_firmware(const struct firmware **firmware_p, const char *name,
|
|
struct device *device)
|
|
{
|
|
|
|
struct firmware *firmware;
|
|
struct builtin_fw *builtin;
|
|
const struct ihex_binrec *rec;
|
|
unsigned int size;
|
|
|
|
int retval;
|
|
|
|
if (!firmware_p)
|
|
return -EINVAL;
|
|
|
|
*firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
|
|
if (!firmware) {
|
|
dbgprintf("%s: kmalloc(struct firmware) failed\n", __func__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
for (builtin = __start_builtin_fw; builtin != __end_builtin_fw;
|
|
builtin++)
|
|
{
|
|
uint8_t *pfw;
|
|
|
|
if (strcmp(name, builtin->name))
|
|
continue;
|
|
dbgprintf("firmware: using built-in firmware %s\n", name);
|
|
|
|
#if 0
|
|
size = 0;
|
|
for (rec = (const struct ihex_binrec *)builtin->data;
|
|
rec; rec = ihex_next_binrec(rec))
|
|
{
|
|
size += be16_to_cpu(rec->len);
|
|
}
|
|
dbgprintf("firmware size %d\n", size);
|
|
|
|
if(unlikely( size == 0))
|
|
return -EINVAL;
|
|
|
|
|
|
pfw = (uint8_t*)kzalloc(size, 0);
|
|
|
|
if(unlikely(pfw == 0))
|
|
return -ENOMEM;
|
|
|
|
firmware->size = size;
|
|
firmware->data = pfw;
|
|
|
|
for (rec = (const struct ihex_binrec *)builtin->data;
|
|
rec; rec = ihex_next_binrec(rec))
|
|
{
|
|
unsigned int src_size;
|
|
|
|
src_size = be16_to_cpu(rec->len);
|
|
memcpy(pfw, rec->data, src_size);
|
|
pfw+= src_size;
|
|
};
|
|
#else
|
|
dbgprintf("firmware size %d\n", builtin->size);
|
|
|
|
firmware->size = builtin->size;
|
|
firmware->data = builtin->data;
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
kfree(firmware);
|
|
*firmware_p = NULL;
|
|
|
|
return -EINVAL;
|
|
};
|
|
|
|
void
|
|
release_firmware(const struct firmware *fw)
|
|
{
|
|
if (fw) {
|
|
kfree((void*)fw);
|
|
}
|
|
}
|
|
|
|
struct platform_device*
|
|
platform_device_register_simple(const char* c, int id, void *r, unsigned int i)
|
|
{
|
|
static struct platform_device pd;
|
|
|
|
return &pd;
|
|
};
|
|
|
|
|