diff --git a/UEFIExtract/CMakeLists.txt b/UEFIExtract/CMakeLists.txt
index 2c5842f..e27c748 100644
--- a/UEFIExtract/CMakeLists.txt
+++ b/UEFIExtract/CMakeLists.txt
@@ -40,6 +40,7 @@ SET(PROJECT_SOURCES
  ../common/generated/edk2_vss2.cpp
  ../common/generated/edk2_ftw.cpp
  ../common/generated/insyde_fdc.cpp
+ ../common/generated/phoenix_flm.cpp
  ../common/generated/intel_acbp_v1.cpp
  ../common/generated/intel_acbp_v2.cpp
  ../common/generated/intel_keym_v1.cpp
diff --git a/UEFIFind/CMakeLists.txt b/UEFIFind/CMakeLists.txt
index 07d27f8..fcfeece 100644
--- a/UEFIFind/CMakeLists.txt
+++ b/UEFIFind/CMakeLists.txt
@@ -37,6 +37,7 @@ SET(PROJECT_SOURCES
  ../common/generated/edk2_vss2.cpp
  ../common/generated/edk2_ftw.cpp
  ../common/generated/insyde_fdc.cpp
+ ../common/generated/phoenix_flm.cpp
  ../common/generated/intel_acbp_v1.cpp
  ../common/generated/intel_acbp_v2.cpp
  ../common/generated/intel_keym_v1.cpp
diff --git a/UEFITool/CMakeLists.txt b/UEFITool/CMakeLists.txt
index 711b073..3228960 100644
--- a/UEFITool/CMakeLists.txt
+++ b/UEFITool/CMakeLists.txt
@@ -73,6 +73,7 @@ SET(PROJECT_SOURCES
  ../common/generated/edk2_vss2.cpp
  ../common/generated/edk2_ftw.cpp
  ../common/generated/insyde_fdc.cpp
+ ../common/generated/phoenix_flm.cpp
  ../common/generated/intel_acbp_v1.cpp
  ../common/generated/intel_acbp_v2.cpp
  ../common/generated/intel_keym_v1.cpp
diff --git a/UEFITool/uefitool.pro b/UEFITool/uefitool.pro
index 411b3df..39e6d28 100644
--- a/UEFITool/uefitool.pro
+++ b/UEFITool/uefitool.pro
@@ -56,6 +56,7 @@ HEADERS += uefitool.h \
  ../common/generated/edk2_vss2.h \
  ../common/generated/edk2_ftw.h \
  ../common/generated/insyde_fdc.h \
+ ../common/generated/phoenix_flm.h \
  ../common/generated/intel_acbp_v1.h \
  ../common/generated/intel_acbp_v2.h \
  ../common/generated/intel_keym_v1.h \
@@ -128,6 +129,7 @@ SOURCES += uefitool_main.cpp \
  ../common/generated/edk2_vss2.cpp \
  ../common/generated/edk2_ftw.cpp \
  ../common/generated/insyde_fdc.cpp \
+ ../common/generated/phoenix_flm.cpp \
  ../common/generated/intel_acbp_v1.cpp \
  ../common/generated/intel_acbp_v2.cpp \
  ../common/generated/intel_keym_v1.cpp \
diff --git a/common/generated/edk2_vss.cpp b/common/generated/edk2_vss.cpp
index d21701a..9c5ecac 100644
--- a/common/generated/edk2_vss.cpp
+++ b/common/generated/edk2_vss.cpp
@@ -23,7 +23,7 @@ void edk2_vss_t::_read() {
     m_vss_size = m__io->read_u4le();
     {
         uint32_t _ = vss_size();
-        if (!( ((_ > len_vss_store_header()) && (_ < 4294967295UL)) )) {
+        if (!( ((_ > static_cast<uint32_t>(len_vss_store_header())) && (_ < 4294967295UL)) )) {
             throw kaitai::validation_expr_error<uint32_t>(vss_size(), _io(), std::string("/seq/1"));
         }
     }
@@ -149,7 +149,7 @@ void edk2_vss_t::vss_variable_t::_read() {
         m_len_total = m__io->read_u4le();
         {
             uint32_t _ = len_total();
-            if (!(_ >= ((len_intel_legacy_header() + 4) + 1))) {
+            if (!(_ >= ((static_cast<uint32_t>(len_intel_legacy_header()) + 4) + 1))) {
                 throw kaitai::validation_expr_error<uint32_t>(len_total(), _io(), std::string("/types/vss_variable/seq/5"));
             }
         }
diff --git a/common/generated/edk2_vss2.cpp b/common/generated/edk2_vss2.cpp
index 848d472..763c7f2 100644
--- a/common/generated/edk2_vss2.cpp
+++ b/common/generated/edk2_vss2.cpp
@@ -47,7 +47,7 @@ void edk2_vss2_t::_read() {
     m_vss2_size = m__io->read_u4le();
     {
         uint32_t _ = vss2_size();
-        if (!( ((_ > len_vss2_store_header()) && (_ < 4294967295UL)) )) {
+        if (!( ((_ > static_cast<uint32_t>(len_vss2_store_header())) && (_ < 4294967295UL)) )) {
             throw kaitai::validation_expr_error<uint32_t>(vss2_size(), _io(), std::string("/seq/4"));
         }
     }
diff --git a/common/generated/insyde_fdc.cpp b/common/generated/insyde_fdc.cpp
index 003f157..2312547 100644
--- a/common/generated/insyde_fdc.cpp
+++ b/common/generated/insyde_fdc.cpp
@@ -21,7 +21,7 @@ void insyde_fdc_t::_read() {
     m_fdc_size = m__io->read_u4le();
     {
         uint32_t _ = fdc_size();
-        if (!( ((_ > len_fdc_store_header()) && (_ < 4294967295UL)) )) {
+        if (!( ((_ > static_cast<uint32_t>(len_fdc_store_header())) && (_ < 4294967295UL)) )) {
             throw kaitai::validation_expr_error<uint32_t>(fdc_size(), _io(), std::string("/seq/1"));
         }
     }
diff --git a/common/generated/phoenix_flm.cpp b/common/generated/phoenix_flm.cpp
new file mode 100644
index 0000000..c1d9228
--- /dev/null
+++ b/common/generated/phoenix_flm.cpp
@@ -0,0 +1,93 @@
+// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
+
+#include "phoenix_flm.h"
+#include "../kaitai/exceptions.h"
+
+phoenix_flm_t::phoenix_flm_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, phoenix_flm_t* p__root) : kaitai::kstruct(p__io) {
+    m__parent = p__parent;
+    m__root = this; (void)p__root;
+    m_entries = nullptr;
+    m_free_space = nullptr;
+    f_len_flm_store = false;
+    f_len_flm_store_header = false;
+    f_len_flm_entry = false;
+    _read();
+}
+
+void phoenix_flm_t::_read() {
+    m_signature = m__io->read_bytes(10);
+    if (!(signature() == std::string("\x5F\x46\x4C\x41\x53\x48\x5F\x4D\x41\x50", 10))) {
+        throw kaitai::validation_not_equal_error<std::string>(std::string("\x5F\x46\x4C\x41\x53\x48\x5F\x4D\x41\x50", 10), signature(), _io(), std::string("/seq/0"));
+    }
+    m_num_entries = m__io->read_u2le();
+    {
+        uint16_t _ = num_entries();
+        if (!(_ <= 113)) {
+            throw kaitai::validation_expr_error<uint16_t>(num_entries(), _io(), std::string("/seq/1"));
+        }
+    }
+    m_reserved = m__io->read_u4le();
+    m_entries = std::unique_ptr<std::vector<std::unique_ptr<flm_entry_t>>>(new std::vector<std::unique_ptr<flm_entry_t>>());
+    const int l_entries = num_entries();
+    for (int i = 0; i < l_entries; i++) {
+        m_entries->push_back(std::move(std::unique_ptr<flm_entry_t>(new flm_entry_t(m__io, this, m__root))));
+    }
+    m_free_space = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
+    const int l_free_space = ((len_flm_store() - len_flm_store_header()) - (len_flm_entry() * num_entries()));
+    for (int i = 0; i < l_free_space; i++) {
+        m_free_space->push_back(std::move(m__io->read_u1()));
+    }
+}
+
+phoenix_flm_t::~phoenix_flm_t() {
+    _clean_up();
+}
+
+void phoenix_flm_t::_clean_up() {
+}
+
+phoenix_flm_t::flm_entry_t::flm_entry_t(kaitai::kstream* p__io, phoenix_flm_t* p__parent, phoenix_flm_t* p__root) : kaitai::kstruct(p__io) {
+    m__parent = p__parent;
+    m__root = p__root;
+    _read();
+}
+
+void phoenix_flm_t::flm_entry_t::_read() {
+    m_guid = m__io->read_bytes(16);
+    m_data_type = m__io->read_u2le();
+    m_entry_type = m__io->read_u2le();
+    m_physical_address = m__io->read_u8le();
+    m_size = m__io->read_u4le();
+    m_offset = m__io->read_u4le();
+}
+
+phoenix_flm_t::flm_entry_t::~flm_entry_t() {
+    _clean_up();
+}
+
+void phoenix_flm_t::flm_entry_t::_clean_up() {
+}
+
+int32_t phoenix_flm_t::len_flm_store() {
+    if (f_len_flm_store)
+        return m_len_flm_store;
+    m_len_flm_store = 4096;
+    f_len_flm_store = true;
+    return m_len_flm_store;
+}
+
+int8_t phoenix_flm_t::len_flm_store_header() {
+    if (f_len_flm_store_header)
+        return m_len_flm_store_header;
+    m_len_flm_store_header = 16;
+    f_len_flm_store_header = true;
+    return m_len_flm_store_header;
+}
+
+int8_t phoenix_flm_t::len_flm_entry() {
+    if (f_len_flm_entry)
+        return m_len_flm_entry;
+    m_len_flm_entry = 36;
+    f_len_flm_entry = true;
+    return m_len_flm_entry;
+}
diff --git a/common/generated/phoenix_flm.h b/common/generated/phoenix_flm.h
new file mode 100644
index 0000000..a42b9c6
--- /dev/null
+++ b/common/generated/phoenix_flm.h
@@ -0,0 +1,100 @@
+#pragma once
+
+// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
+
+#include "../kaitai/kaitaistruct.h"
+#include <stdint.h>
+#include <memory>
+#include <vector>
+
+#if KAITAI_STRUCT_VERSION < 9000L
+#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
+#endif
+
+class phoenix_flm_t : public kaitai::kstruct {
+
+public:
+    class flm_entry_t;
+
+    phoenix_flm_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, phoenix_flm_t* p__root = nullptr);
+
+private:
+    void _read();
+    void _clean_up();
+
+public:
+    ~phoenix_flm_t();
+
+    class flm_entry_t : public kaitai::kstruct {
+
+    public:
+
+        flm_entry_t(kaitai::kstream* p__io, phoenix_flm_t* p__parent = nullptr, phoenix_flm_t* p__root = nullptr);
+
+    private:
+        void _read();
+        void _clean_up();
+
+    public:
+        ~flm_entry_t();
+
+    private:
+        std::string m_guid;
+        uint16_t m_data_type;
+        uint16_t m_entry_type;
+        uint64_t m_physical_address;
+        uint32_t m_size;
+        uint32_t m_offset;
+        phoenix_flm_t* m__root;
+        phoenix_flm_t* m__parent;
+
+    public:
+        std::string guid() const { return m_guid; }
+        uint16_t data_type() const { return m_data_type; }
+        uint16_t entry_type() const { return m_entry_type; }
+        uint64_t physical_address() const { return m_physical_address; }
+        uint32_t size() const { return m_size; }
+        uint32_t offset() const { return m_offset; }
+        phoenix_flm_t* _root() const { return m__root; }
+        phoenix_flm_t* _parent() const { return m__parent; }
+    };
+
+private:
+    bool f_len_flm_store;
+    int32_t m_len_flm_store;
+
+public:
+    int32_t len_flm_store();
+
+private:
+    bool f_len_flm_store_header;
+    int8_t m_len_flm_store_header;
+
+public:
+    int8_t len_flm_store_header();
+
+private:
+    bool f_len_flm_entry;
+    int8_t m_len_flm_entry;
+
+public:
+    int8_t len_flm_entry();
+
+private:
+    std::string m_signature;
+    uint16_t m_num_entries;
+    uint32_t m_reserved;
+    std::unique_ptr<std::vector<std::unique_ptr<flm_entry_t>>> m_entries;
+    std::unique_ptr<std::vector<uint8_t>> m_free_space;
+    phoenix_flm_t* m__root;
+    kaitai::kstruct* m__parent;
+
+public:
+    std::string signature() const { return m_signature; }
+    uint16_t num_entries() const { return m_num_entries; }
+    uint32_t reserved() const { return m_reserved; }
+    std::vector<std::unique_ptr<flm_entry_t>>* entries() const { return m_entries.get(); }
+    std::vector<uint8_t>* free_space() const { return m_free_space.get(); }
+    phoenix_flm_t* _root() const { return m__root; }
+    kaitai::kstruct* _parent() const { return m__parent; }
+};
diff --git a/common/ksy/edk2_vss.ksy b/common/ksy/edk2_vss.ksy
index ed478c1..a36c5df 100644
--- a/common/ksy/edk2_vss.ksy
+++ b/common/ksy/edk2_vss.ksy
@@ -17,7 +17,7 @@ seq:
 - id: vss_size
   type: u4
   valid:
-   expr: _ > len_vss_store_header and _ < 0xFFFFFFFF
+   expr: _ > len_vss_store_header.as<u4> and _ < 0xFFFFFFFF
 - id: format
   type: u1
   valid:
@@ -87,7 +87,7 @@ types:
     type: u4
     if: signature_first == 0xAA and is_intel_legacy
     valid:
-     expr: _ >= len_intel_legacy_header + 4 + 1 # Header size + at least one UCS2 character for the name + UCS2 null terminator + at least one byte of data
+     expr: _ >= len_intel_legacy_header.as<u4> + 4 + 1 # Header size + at least one UCS2 character for the name + UCS2 null terminator + at least one byte of data
 # ^^^ Intel legacy
 # Next 2 fields can be of any value for an authenticated variable due to them being a combined value of MonothonicCounter
   - id: len_name
diff --git a/common/ksy/edk2_vss2.ksy b/common/ksy/edk2_vss2.ksy
index 07903ee..0a79273 100644
--- a/common/ksy/edk2_vss2.ksy
+++ b/common/ksy/edk2_vss2.ksy
@@ -26,7 +26,7 @@ seq:
 - id: vss2_size
   type: u4
   valid:
-   expr: _ > len_vss2_store_header and _ < 0xFFFFFFFF
+   expr: _ > len_vss2_store_header.as<u4> and _ < 0xFFFFFFFF
 - id: format
   type: u1
   valid:
diff --git a/common/ksy/insyde_fdc.ksy b/common/ksy/insyde_fdc.ksy
index 038721a..1d6ec93 100644
--- a/common/ksy/insyde_fdc.ksy
+++ b/common/ksy/insyde_fdc.ksy
@@ -17,7 +17,7 @@ seq:
 - id: fdc_size
   type: u4
   valid:
-   expr: _ > len_fdc_store_header and _ < 0xFFFFFFFF
+   expr: _ > len_fdc_store_header.as<u4> and _ < 0xFFFFFFFF
 - id: body
   size: fdc_size - len_fdc_store_header
 instances:
diff --git a/common/ksy/phoenix_flm.ksy b/common/ksy/phoenix_flm.ksy
new file mode 100644
index 0000000..d46acee
--- /dev/null
+++ b/common/ksy/phoenix_flm.ksy
@@ -0,0 +1,54 @@
+meta:
+  id: phoenix_flm
+  title: Phoenix flash map
+  application: Phoenix-based UEFI firmware
+  file-extension: flm
+  tags:
+    - firmware
+  license: CC0-1.0
+  ks-version: 0.9
+  endian: le
+  
+seq:
+- id: signature
+  contents: [0x5F, 0x46, 0x4C, 0x41, 0x53, 0x48, 0x5F, 0x4D, 0x41, 0x50] # _FLASH_MAP
+- id: num_entries
+  type: u2
+  valid: 
+   expr: _ <= 113 # Needs to fit into the last 0x1000 bytes of the NVRAM volume
+- id: reserved
+  type: u4
+- id: entries
+  type: flm_entry
+  repeat: expr
+  repeat-expr: num_entries
+- id: free_space
+  type: u1
+  repeat: expr
+  repeat-expr: len_flm_store - len_flm_store_header - len_flm_entry * num_entries
+  
+instances:
+  len_flm_store:
+   value: 0x1000
+  len_flm_store_header:
+    value: 16
+  len_flm_entry:
+    value: 36
+
+types:
+  flm_entry:
+   seq:
+   - id: guid
+     size: 16
+   - id: data_type
+     type: u2
+   - id: entry_type
+     type: u2
+   - id: physical_address
+     type: u8
+   - id: size
+     type: u4
+   - id: offset
+     type: u4
+    
+    
diff --git a/common/meson.build b/common/meson.build
index de04cb9..2e73307 100644
--- a/common/meson.build
+++ b/common/meson.build
@@ -38,6 +38,7 @@ uefitoolcommon = static_library('uefitoolcommon',
     'generated/edk2_vss2.cpp',
     'generated/edk2_ftw.cpp',
     'generated/insyde_fdc.cpp',
+    'generated/phoenix_flm.cpp',
     'generated/intel_acbp_v1.cpp',
     'generated/intel_acbp_v2.cpp',
     'generated/intel_keym_v1.cpp',
diff --git a/common/nvram.cpp b/common/nvram.cpp
index 93bf7a9..f120a10 100644
--- a/common/nvram.cpp
+++ b/common/nvram.cpp
@@ -17,6 +17,8 @@
 //
 // GUIDs mentioned in by nvram.h
 //
+extern const UByteArray ZERO_GUID // 00000000-0000-0000-0000-000000000000
+("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16);
 extern const UByteArray NVRAM_NVAR_STORE_FILE_GUID // CEF5B9A3-476D-497F-9FDC-E98143E0422C
 ("\xA3\xB9\xF5\xCE\x6D\x47\x7F\x49\x9F\xDC\xE9\x81\x43\xE0\x42\x2C", 16);
 extern const UByteArray NVRAM_NVAR_EXTERNAL_DEFAULTS_FILE_GUID // 9221315B-30BB-46B5-813E-1B1BF4712BD3
@@ -168,6 +170,7 @@ UString flashMapGuidToUString(const EFI_GUID & guid)
         || baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA6_GUID
         || baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA7_GUID)        return UString("EVSA store");
     if (baGuid == NVRAM_PHOENIX_FLASH_MAP_SELF_GUID)            return UString("Flash map");
+    if (baGuid == ZERO_GUID)                                    return UString();
     return UString("Unknown");
 }
 
diff --git a/common/nvram.h b/common/nvram.h
index 598aa47..c162435 100755
--- a/common/nvram.h
+++ b/common/nvram.h
@@ -332,7 +332,7 @@ extern const UByteArray NVRAM_PHOENIX_FLASH_MAP_SIGNATURE;
 typedef struct PHOENIX_FLASH_MAP_HEADER_ {
     UINT8  Signature[10]; // _FLASH_MAP signature
     UINT16 NumEntries;    // Number of entries in the map
-    UINT32 : 32;          // Reserved field
+    UINT32 Reserved;      // Reserved field
 } PHOENIX_FLASH_MAP_HEADER;
 
 typedef struct PHOENIX_FLASH_MAP_ENTRY_ {
@@ -343,9 +343,9 @@ typedef struct PHOENIX_FLASH_MAP_ENTRY_ {
     UINT32 Size;
     UINT32 Offset;
 } PHOENIX_FLASH_MAP_ENTRY;
-
-#define NVRAM_PHOENIX_FLASH_MAP_ENTRY_TYPE_VOLUME     0x0000
-#define NVRAM_PHOENIX_FLASH_MAP_ENTRY_TYPE_DATA_BLOCK 0x0001
+#define NVRAM_PHOENIX_FLASH_MAP_TOTAL_SIZE 0x1000
+#define NVRAM_PHOENIX_FLASH_MAP_ENTRY_DATA_TYPE_VOLUME     0x0000
+#define NVRAM_PHOENIX_FLASH_MAP_ENTRY_DATA_TYPE_DATA_BLOCK 0x0001
 
 extern UString flashMapGuidToUString(const EFI_GUID & guid);
 
@@ -416,6 +416,9 @@ typedef struct PHOENIX_CMDB_HEADER_ {
 #define NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE 0x42444D43
 #define NVRAM_PHOENIX_CMDB_SIZE 0x100;
 
+// Zero GUID
+extern const UByteArray ZERO_GUID;
+
 // Restore previous packing rules
 #pragma pack(pop)
 
diff --git a/common/nvramparser.cpp b/common/nvramparser.cpp
index cb1369b..ab48b9d 100644
--- a/common/nvramparser.cpp
+++ b/common/nvramparser.cpp
@@ -31,6 +31,7 @@
 #include "generated/edk2_vss2.h"
 #include "generated/edk2_ftw.h"
 #include "generated/insyde_fdc.h"
+#include "generated/phoenix_flm.h"
 
 USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
 {
@@ -44,6 +45,14 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
     if (nvar.isEmpty())
         return U_SUCCESS;
 
+    // Obtain required fields from parsing data
+    UINT8 emptyByte = 0xFF;
+    if (model->hasEmptyParsingData(index) == false) {
+        UByteArray data = model->parsingData(index);
+        const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData();
+        emptyByte = pdata->emptyByte;
+    }
+    
     try {
         const UINT32 localOffset = (UINT32)model->header(index).size();
         umemstream is(nvar.constData(), nvar.size());
@@ -73,7 +82,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
                 // Get info
                 UString info = usprintf("Full size: %Xh (%u)", (UINT32)padding.size(), (UINT32)padding.size());
 
-                if ((UINT32)padding.count('\'xFF') == unparsedSize) { // Free space
+                if ((UINT32)padding.count(emptyByte) == unparsedSize) { // Free space
                     // Add tree item
                     model->addItem(localOffset + entry->offset(), Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
                 }
@@ -106,7 +115,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
 
             // Set default next to predefined last value
             NVAR_ENTRY_PARSING_DATA pdata = {};
-            pdata.emptyByte = 0xFF;
+            pdata.emptyByte = emptyByte;
             pdata.next = 0xFFFFFF;
             pdata.isValid = TRUE;
 
@@ -313,6 +322,9 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
     for (UINT32 storeOffset = 0;
          storeOffset < volumeBodySize;
          storeOffset++) {
+        UString name, text, info;
+        UByteArray header, body;
+        
         // VSS
         try {
             if (volumeBodySize - storeOffset < sizeof(VSS_VARIABLE_STORE_HEADER)) {
@@ -347,11 +359,10 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
             }
 
             // Construct header and body
-            UByteArray header = vss.left(parsed.len_vss_store_header());
-            UByteArray body = vss.mid(header.size(), storeSize - header.size());
+            header = vss.left(parsed.len_vss_store_header());
+            body = vss.mid(header.size(), storeSize - header.size());
             
             // Add info
-            UString name;
             if (parsed.signature() == NVRAM_APPLE_SVS_STORE_SIGNATURE) {
                 name = UString("SVS store");
             }
@@ -361,7 +372,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
             else {
                 name = UString("VSS store");
             }
-            UString info = usprintf("Signature: %Xh (", parsed.signature()) + fourCC(parsed.signature()) + UString(")\n");
+            info = usprintf("Signature: %Xh (", parsed.signature()) + fourCC(parsed.signature()) + UString(")\n");
             
             info += usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nFormat: %02Xh\nState: %02Xh\nReserved: %02Xh\nReserved1: %04Xh",
                             storeSize , storeSize,
@@ -379,7 +390,6 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
             UINT32 vssVariableOffset = storeOffset + parsed.len_vss_store_header();
             for (const auto & variable : *parsed.body()->variables()) {
                 UINT8 subtype;
-                UString text;
                 
                 // This is the terminating entry, needs special processing
                 if (variable->_is_null_signature_last()) {
@@ -529,18 +539,17 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
             // VSS2 store at current offset parsed correctly
             // Check if we need to add a padding before it
             if (!outerPadding.isEmpty()) {
-                UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
+                info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
                 model->addItem(previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
                 outerPadding.clear();
             }
 
             // Construct header and body
-            UByteArray header = vss2.left(parsed.len_vss2_store_header());
-            UByteArray body = vss2.mid(header.size(), storeSize - header.size());
+            header = vss2.left(parsed.len_vss2_store_header());
+            body = vss2.mid(header.size(), storeSize - header.size());
             
             // Add info
-            UString name = UString("VSS2 store");
-            UString info;
+            name = UString("VSS2 store");
             if (parsed.signature() == NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1) {
                 info = UString("Signature: AAF32C78-947B-439A-A180-2E144EC37792\n");
             }
@@ -567,7 +576,6 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
             UINT32 vss2VariableOffset = storeOffset + parsed.len_vss2_store_header();
             for (const auto & variable : *parsed.body()->variables()) {
                 UINT8 subtype;
-                UString text;
                 
                 // This is the terminating entry, needs special processing
                 if (variable->_is_null_signature_last()) {
@@ -662,6 +670,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
         if (fdcStoreSizeOverride != 0) {
             continue;
         }
+        
         // FTW
         try {
             if (volumeBodySize - storeOffset < sizeof(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32)) {
@@ -676,7 +685,6 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
             UINT64 storeSize;
             UINT64 headerSize;
             UINT32 calculatedCrc;
-            UByteArray header;
             if (parsed._is_null_len_write_queue_64()) {
                 headerSize = parsed.len_ftw_store_header_32();
                 storeSize = headerSize + parsed.len_write_queue_32();
@@ -711,12 +719,12 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
             }
             
             // Construct header and body
-            UByteArray body = ftw.mid(header.size(), storeSize - header.size());
+            body = ftw.mid(header.size(), storeSize - header.size());
             
             // Add info
             const EFI_GUID* guid = (const EFI_GUID*)header.constData();
-            UString name = UString("FTW store");
-            UString info = UString("Signature: ") + guidToUString(*guid, false);
+            name = UString("FTW store");
+            info = UString("Signature: ") + guidToUString(*guid, false);
             info += usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nState: %02Xh\nHeader CRC32: %08Xh",
                              (UINT32)storeSize, (UINT32)storeSize,
                              (UINT32)header.size(), (UINT32)header.size(),
@@ -733,6 +741,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
         } catch (...) {
             // Parsing failed, try something else
         }
+        
         // Insyde FDC
         try {
             if (volumeBodySize - storeOffset < sizeof(FDC_VOLUME_HEADER)) {
@@ -755,12 +764,12 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
             }
             
             // Construct header and body
-            UByteArray header = fdc.left(parsed.len_fdc_store_header());
-            UByteArray body = fdc.mid(header.size(),storeSize - header.size());
+            header = fdc.left(parsed.len_fdc_store_header());
+            body = fdc.mid(header.size(),storeSize - header.size());
             
             // Add info
-            UString name = UString("FDC store");
-            UString info = usprintf("Signature: _FDC\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)",
+            name = UString("FDC store");
+            info = usprintf("Signature: _FDC\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)",
                                     storeSize, storeSize,
                                     (UINT32)header.size(), (UINT32)header.size(),
                                     (UINT32)body.size(), (UINT32)body.size());
@@ -794,21 +803,19 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
             // Apple SysF store at current offset parsed correctly
             // Check if we need to add a padding before it
             if (!outerPadding.isEmpty()) {
-                UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
+                info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
                 model->addItem(previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
                 outerPadding.clear();
             }
             
             // Construct header and body
-            UByteArray header = sysf.left(parsed.len_sysf_store_header());
-            UByteArray body = sysf.mid(header.size(), storeSize - header.size());
+            header = sysf.left(parsed.len_sysf_store_header());
+            body = sysf.mid(header.size(), storeSize - header.size());
             
             // Check store checksum
             UINT32 calculatedCrc = (UINT32)crc32(0, (const UINT8*)sysf.constData(), storeSize - sizeof(UINT32));
             
             // Add info
-            UString name;
-            UString info;
             if (parsed.signature() == NVRAM_APPLE_SYSF_STORE_SIGNATURE) {
                 name = UString("SysF store");
                 info = UString("Signature: Fsys\n");
@@ -841,6 +848,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
                     subtype = Subtypes::NormalSysFEntry;
                     name = usprintf("%s", variable->name().c_str());
                 }
+                
                 if (variable->len_name() == 3 && variable->name() == "EOF") {
                     header = volumeBody.mid(sysfVariableOffset, 4);
                 }
@@ -886,10 +894,113 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
             // Parsing failed, try something else
         }
         
-        // Phoenix EVSA
         // Phoenix FlashMap
+        try {
+            if (volumeBodySize - storeOffset < NVRAM_PHOENIX_FLASH_MAP_TOTAL_SIZE) {
+                // No need to parse further, the rest of the volume is too small
+                throw 0;
+            }
+            
+            UByteArray flm = volumeBody.mid(storeOffset);
+            umemstream is(flm.constData(), flm.size());
+            kaitai::kstream ks(&is);
+            phoenix_flm_t parsed(&ks);
+            UINT32 storeSize = parsed.len_flm_store();
+            
+            // Phoenix FlashMap store at current offset parsed correctly
+            // Check if we need to add a padding before it
+            if (!outerPadding.isEmpty()) {
+                info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
+                model->addItem(previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
+                outerPadding.clear();
+            }
+            
+            // Construct header and body
+            header = flm.left(parsed.len_flm_store_header());
+            body = flm.mid(header.size(), storeSize - header.size());
+            
+            // Add info
+            name = UString("FlashMap");
+            info = usprintf("Signature: _FLASH_MAP\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nEntries: %u\nReserved: %08Xh",
+                                    storeSize, storeSize,
+                                    (UINT32)header.size(), (UINT32)header.size(),
+                                    (UINT32)body.size(), (UINT32)body.size(),
+                                    parsed.num_entries(),
+                                    parsed.reserved());
+            
+            // Add header tree item
+            UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::FlashMapStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
+            
+            // Add entries
+            UINT32 entryOffset = storeOffset + parsed.len_flm_store_header();
+            for (const auto & entry : *parsed.entries()) {
+                UINT8 subtype;
+                
+                if (entry->data_type() == NVRAM_PHOENIX_FLASH_MAP_ENTRY_DATA_TYPE_VOLUME) {
+                    subtype = Subtypes::VolumeFlashMapEntry;
+                }
+                else if (entry->data_type() == NVRAM_PHOENIX_FLASH_MAP_ENTRY_DATA_TYPE_DATA_BLOCK) {
+                    subtype = Subtypes::DataFlashMapEntry;
+                }
+                else {
+                    subtype = Subtypes::UnknownFlashMapEntry;
+                }
+                
+                const EFI_GUID guid = readUnaligned((const EFI_GUID*)entry->guid().c_str());
+                name = guidToUString(guid);
+                text = flashMapGuidToUString(guid);
+                header = volumeBody.mid(entryOffset, parsed.len_flm_entry());
+
+                // Add info
+                UINT32 entrySize = (UINT32)header.size();
+                info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: 0h (0)\nData type: %04Xh\nEntry type: %04Xh\nSize: %08Xh\nOffset: %08Xh\nPhysical address: %" PRIX64 "h",
+                                entrySize, entrySize,
+                                (UINT32)header.size(), (UINT32)header.size(),
+                                entry->data_type(),
+                                entry->entry_type(),
+                                entry->size(),
+                                entry->offset(),
+                                entry->physical_address());
+                
+                // Add tree item
+                model->addItem(entryOffset, Types::FlashMapEntry, subtype, name, text, info, header, UByteArray(), UByteArray(), Fixed, headerIndex);
+                
+                entryOffset += entrySize;
+            }
+            
+            // Add free space, if needed
+            UByteArray freeSpace;
+            for (const auto & byte : *parsed.free_space()) {
+                freeSpace += (const char)byte;
+            }
+            if (freeSpace.size() > 0) {
+                // Add info
+                info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size());
+                
+                // Check that remaining unparsed bytes are actually zeroes
+                if (freeSpace.count(emptyByte) == freeSpace.size()) { // Free space
+                    // Add tree item
+                    model->addItem(entryOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex);
+                }
+                else {
+                    // Add tree item
+                    model->addItem(entryOffset, Types::Padding, getPaddingType(freeSpace), UString("Padding"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex);
+                }
+            }
+            
+            storeOffset += storeSize - 1;
+            previousStoreEndOffset = storeOffset + 1;
+            continue;
+        } catch (...) {
+            // Parsing failed, try something else
+        }
+        
+        // Phoenix EVSA
+        
         // Phoenix CMDB
+        
         // Phoenix SLIC Pubkey/Marker
+        
         // Intel uCode
         
         // Padding
diff --git a/common/types.cpp b/common/types.cpp
index 9b51628..8762fcd 100755
--- a/common/types.cpp
+++ b/common/types.cpp
@@ -142,6 +142,7 @@ UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
         case Types::FlashMapEntry:
             if      (subtype == Subtypes::VolumeFlashMapEntry)          return UString("Volume");
             else if (subtype == Subtypes::DataFlashMapEntry)            return UString("Data");
+            else if (subtype == Subtypes::UnknownFlashMapEntry)         return UString("Unknown");
             break;
         case Types::Microcode:
             if      (subtype == Subtypes::IntelMicrocode)               return UString("Intel");
diff --git a/common/types.h b/common/types.h
index fde5e11..2f0b062 100755
--- a/common/types.h
+++ b/common/types.h
@@ -154,6 +154,7 @@ namespace Subtypes {
     enum FlashMapEntrySubtypes {
         VolumeFlashMapEntry = 170,
         DataFlashMapEntry,
+        UnknownFlashMapEntry,
     };
 
     enum MicrocodeSubtypes {
diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt
index 2fba14c..2b70347 100644
--- a/fuzzing/CMakeLists.txt
+++ b/fuzzing/CMakeLists.txt
@@ -37,6 +37,7 @@ SET(PROJECT_SOURCES
  ../common/generated/edk2_vss2.cpp
  ../common/generated/edk2_ftw.cpp
  ../common/generated/insyde_fdc.cpp
+ ../common/generated/phoenix_flm.cpp
  ../common/generated/intel_acbp_v1.cpp
  ../common/generated/intel_acbp_v2.cpp
  ../common/generated/intel_keym_v1.cpp