Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 171212
b: refs/heads/master
c: 10607c8
h: refs/heads/master
v: v3
  • Loading branch information
Inaky Perez-Gonzalez committed Oct 19, 2009
1 parent dc562d8 commit 16f0ccf
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bfc44187bbaeabf597be6566a24e8fa7d689b984
refs/heads/master: 10607c86e163e3da8bdf58a934da7dd3a68dcb7c
111 changes: 92 additions & 19 deletions trunk/drivers/net/wimax/i2400m/fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -665,8 +665,8 @@ static int i2400m_download_chunk(struct i2400m *i2400m, const void *chunk,
* Download a BCF file's sections to the device
*
* @i2400m: device descriptor
* @bcf: pointer to firmware data (followed by the payloads). Assumed
* verified and consistent.
* @bcf: pointer to firmware data (first header followed by the
* payloads). Assumed verified and consistent.
* @bcf_len: length (in bytes) of the @bcf buffer.
*
* Returns: < 0 errno code on error or the offset to the jump instruction.
Expand Down Expand Up @@ -756,11 +756,17 @@ unsigned i2400m_boot_is_signed(struct i2400m *i2400m)
/*
* Do the final steps of uploading firmware
*
* @bcf_hdr: BCF header we are actually using
* @bcf: pointer to the firmware image (which matches the first header
* that is followed by the actual payloads).
* @offset: [byte] offset into @bcf for the command we need to send.
*
* Depending on the boot mode (signed vs non-signed), different
* actions need to be taken.
*/
static
int i2400m_dnload_finalize(struct i2400m *i2400m,
const struct i2400m_bcf_hdr *bcf_hdr,
const struct i2400m_bcf_hdr *bcf, size_t offset)
{
int ret = 0;
Expand Down Expand Up @@ -792,12 +798,13 @@ int i2400m_dnload_finalize(struct i2400m *i2400m,
cmd_buf = i2400m->bm_cmd_buf;
memcpy(&cmd_buf->cmd, cmd, sizeof(*cmd));
signature_block_offset =
sizeof(*bcf)
+ le32_to_cpu(bcf->key_size) * sizeof(u32)
+ le32_to_cpu(bcf->exponent_size) * sizeof(u32);
sizeof(*bcf_hdr)
+ le32_to_cpu(bcf_hdr->key_size) * sizeof(u32)
+ le32_to_cpu(bcf_hdr->exponent_size) * sizeof(u32);
signature_block_size =
le32_to_cpu(bcf->modulus_size) * sizeof(u32);
memcpy(cmd_buf->cmd_pl, (void *) bcf + signature_block_offset,
le32_to_cpu(bcf_hdr->modulus_size) * sizeof(u32);
memcpy(cmd_buf->cmd_pl,
(void *) bcf_hdr + signature_block_offset,
signature_block_size);
ret = i2400m_bm_cmd(i2400m, &cmd_buf->cmd,
sizeof(cmd_buf->cmd) + signature_block_size,
Expand Down Expand Up @@ -1122,14 +1129,15 @@ int i2400m_dnload_init_signed(struct i2400m *i2400m,
* (signed or non-signed).
*/
static
int i2400m_dnload_init(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf)
int i2400m_dnload_init(struct i2400m *i2400m,
const struct i2400m_bcf_hdr *bcf_hdr)
{
int result;
struct device *dev = i2400m_dev(i2400m);

if (i2400m_boot_is_signed(i2400m)) {
d_printf(1, dev, "signed boot\n");
result = i2400m_dnload_init_signed(i2400m, bcf);
result = i2400m_dnload_init_signed(i2400m, bcf_hdr);
if (result == -ERESTARTSYS)
return result;
if (result < 0)
Expand Down Expand Up @@ -1182,38 +1190,38 @@ int i2400m_fw_hdr_check(struct i2400m *i2400m,
date = le32_to_cpu(bcf_hdr->date);
size = sizeof(u32) * le32_to_cpu(bcf_hdr->size);

d_printf(1, dev, "firmware %s #%d@%08x: BCF header "
"type:vendor:id 0x%x:%x:%x v%u.%u (%zu/%zu B) built %08x\n",
d_printf(1, dev, "firmware %s #%zd@%08zx: BCF header "
"type:vendor:id 0x%x:%x:%x v%u.%u (%u/%u B) built %08x\n",
i2400m->fw_name, index, offset,
module_type, module_vendor, module_id,
major_version, minor_version, header_len, size, date);

/* Hard errors */
if (major_version != 1) {
dev_err(dev, "firmware %s #%d@%08x: major header version "
dev_err(dev, "firmware %s #%zd@%08zx: major header version "
"v%u.%u not supported\n",
i2400m->fw_name, index, offset,
major_version, minor_version);
return -EBADF;
}

if (module_type != 6) { /* built for the right hardware? */
dev_err(dev, "firmware %s #%d@%08x: unexpected module "
dev_err(dev, "firmware %s #%zd@%08zx: unexpected module "
"type 0x%x; aborting\n",
i2400m->fw_name, index, offset,
module_type);
return -EBADF;
}

if (module_vendor != 0x8086) {
dev_err(dev, "firmware %s #%d@%08x: unexpected module "
dev_err(dev, "firmware %s #%zd@%08zx: unexpected module "
"vendor 0x%x; aborting\n",
i2400m->fw_name, index, offset, module_vendor);
return -EBADF;
}

if (date < 0x20080300)
dev_warn(dev, "firmware %s #%d@%08x: build date %08x "
dev_warn(dev, "firmware %s #%zd@%08zx: build date %08x "
"too old; unsupported\n",
i2400m->fw_name, index, offset, date);
return 0;
Expand All @@ -1239,7 +1247,7 @@ int i2400m_fw_check(struct i2400m *i2400m, const void *bcf, size_t bcf_size)
size_t headers = 0;
const struct i2400m_bcf_hdr *bcf_hdr;
const void *itr, *next, *top;
unsigned slots = 0, used_slots = 0;
size_t slots = 0, used_slots = 0;

for (itr = bcf, top = itr + bcf_size;
itr < top;
Expand All @@ -1249,7 +1257,7 @@ int i2400m_fw_check(struct i2400m *i2400m, const void *bcf, size_t bcf_size)
leftover = top - itr;
offset = itr - (const void *) bcf;
if (leftover <= sizeof(*bcf_hdr)) {
dev_err(dev, "firmware %s: %zu B left at @%x, "
dev_err(dev, "firmware %s: %zu B left at @%zx, "
"not enough for BCF header\n",
i2400m->fw_name, leftover, offset);
break;
Expand Down Expand Up @@ -1292,6 +1300,60 @@ int i2400m_fw_check(struct i2400m *i2400m, const void *bcf, size_t bcf_size)
}


/*
* Match a barker to a BCF header module ID
*
* The device sends a barker which tells the firmware loader which
* header in the BCF file has to be used. This does the matching.
*/
static
unsigned i2400m_bcf_hdr_match(struct i2400m *i2400m,
const struct i2400m_bcf_hdr *bcf_hdr)
{
u32 barker = le32_to_cpu(i2400m->barker->data[0])
& 0x7fffffff;
u32 module_id = le32_to_cpu(bcf_hdr->module_id)
& 0x7fffffff; /* high bit used for something else */

/* special case for 5x50 */
if (barker == I2400M_SBOOT_BARKER && module_id == 0)
return 1;
if (module_id == barker)
return 1;
return 0;
}

static
const struct i2400m_bcf_hdr *i2400m_bcf_hdr_find(struct i2400m *i2400m)
{
struct device *dev = i2400m_dev(i2400m);
const struct i2400m_bcf_hdr **bcf_itr, *bcf_hdr;
unsigned i = 0;
u32 barker = le32_to_cpu(i2400m->barker->data[0]);

d_printf(2, dev, "finding BCF header for barker %08x\n", barker);
if (barker == I2400M_NBOOT_BARKER) {
bcf_hdr = i2400m->fw_hdrs[0];
d_printf(1, dev, "using BCF header #%u/%08x for non-signed "
"barker\n", 0, le32_to_cpu(bcf_hdr->module_id));
return bcf_hdr;
}
for (bcf_itr = i2400m->fw_hdrs; *bcf_itr != NULL; bcf_itr++, i++) {
bcf_hdr = *bcf_itr;
if (i2400m_bcf_hdr_match(i2400m, bcf_hdr)) {
d_printf(1, dev, "hit on BCF hdr #%u/%08x\n",
i, le32_to_cpu(bcf_hdr->module_id));
return bcf_hdr;
} else
d_printf(1, dev, "miss on BCF hdr #%u/%08x\n",
i, le32_to_cpu(bcf_hdr->module_id));
}
dev_err(dev, "cannot find a matching BCF header for barker %08x\n",
barker);
return NULL;
}


/*
* Download the firmware to the device
*
Expand All @@ -1313,6 +1375,7 @@ int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf,
int ret = 0;
struct device *dev = i2400m_dev(i2400m);
int count = i2400m->bus_bm_retries;
const struct i2400m_bcf_hdr *bcf_hdr;

d_fnstart(5, dev, "(i2400m %p bcf %p size %zu)\n",
i2400m, bcf, bcf_size);
Expand All @@ -1337,8 +1400,17 @@ int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf,
* Initialize the download, push the bytes to the device and
* then jump to the new firmware. Note @ret is passed with the
* offset of the jump instruction to _dnload_finalize()
*
* Note we need to use the BCF header in the firmware image
* that matches the barker that the device sent when it
* rebooted, so it has to be passed along.
*/
ret = i2400m_dnload_init(i2400m, bcf); /* Init device's dnload */
ret = -EBADF;
bcf_hdr = i2400m_bcf_hdr_find(i2400m);
if (bcf_hdr == NULL)
goto error_bcf_hdr_find;

ret = i2400m_dnload_init(i2400m, bcf_hdr);
if (ret == -ERESTARTSYS)
goto error_dev_rebooted;
if (ret < 0)
Expand All @@ -1353,7 +1425,7 @@ int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf,
goto error_dnload_bcf;
}

ret = i2400m_dnload_finalize(i2400m, bcf, ret);
ret = i2400m_dnload_finalize(i2400m, bcf_hdr, bcf, ret);
if (ret == -ERESTARTSYS)
goto error_dev_rebooted;
if (ret < 0) {
Expand All @@ -1370,6 +1442,7 @@ int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf,
error_dnload_finalize:
error_dnload_bcf:
error_dnload_init:
error_bcf_hdr_find:
error_bootrom_init:
error_too_many_reboots:
d_fnend(5, dev, "(i2400m %p bcf %p size %zu) = %d\n",
Expand Down

0 comments on commit 16f0ccf

Please sign in to comment.