mirror of
https://github.com/LongSoft/UEFITool.git
synced 2025-05-18 17:25:19 -04:00
Version 0.2.0
Initial public commit
This commit is contained in:
commit
4afe74850d
46 changed files with 13817 additions and 0 deletions
354
treemodel.cpp
Normal file
354
treemodel.cpp
Normal file
|
@ -0,0 +1,354 @@
|
|||
/* treemodel.cpp
|
||||
|
||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
*/
|
||||
|
||||
#include "treeitem.h"
|
||||
#include "treemodel.h"
|
||||
#include "ffs.h"
|
||||
#include "descriptor.h"
|
||||
|
||||
TreeModel::TreeModel(QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
{
|
||||
rootItem = new TreeItem(ItemTypes::RootItem, 0, tr("Object"), tr("Type"), tr("Subtype"), tr("Text"));
|
||||
}
|
||||
|
||||
TreeModel::~TreeModel()
|
||||
{
|
||||
delete rootItem;
|
||||
}
|
||||
|
||||
bool TreeModel::hasEmptyHeader(const QModelIndex& index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return true;
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
|
||||
return item->hasEmptyHeader();
|
||||
}
|
||||
|
||||
bool TreeModel::hasEmptyBody(const QModelIndex& index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return true;
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
|
||||
return item->hasEmptyBody();
|
||||
}
|
||||
|
||||
|
||||
int TreeModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
|
||||
else
|
||||
return rootItem->columnCount();
|
||||
}
|
||||
|
||||
QVariant TreeModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (role != Qt::DisplayRole && role != Qt::UserRole)
|
||||
return QVariant();
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
return item->data(index.column());
|
||||
else
|
||||
return item->info();
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
}
|
||||
|
||||
QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
|
||||
int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
return rootItem->data(section);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent)
|
||||
const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem *parentItem;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = rootItem;
|
||||
else
|
||||
parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||
|
||||
TreeItem *childItem = parentItem->child(row);
|
||||
if (childItem)
|
||||
return createIndex(row, column, childItem);
|
||||
else
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex TreeModel::parent(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
|
||||
TreeItem *parentItem = childItem->parent();
|
||||
|
||||
if (parentItem == rootItem)
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(parentItem->row(), 0, parentItem);
|
||||
}
|
||||
|
||||
|
||||
int TreeModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
TreeItem *parentItem;
|
||||
if (parent.column() > 0)
|
||||
return 0;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = rootItem;
|
||||
else
|
||||
parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||
|
||||
return parentItem->childCount();
|
||||
}
|
||||
|
||||
QModelIndex TreeModel::addItem(UINT8 type, UINT8 subtype, const QByteArray &header, const QByteArray &body, const QModelIndex &parent)
|
||||
{
|
||||
TreeItem *parentItem;
|
||||
int parentColumn = 0;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = rootItem;
|
||||
else
|
||||
{
|
||||
parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||
parentColumn = parent.column();
|
||||
}
|
||||
|
||||
// All information extraction must be here
|
||||
QString name, typeName, subtypeName, info;
|
||||
EFI_CAPSULE_HEADER* capsuleHeader;
|
||||
APTIO_CAPSULE_HEADER* aptioCapsuleHeader;
|
||||
FLASH_DESCRIPTOR_MAP* descriptorMap;
|
||||
//FLASH_DESCRIPTOR_COMPONENT_SECTION* componentSection;
|
||||
//FLASH_DESCRIPTOR_REGION_SECTION* regionSection;
|
||||
//FLASH_DESCRIPTOR_MASTER_SECTION* masterSection;
|
||||
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader;
|
||||
EFI_FFS_FILE_HEADER* fileHeader;
|
||||
//EFI_COMMON_SECTION_HEADER* sectionHeader;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ItemTypes::RootItem:
|
||||
// Do not allow to add another root item
|
||||
return QModelIndex();
|
||||
break;
|
||||
case ItemTypes::CapsuleItem:
|
||||
//typeName = tr("Capsule");
|
||||
switch (subtype)
|
||||
{
|
||||
case CapsuleSubtypes::AptioCapsule:
|
||||
name = tr("AMI Aptio capsule");
|
||||
aptioCapsuleHeader = (APTIO_CAPSULE_HEADER*) header.constData();
|
||||
info = tr("GUID: %1\nHeader size: %2\nFlags: %3\nImage size: %4")
|
||||
.arg(guidToQString(aptioCapsuleHeader->CapsuleHeader.CapsuleGuid))
|
||||
.arg(aptioCapsuleHeader->CapsuleHeader.Flags, 8, 16, QChar('0'))
|
||||
.arg(aptioCapsuleHeader->RomImageOffset, 4, 16, QChar('0'))
|
||||
.arg(aptioCapsuleHeader->CapsuleHeader.CapsuleImageSize - aptioCapsuleHeader->RomImageOffset, 8, 16, QChar('0'));
|
||||
//!TODO: more info about Aptio capsule
|
||||
break;
|
||||
case CapsuleSubtypes::UefiCapsule:
|
||||
name = tr("UEFI capsule");
|
||||
capsuleHeader = (EFI_CAPSULE_HEADER*) header.constData();
|
||||
info = tr("GUID: %1\nHeader size: %2\nFlags: %3\nImage size: %4")
|
||||
.arg(guidToQString(capsuleHeader->CapsuleGuid))
|
||||
.arg(capsuleHeader->Flags, 8, 16, QChar('0'))
|
||||
.arg(capsuleHeader->HeaderSize, 8, 16, QChar('0'))
|
||||
.arg(capsuleHeader->CapsuleImageSize, 8, 16, QChar('0'));
|
||||
break;
|
||||
default:
|
||||
name = tr("Unknown capsule");
|
||||
info = tr("GUID: %1\n").arg(guidToQString(*(EFI_GUID*)header.constData()));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ItemTypes::DescriptorItem:
|
||||
name = tr("Descriptor");
|
||||
descriptorMap = (FLASH_DESCRIPTOR_MAP*) body.constData();
|
||||
info = tr("Flash chips: %1\nRegions: %2\nMasters: %3\nPCH straps:%4\nPROC straps: %5\nICC table entries: %6")
|
||||
.arg(descriptorMap->NumberOfFlashChips + 1) //
|
||||
.arg(descriptorMap->NumberOfRegions + 1) // Zero-based numbers in storage
|
||||
.arg(descriptorMap->NumberOfMasters + 1) //
|
||||
.arg(descriptorMap->NumberOfPchStraps)
|
||||
.arg(descriptorMap->NumberOfProcStraps)
|
||||
.arg(descriptorMap->NumberOfIccTableEntries);
|
||||
//!TODO: more info about descriptor
|
||||
break;
|
||||
case ItemTypes::RegionItem:
|
||||
typeName = tr("Region");
|
||||
info = tr("Size: %1").arg(body.size(), 8, 16, QChar('0'));
|
||||
//!TODO: more info about GbE and ME regions
|
||||
switch (subtype)
|
||||
{
|
||||
case RegionSubtypes::GbeRegion:
|
||||
name = tr("GbE region");
|
||||
break;
|
||||
case RegionSubtypes::MeRegion:
|
||||
name = tr("ME region");
|
||||
break;
|
||||
case RegionSubtypes::BiosRegion:
|
||||
name = tr("BIOS region");
|
||||
break;
|
||||
case RegionSubtypes::PdrRegion:
|
||||
name = tr("PDR region");
|
||||
break;
|
||||
default:
|
||||
name = tr("Unknown region");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ItemTypes::PaddingItem:
|
||||
name = tr("Padding");
|
||||
info = tr("Size: %1").arg(body.size(), 8, 16, QChar('0'));
|
||||
break;
|
||||
case ItemTypes::VolumeItem:
|
||||
typeName = tr("Volume");
|
||||
// Parse volume header to determine its revision and file system
|
||||
volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) header.constData();
|
||||
name = guidToQString(volumeHeader->FileSystemGuid);
|
||||
subtypeName = tr("Revision %1").arg(volumeHeader->Revision);
|
||||
info = tr("Size: %1\nSignature: %2\nAttributes: %3\nHeader size: %4")
|
||||
.arg(volumeHeader->FvLength, 8, 16, QChar('0'))
|
||||
.arg(volumeHeader->Signature, 8, 16, QChar('0'))
|
||||
.arg(volumeHeader->Attributes, 8, 16, QChar('0'))
|
||||
.arg(volumeHeader->HeaderLength, 4, 16, QChar('0'));
|
||||
break;
|
||||
case ItemTypes::FileItem:
|
||||
typeName = tr("File");
|
||||
// Parse file header to determine its GUID and type
|
||||
fileHeader = (EFI_FFS_FILE_HEADER*) header.constData();
|
||||
name = guidToQString(fileHeader->Name);
|
||||
subtypeName = fileTypeToQString(subtype);
|
||||
info = tr("Type: %1\nAttributes: %2\nSize: %3\nState: %4")
|
||||
.arg(fileHeader->Type, 2, 16, QChar('0'))
|
||||
.arg(fileHeader->Attributes, 2, 16, QChar('0'))
|
||||
.arg(uint24ToUint32(fileHeader->Size), 6, 16, QChar('0'))
|
||||
.arg(fileHeader->State, 2, 16, QChar('0'));
|
||||
break;
|
||||
case ItemTypes::SectionItem:
|
||||
typeName = tr("Section");
|
||||
name = sectionTypeToQString(subtype) + tr(" section");
|
||||
info = tr("Size: %1").arg(body.size(), 8, 16, QChar('0'));
|
||||
//!TODO: add more specific info for all section types with uncommon headers
|
||||
// Set name of file
|
||||
if (subtype == SectionSubtypes::UserInterfaceSection)
|
||||
{
|
||||
QString text = QString::fromUtf16((const ushort*)body.constData());
|
||||
setItemText(text, findParentOfType(ItemTypes::FileItem, parent));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
name = tr("Unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
emit layoutAboutToBeChanged();
|
||||
TreeItem *item = new TreeItem(type, subtype, name, typeName, subtypeName, "", info, header, body, parentItem);
|
||||
parentItem->appendChild(item);
|
||||
emit layoutChanged();
|
||||
return createIndex(parentItem->childCount() - 1, parentColumn, item);
|
||||
}
|
||||
|
||||
bool TreeModel::setItemName(const QString &data, const QModelIndex &index)
|
||||
{
|
||||
if(!index.isValid())
|
||||
return false;
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
item->setName(data);
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TreeModel::setItemText(const QString &data, const QModelIndex &index)
|
||||
{
|
||||
if(!index.isValid())
|
||||
return false;
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
item->setText(data);
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TreeModel::removeItem(const QModelIndex &index)
|
||||
{
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
item->parent()->removeChild(item);
|
||||
delete item;
|
||||
return true;
|
||||
}
|
||||
|
||||
QModelIndex TreeModel::findParentOfType(UINT8 type, const QModelIndex& index)
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem *item;
|
||||
QModelIndex parent = index;
|
||||
|
||||
for(item = static_cast<TreeItem*>(parent.internalPointer());
|
||||
item != NULL && item != rootItem && item->type() != type;
|
||||
item = static_cast<TreeItem*>(parent.internalPointer()))
|
||||
parent = parent.parent();
|
||||
if (item != NULL && item != rootItem)
|
||||
return parent;
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QByteArray TreeModel::header(const QModelIndex& index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QByteArray();
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->header();
|
||||
}
|
||||
|
||||
QByteArray TreeModel::body(const QModelIndex& index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QByteArray();
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->body();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue