+ if (version >= 3) {
+ printf("Blobs offset:\t%d\n", le32_to_cpu(hdr.blobs_offset));
+ printf("Blobs length:\t%d\n", le32_to_cpu(hdr.blobs_len));
+ }
+
+ if (version >= 3 && hdr.blobs_offset) {
+ size_t offset;
+
+ fseek(lxl, le32_to_cpu(hdr.blobs_offset), SEEK_SET);
+ for (offset = 0; offset < le32_to_cpu(hdr.blobs_len); ) {
+ struct lxl_blob blob;
+ size_t bytes;
+ size_t len;
+
+ bytes = fread(&blob, 1, sizeof(blob), lxl);
+ if (bytes != sizeof(blob)) {
+ fprintf(stderr, "Failed to read blob section\n");
+ err = -ENXIO;
+ goto err_close;
+ }
+
+ len = le32_to_cpu(blob.len);
+
+ printf("\n");
+ printf("Blob\n");
+ printf("Magic:\t\t%s\n", blob.magic);
+ printf("Type:\t\t0x%04x\n", le16_to_cpu(blob.type));
+ printf("Length:\t\t%zu\n", len);
+
+ offset += sizeof(blob) + len;
+ fseek(lxl, len, SEEK_CUR);
+ }
+
+ if (offset != le32_to_cpu(hdr.blobs_len)) {
+ printf("\n");
+ fprintf(stderr, "Blobs size (0x%zx) doesn't match declared length (0x%x)\n", offset, le32_to_cpu(hdr.blobs_len));
+ }
+ }
+
+err_close:
+ fclose(lxl);
+out:
+ return err;
+}
+
+/**************************************************
+ * Blobs
+ **************************************************/
+
+/**
+ * lxlfw_blob_save - save blob data to external file
+ *
+ * @lxl: Luxul firmware FILE with position seeked to blob data
+ * @len: blob data length
+ * @path: external file pathname to write
+ */
+#if 0
+static int lxlfw_blob_save(FILE *lxl, size_t len, const char *path) {
+ char buf[256];
+ size_t bytes;
+ FILE *out;
+ int err = 0;
+
+ out = fopen(path, "w+");
+ if (!out) {
+ fprintf(stderr, "Could not open \"%s\" file\n", path);
+ err = -EIO;
+ goto err_out;
+ }
+
+ while (len && (bytes = fread(buf, 1, min(len, sizeof(buf)), lxl)) > 0) {
+ if (fwrite(buf, 1, bytes, out) != bytes) {
+ fprintf(stderr, "Could not copy %zu bytes from input file\n", bytes);
+ err = -EIO;
+ goto err_close_out;
+ }
+ len -= bytes;
+ }
+
+ if (len) {
+ fprintf(stderr, "Could not copy all signature\n");
+ err = -EIO;
+ goto err_close_out;
+ }
+
+err_close_out:
+ fclose(out);
+err_out:
+ return err;
+}
+#endif
+
+static int lxlfw_blobs(int argc, char **argv) {
+ struct lxl_hdr hdr;
+ uint32_t version;
+ size_t offset;
+ size_t bytes;
+ int err = 0;
+ FILE *lxl;
+ int c;
+
+ if (argc < 3) {
+ fprintf(stderr, "Missing <file> argument\n");
+ err = -EINVAL;
+ goto out;
+ }
+
+ optind = 3;
+ while ((c = getopt(argc, argv, "")) != -1) {
+ }
+
+ if (1) {
+ fprintf(stderr, "Missing info on blobs to extract\n");
+ err = -EINVAL;
+ goto out;
+ }
+
+ lxl = lxlfw_open(argv[2], &hdr);
+ if (!lxl) {
+ fprintf(stderr, "Failed to open \"%s\" Luxul firmware\n", argv[2]);
+ err = -ENOENT;
+ goto out;
+ }
+
+ version = le32_to_cpu(hdr.version);
+
+ if (version < 3 || !hdr.blobs_offset) {
+ fprintf(stderr, "File <file> doesn't contain any blobs\n");
+ err = -ENOENT;
+ goto err_close;
+ }
+
+ fseek(lxl, le32_to_cpu(hdr.blobs_offset), SEEK_SET);
+ for (offset = 0; offset < le32_to_cpu(hdr.blobs_len); ) {
+ struct lxl_blob blob;
+ size_t len;
+
+ bytes = fread(&blob, 1, sizeof(blob), lxl);
+ if (bytes != sizeof(blob)) {
+ fprintf(stderr, "Failed to read blob section\n");
+ err = -ENXIO;
+ goto err_close;
+ }
+ offset += bytes;
+
+ if (memcmp(blob.magic, "D#", 2)) {
+ fprintf(stderr, "Failed to parse blob section\n");
+ err = -ENXIO;
+ goto err_close;
+ }
+
+ len = le32_to_cpu(blob.len);
+
+ if (0) {
+ /* TODO */
+ } else {
+ fseek(lxl, len, SEEK_CUR);
+ }
+ if (err) {
+ fprintf(stderr, "Failed to save blob section\n");
+ goto err_close;
+ }
+ offset += len;
+ }