static int _process_sigma_firmware(struct device *dev, struct sigma_firmware *ssfw, const char *name) { int ret; struct sigma_firmware_header *ssfw_head; const struct firmware *fw; u32 crc; pr_debug("%s: loading firmware %s\n", __func__, name); /* first load the blob */ ret = maybe_reject_firmware(&fw, name, dev); if (ret) { pr_debug("%s: maybe_reject_firmware() failed with %i\n", __func__, ret); return ret; } ssfw->fw = fw; /* then verify the header */ ret = -EINVAL; /* * Reject too small or unreasonable large files. The upper limit has been * chosen a bit arbitrarily, but it should be enough for all practical * purposes and having the limit makes it easier to avoid integer * overflows later in the loading process. */ if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) { dev_err(dev, "Failed to load firmware: Invalid size\n"); goto done; } ssfw_head = (void *)fw->data; if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) { dev_err(dev, "Failed to load firmware: Invalid magic\n"); goto done; } crc = crc32(0, fw->data + sizeof(*ssfw_head), fw->size - sizeof(*ssfw_head)); pr_debug("%s: crc=%x\n", __func__, crc); if (crc != le32_to_cpu(ssfw_head->crc)) { dev_err(dev, "Failed to load firmware: Wrong crc checksum: expected %x got %x\n", le32_to_cpu(ssfw_head->crc), crc); goto done; } ssfw->pos = sizeof(*ssfw_head); /* finally process all of the actions */ ret = process_sigma_actions(ssfw); done: release_firmware(fw); pr_debug("%s: loaded %s\n", __func__, name); return ret; }
int process_sigma_firmware(struct i2c_client *client, const char *name) { int ret; struct sigma_firmware_header *ssfw_head; struct sigma_firmware ssfw; const struct firmware *fw; u32 crc; pr_debug("%s: loading firmware %s\n", __func__, name); /* first load the blob */ ret = request_firmware(&fw, name, &client->dev); if (ret) { pr_debug("%s: request_firmware() failed with %i\n", __func__, ret); return ret; } ssfw.fw = fw; /* then verify the header */ ret = -EINVAL; if (fw->size < sizeof(*ssfw_head)) goto done; ssfw_head = (void *)fw->data; if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) goto done; crc = crc32(0, fw->data, fw->size); pr_debug("%s: crc=%x\n", __func__, crc); if (crc != ssfw_head->crc) goto done; ssfw.pos = sizeof(*ssfw_head); /* finally process all of the actions */ ret = process_sigma_actions(client, &ssfw); done: release_firmware(fw); pr_debug("%s: loaded %s\n", __func__, name); return ret; }