Add -Wall and -Werror compile options, and get them working

Allow unused functions/variables, as they could be debug only
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 552a22c..2e0d39f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,6 +6,12 @@
     set(CMAKE_BUILD_TYPE Release)
 endif()
 
+include(CheckCXXCompilerFlag)
+check_cxx_compiler_flag("-Wall;-Wno-unused-function;-Wno-unused-variable;-Wno-unused-but-set-variable;-Werror" flag_supported)
+if(flag_supported)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable -Werror")
+endif()
+
 if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
     set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
     message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
diff --git a/bintool/bintool.cpp b/bintool/bintool.cpp
index 43a23a0..c836d06 100644
--- a/bintool/bintool.cpp
+++ b/bintool/bintool.cpp
@@ -1078,7 +1078,7 @@
 
     // Salt IV
     assert(iv_data.size() == iv_salt.size());
-    for (int i=0; i < iv_data.size(); i++) {
+    for (size_t i=0; i < iv_data.size(); i++) {
         iv_data[i] ^= iv_salt[i];
     }
 
@@ -1182,7 +1182,7 @@
 
     // Salt IV
     assert(iv_data.size() == iv_salt.size());
-    for (int i=0; i < iv_data.size(); i++) {
+    for (size_t i=0; i < iv_data.size(); i++) {
         iv_data[i] ^= iv_salt[i];
     }
 
diff --git a/cli.h b/cli.h
index bfaae40..f2c646c 100644
--- a/cli.h
+++ b/cli.h
@@ -7,6 +7,11 @@
 #ifndef _CLI_H
 #define _CLI_H
 
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsign-compare"
+#endif
+
 #include <algorithm>
 #include <exception>
 #include <functional>
@@ -1039,4 +1044,8 @@
     }
 }
 
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
 #endif
diff --git a/elf/elf_file.cpp b/elf/elf_file.cpp
index d4f8d53..ebfb488 100644
--- a/elf/elf_file.cpp
+++ b/elf/elf_file.cpp
@@ -256,11 +256,11 @@
 // but this is not necessary for signing/hashing
 void elf_file::remove_ph_holes(void) {
     auto sorted_ph_entries = sorted_segments();
-    for (int i=0; i+1 < ph_entries.size(); i++) {
+    for (size_t i=0; i+1 < ph_entries.size(); i++) {
         auto ph0 = &(ph_entries[i]);
         const elf32_ph_entry* ph1 = nullptr;
         // ph1 is the next segment by address
-        for (int j=0; j+1 < sorted_ph_entries.size(); j++) {
+        for (size_t j=0; j+1 < sorted_ph_entries.size(); j++) {
             auto tst_ph0 = sorted_ph_entries[j];
             if (tst_ph0->offset == ph0->offset) {
                 ph1 = sorted_ph_entries[j+1];
@@ -284,7 +284,7 @@
             if (ph0->offset + ph0->filez + gap > ph1file.offset) {
                 fail(ERROR_INCOMPATIBLE, "Segment %d: Cannot plug gap without space in file - gap %d", i, gap);
             }
-            if (verbose) printf("Segment %d: Moving end from 0x%08x to 0x%08x to plug gap\n", i, ph0->paddr + ph0->filez, ph1->paddr);
+            if (verbose) printf("Segment %d: Moving end from 0x%08x to 0x%08x to plug gap\n", (int)i, ph0->paddr + ph0->filez, ph1->paddr);
             ph0->filez = ph1->paddr - ph0->paddr;
             ph0->memsz = ph0->filez;
         }
@@ -296,7 +296,7 @@
 // signing/hashing/encrypting data that may not be written, as many tools write in sections not segments
 void elf_file::remove_sh_holes(void) {
     bool found_hole = false;
-    for (int i=0; i+1 < sh_entries.size(); i++) {
+    for (size_t i=0; i+1 < sh_entries.size(); i++) {
         auto sh0 = &(sh_entries[i]);
         elf32_sh_entry sh1 = sh_entries[i+1];
         if (
@@ -310,7 +310,7 @@
             if (gap > sh1.addralign) {
                 fail(ERROR_INCOMPATIBLE, "Section %d: Cannot plug gap greater than alignment - gap %d, alignment %d", i, gap, sh1.addralign);
             }
-            if (verbose) printf("Section %d: Moving end from 0x%08x to 0x%08x to plug gap\n", i, sh0->addr + sh0->size, sh1.addr);
+            if (verbose) printf("Section %d: Moving end from 0x%08x to 0x%08x to plug gap\n", (int)i, sh0->addr + sh0->size, sh1.addr);
             sh0->size = sh1.addr - sh0->addr;
             found_hole = true;
         } else if (
@@ -321,7 +321,7 @@
         ) {
             const elf32_ph_entry *seg = segment_from_section(*sh0);
             uint32_t gap = seg->offset + seg->filez - sh0->offset - sh0->size;
-            if (verbose) printf("Section %d: Moving end from 0x%08x to 0x%08x to plug gap at end of segment\n", i, sh0->addr + sh0->size, seg->offset + seg->filez);
+            if (verbose) printf("Section %d: Moving end from 0x%08x to 0x%08x to plug gap at end of segment\n", (int)i, sh0->addr + sh0->size, seg->offset + seg->filez);
             sh0->size = seg->offset + seg->filez - sh0->offset;
             found_hole = true;
         }
@@ -330,7 +330,7 @@
 }
 
 void elf_file::remove_empty_ph_entries(void) {
-    for (int i = 0; i < ph_entries.size(); i++) {
+    for (size_t i = 0; i < ph_entries.size(); i++) {
         if (ph_entries[i].filez == 0) {
             ph_entries.erase(ph_entries.begin() + i);
             eh.ph_num--; i--;
diff --git a/main.cpp b/main.cpp
index 534b794..db447ef 100644
--- a/main.cpp
+++ b/main.cpp
@@ -253,7 +253,7 @@
 struct cancelled_exception : std::exception { };
 
 struct not_mapped_exception : std::exception {
-    explicit not_mapped_exception(uint32_t addr) : addr(addr), std::exception() {}
+    explicit not_mapped_exception(uint32_t addr) : std::exception(), addr(addr) {}
     const char *what() const noexcept override {
         return "Hmm uncaught not mapped";
     }
@@ -1223,8 +1223,8 @@
             ).min(0) % "Add Minor Version" +
             (
                 option("--rollback") &
-                    integer("rollback").set(settings.seal.rollback_version) +
-                    hex("rows").add_to(settings.seal.rollback_rows).min(0).repeatable()
+                    (integer("rollback").set(settings.seal.rollback_version) +
+                    hex("rows").add_to(settings.seal.rollback_rows).min(0).repeatable())
             ).min(0) % "Add Rollback Version"
         );
     }
@@ -2529,7 +2529,7 @@
                 }
                 // Check if we need to erase (ie check for bits that need to be set)
                 bool do_erase = false;
-                for (int i = 0; i < write_data.size(); i++) {
+                for (size_t i = 0; i < write_data.size(); i++) {
                     if (buffer[i] & ~write_data[i]) {
                         do_erase = true;
                         break;
@@ -5132,7 +5132,7 @@
         if (!partitions) {
             fail(ERROR_NOT_POSSIBLE, "There is no partition table on the device");
         }
-        if (settings.load.partition >= partitions->size()) {
+        if (settings.load.partition >= (int)partitions->size()) {
             fail(ERROR_NOT_POSSIBLE, "There are only %d partitions on the device", partitions->size());
         }
         size_t tmp;
@@ -5425,7 +5425,7 @@
         if (!partitions) {
             fail(ERROR_NOT_POSSIBLE, "There is no partition table on the device");
         }
-        if (settings.load.partition >= partitions->size()) {
+        if (settings.load.partition >= (int)partitions->size()) {
             fail(ERROR_NOT_POSSIBLE, "There are only %d partitions on the device", partitions->size());
         }
         uint32_t start = (*partitions)[settings.load.partition].start;
@@ -5800,7 +5800,7 @@
     }
 
     // Key is stored as a 4-way share of each word, ie X[0] = A[0] ^ B[0] ^ C[0] ^ D[0], stored as A[0], B[0], C[0], D[0]
-    for (int i=0; i < count_of(aes_key.words); i++) {
+    for (size_t i=0; i < count_of(aes_key.words); i++) {
         aes_key.words[i] = aes_key_share.words[i*4]
                          ^ aes_key_share.words[i*4 + 1]
                          ^ aes_key_share.words[i*4 + 2]
@@ -5859,7 +5859,7 @@
 
             // Salt IV
             assert(iv_data.size() == iv_salt.size());
-            for (int i=0; i < iv_data.size(); i++) {
+            for (size_t i=0; i < iv_data.size(); i++) {
                 iv_data[i] ^= iv_salt[i];
             }
             auto tmp = std::make_shared<std::stringstream>();
@@ -6024,30 +6024,30 @@
         memcpy(page2_data.data(), iv_salt.data(), iv_salt.size());
 
         // The bits in rows 32-63 must be the inverse of the bits in rows 0-31
-        for (int i = 0; i < page0_data.size(); i += 2) {
+        for (size_t i = 0; i < page0_data.size(); i += 2) {
             page0_inverse[i*2] = ~page0_data[i];
             page0_inverse[i*2+1] = ~page0_data[i+1];
             page0_inverse[i*2+2] = ~otp_calculate_ecc(*(uint16_t*)&page0_data[i]) >> 16;
         }
-        for (int i = 0; i < page1_data.size(); i += 2) {
+        for (size_t i = 0; i < page1_data.size(); i += 2) {
             page1_inverse[i*2] = ~page1_data[i];
             page1_inverse[i*2+1] = ~page1_data[i+1];
             page1_inverse[i*2+2] = ~otp_calculate_ecc(*(uint16_t*)&page1_data[i]) >> 16;
         }
-        for (int i = 0; i < page2_data.size(); i += 2) {
+        for (size_t i = 0; i < page2_data.size(); i += 2) {
             page2_inverse[i*2] = ~page2_data[i];
             page2_inverse[i*2+1] = ~page2_data[i+1];
             page2_inverse[i*2+2] = ~otp_calculate_ecc(*(uint16_t*)&page2_data[i]) >> 16;
         }
 
         // Add otp AES key pages
-        for (int i = 0; i < page0_data.size(); i++) {
+        for (size_t i = 0; i < page0_data.size(); i++) {
             std::stringstream ss;
             ss << settings.encrypt.otp_key_page << ":0";
             otp_json[ss.str()]["ecc"] = true;
             otp_json[ss.str()]["value"][i] = page0_data[i];
         }
-        for (int i = 0; i < page1_data.size(); i++) {
+        for (size_t i = 0; i < page1_data.size(); i++) {
             std::stringstream ss;
             ss << settings.encrypt.otp_key_page + 1 << ":0";
             otp_json[ss.str()]["ecc"] = true;
@@ -6055,7 +6055,7 @@
         }
 
         // Add otp IV salt page
-        for (int i = 0; i < page2_data.size(); i++) {
+        for (size_t i = 0; i < page2_data.size(); i++) {
             std::stringstream ss;
             ss << settings.encrypt.otp_key_page + 2 << ":0";
             otp_json[ss.str()]["ecc"] = true;
@@ -6063,19 +6063,19 @@
         }
 
         // Add inverse pages
-        for (int i = 0; i < page0_inverse.size(); i++) {
+        for (size_t i = 0; i < page0_inverse.size(); i++) {
             std::stringstream ss;
             ss << settings.encrypt.otp_key_page << ":32";
             otp_json[ss.str()]["ecc"] = false;
             otp_json[ss.str()]["value"][i] = page0_inverse[i];
         }
-        for (int i = 0; i < page1_inverse.size(); i++) {
+        for (size_t i = 0; i < page1_inverse.size(); i++) {
             std::stringstream ss;
             ss << settings.encrypt.otp_key_page + 1 << ":32";
             otp_json[ss.str()]["ecc"] = false;
             otp_json[ss.str()]["value"][i] = page1_inverse[i];
         }
-        for (int i = 0; i < page2_inverse.size(); i++) {
+        for (size_t i = 0; i < page2_inverse.size(); i++) {
             std::stringstream ss;
             ss << settings.encrypt.otp_key_page + 2 << ":32";
             otp_json[ss.str()]["ecc"] = false;
@@ -6083,7 +6083,7 @@
         }
     #else
         // Add otp AES key page
-        for (int i = 0; i < 128; ++i) {
+        for (size_t i = 0; i < 128; ++i) {
             std::stringstream ss;
             ss << settings.encrypt.otp_key_page << ":0";
             otp_json[ss.str()]["ecc"] = true;
@@ -6091,7 +6091,7 @@
         }
 
         // Add otp IV salt page
-        for (int i = 0; i < iv_salt.size(); ++i) {
+        for (size_t i = 0; i < iv_salt.size(); ++i) {
             std::stringstream ss;
             ss << settings.encrypt.otp_key_page + 1 << ":0";
             otp_json[ss.str()]["ecc"] = true;
@@ -6428,7 +6428,7 @@
             if (!partitions) {
                 fail(ERROR_NOT_POSSIBLE, "There is no partition table on the device");
             }
-            if (settings.bdev.partition_number >= partitions->size()) {
+            if (settings.bdev.partition_number >= (int)partitions->size()) {
                 fail(ERROR_NOT_POSSIBLE, "There are only %d partitions on the device", partitions->size());
             }
             chosen_partition = (*partitions)[settings.bdev.partition_number];
@@ -7064,7 +7064,7 @@
                     err = lfs_file_read(lfs, &file, data_buf.data(), data_buf.size());
                     if (err < 0) {
                         fail(ERROR_READ_FAILED, "LittleFS Read Error: %s", lfs_err_str(err).c_str());
-                    } else if (err != data_buf.size()) {
+                    } else if (err != (int)data_buf.size()) {
                         fail(ERROR_READ_FAILED, "LittleFS Read too short - got %d bytes expected %d bytes", err, data_buf.size());
                     }
                     err = lfs_file_close(lfs, &file);
@@ -7079,7 +7079,7 @@
                     err = lfs_file_write(lfs, &file, data_buf.data(), data_buf.size());
                     if (err < 0) {
                         fail(ERROR_WRITE_FAILED, "LittleFS Write Error: %s", lfs_err_str(err).c_str());
-                    } else if (err != data_buf.size()) {
+                    } else if (err != (int)data_buf.size()) {
                         fail(ERROR_WRITE_FAILED, "LittleFS Write too short - wrote %d bytes expected %d bytes", err, data_buf.size());
                     }
                     err = lfs_file_close(lfs, &file);
@@ -7214,7 +7214,7 @@
                 err = lfs_file_read(lfs, &file, data_buf.data(), data_buf.size());
                 if (err < 0) {
                     fail(ERROR_READ_FAILED, "LittleFS Read Error: %s", lfs_err_str(err).c_str());
-                } else if (err != data_buf.size()) {
+                } else if (err != (int)data_buf.size()) {
                     fail(ERROR_READ_FAILED, "LittleFS Read too short - got %d bytes expected %d bytes", err, data_buf.size());
                 }
                 err = lfs_file_close(lfs, &file);
@@ -7689,11 +7689,11 @@
 
     if (partitions) {
         printf("partitions:\n");
-        for (int i = 0; i < (*partitions).size(); i++) {
+        for (size_t i = 0; i < (*partitions).size(); i++) {
             auto partition = (*partitions)[i];
             uint32_t flags_and_permissions = partition.flags_and_permissions;
             uint64_t id = partition.id;
-            printf("  %d", i);
+            printf("  %d", (int)i);
             if ((flags_and_permissions & PICOBIN_PARTITION_FLAGS_LINK_TYPE_BITS) ==
                 PICOBIN_PARTITION_FLAGS_LINK_TYPE_AS_BITS(A_PARTITION)) {
                 printf("(B w/ %d) ", (flags_and_permissions & PICOBIN_PARTITION_FLAGS_LINK_VALUE_BITS)
@@ -8144,7 +8144,7 @@
                 continue;
             }
 
-            if (settings.uf2.partition < 0 || settings.uf2.partition >= partition_table->partitions.size()) {
+            if (settings.uf2.partition < 0 || settings.uf2.partition >= (int)partition_table->partitions.size()) {
                 fail(ERROR_ARGS, "Partition table only contains partitions 0 -> %d\n", partition_table->partitions.size() - 1);
             }
 
diff --git a/model/model.h b/model/model.h
index 3b51ec2..4c1b111 100644
--- a/model/model.h
+++ b/model/model.h
@@ -128,11 +128,11 @@
     virtual uint32_t unreadable_rom_end() { return 0xffffffff; }
     virtual const unsigned char *unreadable_rom_data() { return nullptr; }
 private:
+    chip_t _chip;
     std::string _name;
     chip_revision_t _chip_revision;
     uint32_t _rom_end;
     std::set<picoboot_cmd_id> _picoboot_cmds;
-    chip_t _chip;
     uint32_t _family_id;
 };