FS Firmware Structure¶
This document provides a comprehensive examination of the firmware binaries utilized for updating Frontier Smart devices, offering a more in-depth analysis of their content and functionality.
Note
It is also worth noting that all numbers utilized in the dicovered structures use little endian ancoded integers.
Header Structure¶
There is a specific file header for the update files that contains additional information about the firmware file. It’s important to note that all of the inspected binary files have nearly identical header structures. Therefore, the basic structure can be defined as follows:
1#include <type/guid.pat>
2
3namespace isu {
4 struct Header {
5 le u32 magic; // 0x1176; file signature
6 le u32 length;
7 le u32 isu_version:
8 char version[32]; // version string (padded)
9 char customisation[64]; // firmware string (padded)
10 if (this.length == 0xA2) {
11 // Extended headers contain major and minor version strings
12 char major_version[6];
13 char minor_version[32];
14 }
15 type::GUID uuid; // maybe a UUID (never valid)
16 };
17}
ISU Header¶
This pattern can be used to parse both default and so-called extended ISU headers. For instance, the following image displays the binary header with highlighted sections, providing a visual representation of the header structure.
The next table shows the associated values:
ISU Extended Header¶
If we now examine the so-called extended ISU headers, which are exclusively found in
fsccp-scb
product firmwares, it becomes apparent that they contain two additional
fields that might indicate the major and minor version of the embedded operating system
being used.
The next table shows the associated values:
Data Fields¶
Warning
Please note that the information provided in this chapter is not 100 percent validated; most of it is based on assumptions. Therefore, it is important to approach this chapter with caution and consider the information as speculative rather than definitive.
During the analysis of certain firmware binaries, sections with peculiar names such as
“DecompBuffer” were discovered. For the purpose of reference, we will refer to each of these
sections as a DataField
. It can be described as follows:
1namespace isu {
2 struct DataField {
3 le u16 length; // maybe? (is the size of this struct)
4 le u16 unknown_1;
5 le u16 name_length;
6 le u16 flags; // unknown
7 char name[16]; // padded string
8
9 if (this.length == 32) {
10 le u32 value;
11 le u32 unknown_2;
12 }
13 };
14}
The additional length check is necessary because firmware binaries of the Venice 8 module include an extra field named “CompSSSize” that does not have any associated value data. Below is an illustration of all possible data fields:
The following table presents the associated values for the identified data fields in the Venice 8 module firmware binary:
One interesting fact is that "CompSize"
refers to the compressed core data of the firmware
binary.
Data Sections¶
This chapter refers to sections that encompass lists of “DataFields.” The analyzed firmware binaries contained multiple structures that can be consolidated into a general “DataSection” structure.
namespace isu {
struct DataSection {
le u8 magic; // always 128
le u8 length;
le u8 data[this.length];
};
}
Since this structure has not been validated, it will not be taken into consideration for further analysis.
Directory Archive¶
Directory archives are widely used and considered as a common structure in use today. As the name implies, these archives store a directory that provides information about all the files, including their names, offsets, and lengths. These archives are typically simple and straightforward to read.
The structure can once again be defined using the pattern language. Since we will be defining multiple structures, we will split the definition into several parts. First, we will define the header:
1namespace archive { // in namespace isu
2 struct Header {
3 char magic[4]; // FSH1
4 le u32 size;
5 le u16 unknown_1;
6 le u32 index_size;
7 isu::archive::Index index; // tbd
8 };
9}
Before we declare the archive index, let’s quickly examine the highlighted values to better understand our current situation.
Note that we replaced the isu::archive::Index
with a raw data block as this structure will
be defined in the next section.
Directory Archive Index¶
The Directory archive begins with a header tag called FSH1
. Immediately after that, the size of
the archive and the size of the index are presented as 32-bit numbers. The actual structure of each
entry in the archive index is as follows:
1namespace archive {
2 enum IndexEntryType : u8 {
3 File = 0x00,
4 Directory
5 };
6
7 struct IndexEntry {
8 isu::archive::IndexEntryType type;
9 le u8 name_length;
10 char name[this.name_length];
11
12 if (this.type == isu::archive::IndexEntryType::Directory) {
13 le u8 entry_count;
14 isu::archive::IndexEntry entries[this.entry_count];
15 } else {
16 le u32 size; // file is compressed if size != compressed_size
17 le u32 offset;
18 le u32 compressed_size;
19 }
20 };
21}
Note
The offset is in relation to the start of the directory archive header, so an absolute offset may be computed with:
absolute_position = OFFSET(archive_header) + entry.offset
Now, let’s return to the binary file and apply the defined structure to view all the contents of an ISU Archive Entry.
The following table displays the values for a directory index entry and a file entry:
Finally, we can define the “root” index, which is placed directly after the archive header. Note that it contains an empty name.
1namespace archive { // within namespace isu
2 struct Index {
3 le u8 length;
4 char name[this.length];
5 le u8 entry_count;
6 isu::archive::IndexEntry entries[this.entry_count];
7 };
8}
Since the fully marked directory archive would be too colorful to list here, it will not be included.
Contents of a Directory Archive¶
The structure of a defined directory archive in ISU-Files (except for FS2028
) doesn’t differ much.
The tree structure can be represented as follows:
icons/
web/
css/
images/
iperf/ (optional)
js/
languages/
<HTML-Files>
FwImage/
Please note that this representation is a simplified visual representation of the directory structure
within the archive. The structure itself reveals some interesting information that was previously
unknown. The iperf
directory contains files specifically designed to interact with an inbound
iperf module.
“iPerf3 is a tool used for actively measuring the maximum achievable bandwidth on IP networks.”
—iPerf3 (source)
Regarding the FwImage
directory, it is highly likely to contain a firmware image, and that assumption
is indeed correct. Typically, the file stored in this directory is the latest firmware image for the
built-in Wi-Fi chip.