vpnor: Enforce a read-only FFS ToC regardless of flags

The virtual PNOR implementation never properly honoured writes to the
FFS ToC, as the ToC's binary representation is generated from the CSV
file shipped in the PNOR squashfs image.

What *did* happen was that opening a write window to the ToC region
succeeded and writes could be flushed, but the flushed writes were never
read, and ToC representation internal to mboxd was never updated to
match the written state. Thus the written values "persisted" until the
ToC's window fell out of the cache (with 64MiB reserved regions,
probably on a host reboot).

Short circuit the insanity of handling FFS more than we have to by
forcefully marking the ToC as read-only, regardless of the flag
configuration shipped in the CSV representation. This prevents the host
from successfully opening a write window and thus the host can have no
expectation of write persistence.

Change-Id: Ib2788c56b245da506cb7d607c0758b17785766cf
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/vpnor/pnor_partition_table.cpp b/vpnor/pnor_partition_table.cpp
index aa0b2fb..7e99ae2 100644
--- a/vpnor/pnor_partition_table.cpp
+++ b/vpnor/pnor_partition_table.cpp
@@ -296,6 +296,15 @@
         }
     }
 
+    // Awful hack: Detect the TOC partition and force it read-only.
+    //
+    // Note that as it stands in the caller code we populate the critical
+    // elements before the user data. These tests make doing so a requirement.
+    if (part.data.id == 0 && !part.data.base && part.data.size)
+    {
+        perms |= PARTITION_READONLY;
+    }
+
     part.data.user.data[0] = state;
     part.data.user.data[1] = perms;
     part.data.user.data[1] |= version;
@@ -374,6 +383,9 @@
 
     // Use the shift to convert "80" to 0x80000000
     unsigned long version = std::stoul(match[VERSION_MATCH].str(), nullptr, 16);
+    // Note that we must have written the partition ID and sizes prior to
+    // populating the userdata. See the note about awful hacks in
+    // writeUserdata()
     writeUserdata(part, version << versionShift, match.suffix().str());
     part.checksum = details::checksum(part.data);
 }
diff --git a/vpnor/test/Makefile.am.include b/vpnor/test/Makefile.am.include
index 3b366b6..f3f4fc2 100644
--- a/vpnor/test/Makefile.am.include
+++ b/vpnor/test/Makefile.am.include
@@ -267,6 +267,5 @@
 	%reldir%/force_readonly_toc
 
 XFAIL_TESTS += \
-	%reldir%/write_toc \
-	%reldir%/force_readonly_toc
+	%reldir%/write_toc
 endif