mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-02-01 17:30:17 +00:00
ofnvram: support CHRP style OF config partition.
This commit is contained in:
parent
d76433f112
commit
c188d0251a
@ -410,7 +410,7 @@ void enter_debugger() {
|
||||
int log_level, context;
|
||||
size_t separator_pos;
|
||||
|
||||
unique_ptr<OfNvramUtils> ofnvram = unique_ptr<OfNvramUtils>(new OfNvramUtils);
|
||||
unique_ptr<OfConfigUtils> ofnvram = unique_ptr<OfConfigUtils>(new OfConfigUtils);
|
||||
|
||||
context = 1; /* start with the PowerPC context */
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||
Copyright (C) 2018-22 divingkatae and maximum
|
||||
Copyright (C) 2018-23 divingkatae and maximum
|
||||
(theweirdo) spatium
|
||||
|
||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||
@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file Utilities for working with the Apple Open Firmware NVRAM partition. */
|
||||
/** Utilities for working with Apple Open Firmware and CHRP NVRAM partitions. */
|
||||
|
||||
#include <devices/common/ofnvram.h>
|
||||
#include <endianswap.h>
|
||||
@ -32,11 +32,19 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static std::string hex2str(uint32_t n)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << setw(8) << setfill('0') << hex << n;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static uint32_t str2env(string& num_str) {
|
||||
try {
|
||||
return (uint32_t)stoul(num_str, NULL, 0);
|
||||
@ -50,22 +58,15 @@ static uint32_t str2env(string& num_str) {
|
||||
}
|
||||
}
|
||||
|
||||
int OfNvramUtils::init()
|
||||
{
|
||||
this->nvram_obj = dynamic_cast<NVram*>(gMachineObj->get_comp_by_name("NVRAM"));
|
||||
return this->nvram_obj == nullptr;
|
||||
}
|
||||
|
||||
bool OfNvramUtils::validate()
|
||||
{
|
||||
int i;
|
||||
OfNvramHdr hdr;
|
||||
bool OfConfigAppl::validate() {
|
||||
int i;
|
||||
OfConfigHdrAppl hdr;
|
||||
|
||||
if (this->nvram_obj == nullptr)
|
||||
return false;
|
||||
|
||||
// read OF partition header
|
||||
for (i = 0; i < sizeof(OfNvramHdr); i++) {
|
||||
for (i = 0; i < sizeof(OfConfigHdrAppl); i++) {
|
||||
((uint8_t*)&hdr)[i] = this->nvram_obj->read_byte(OF_NVRAM_OFFSET + i);
|
||||
}
|
||||
|
||||
@ -75,7 +76,7 @@ bool OfNvramUtils::validate()
|
||||
|
||||
this->size = hdr.num_pages * 256;
|
||||
|
||||
if (this->size != 0x800)
|
||||
if (this->size != OF_CFG_SIZE)
|
||||
return false;
|
||||
|
||||
// read the entire partition into the local buffer
|
||||
@ -88,10 +89,9 @@ bool OfNvramUtils::validate()
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
uint16_t OfNvramUtils::checksum_partition()
|
||||
{
|
||||
uint16_t OfConfigAppl::checksum_partition() {
|
||||
uint32_t acc = 0;
|
||||
|
||||
for (int i = 0; i < this->size; i += 2) {
|
||||
@ -101,25 +101,6 @@ uint16_t OfNvramUtils::checksum_partition()
|
||||
return acc + (acc >> 16);
|
||||
}
|
||||
|
||||
void OfNvramUtils::update_partition()
|
||||
{
|
||||
// set checksum in the header to zero
|
||||
this->buf[4] = 0;
|
||||
this->buf[5] = 0;
|
||||
|
||||
// calculate new checksum
|
||||
uint16_t checksum = this->checksum_partition();
|
||||
checksum = checksum ? ~checksum : 0xFFFFU;
|
||||
|
||||
// stuff it into the header
|
||||
WRITE_WORD_BE_A(&this->buf[4], checksum);
|
||||
|
||||
// write the entire partition back to NVRAM
|
||||
for (int i = 0; i < this->size; i++) {
|
||||
this->nvram_obj->write_byte(OF_NVRAM_OFFSET + i, this->buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static const string flag_names[8] = {
|
||||
"little-endian?",
|
||||
"real-mode?",
|
||||
@ -154,58 +135,74 @@ static const map<string, std::tuple<int, uint16_t>> of_vars = {
|
||||
{"boot-command", {OF_VAR_TYPE_STR, 0x58}},
|
||||
};
|
||||
|
||||
void OfNvramUtils::printenv()
|
||||
{
|
||||
int i;
|
||||
const OfConfigImpl::config_dict& OfConfigAppl::get_config_vars() {
|
||||
this->_config_vars.clear();
|
||||
|
||||
if (!this->validate()) {
|
||||
cout << "Invalid Open Firmware partition content!" << endl;
|
||||
return;
|
||||
}
|
||||
if (!this->validate())
|
||||
return _config_vars;
|
||||
|
||||
uint8_t of_flags = this->buf[12];
|
||||
|
||||
cout << endl;
|
||||
|
||||
// print flags
|
||||
for (i = 0; i < 8; i++) {
|
||||
cout << setw(20) << left << flag_names[i] <<
|
||||
(((of_flags << i) & 0x80) ? "true" : "false") << endl;
|
||||
// populate flags
|
||||
for (int i = 0; i < 8; i++) {
|
||||
_config_vars.push_back(std::make_pair(flag_names[i],
|
||||
((of_flags << i) & 0x80) ? "true" : "false"));
|
||||
}
|
||||
|
||||
// print the remaining variables
|
||||
// populate the remaining variables
|
||||
for (auto& var : of_vars) {
|
||||
auto name = var.first;
|
||||
auto type = std::get<0>(var.second);
|
||||
auto offset = std::get<1>(var.second);
|
||||
|
||||
cout << setw(20) << left << var.first;
|
||||
|
||||
switch (type) {
|
||||
case OF_VAR_TYPE_INT:
|
||||
cout << hex << READ_DWORD_BE_A(&this->buf[offset]) << endl;
|
||||
_config_vars.push_back(std::make_pair(name,
|
||||
hex2str(READ_DWORD_BE_A(&this->buf[offset]))));
|
||||
break;
|
||||
case OF_VAR_TYPE_STR:
|
||||
uint16_t str_offset = READ_WORD_BE_A(&this->buf[offset]) - OF_NVRAM_OFFSET;
|
||||
uint16_t str_len = READ_WORD_BE_A(&this->buf[offset+2]);
|
||||
for (i = 0; i < str_len; i++) {
|
||||
char ch = *(char *)&(this->buf[str_offset + i]);
|
||||
if (ch == '\x0D') cout << endl; else cout << ch;
|
||||
|
||||
if ((str_offset + str_len) > OF_CFG_SIZE) {
|
||||
cout << "string property too long - skip it" << endl;
|
||||
break;
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
char prop_val[OF_CFG_SIZE] = "";
|
||||
memcpy(prop_val, &this->buf[str_offset], str_len);
|
||||
prop_val[str_len] = '\0';
|
||||
|
||||
_config_vars.push_back(std::make_pair(name, prop_val));
|
||||
}
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
return _config_vars;
|
||||
};
|
||||
|
||||
void OfConfigAppl::update_partition() {
|
||||
// set checksum in the header to zero
|
||||
this->buf[4] = 0;
|
||||
this->buf[5] = 0;
|
||||
|
||||
// calculate new checksum
|
||||
uint16_t checksum = this->checksum_partition();
|
||||
checksum = checksum ? ~checksum : 0xFFFFU;
|
||||
|
||||
// stuff checksum into the header
|
||||
WRITE_WORD_BE_A(&this->buf[4], checksum);
|
||||
|
||||
// write the entire partition back to NVRAM
|
||||
for (int i = 0; i < this->size; i++) {
|
||||
this->nvram_obj->write_byte(OF_NVRAM_OFFSET + i, this->buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void OfNvramUtils::setenv(string var_name, string value)
|
||||
{
|
||||
bool OfConfigAppl::set_var(std::string& var_name, std::string& value) {
|
||||
int i, flag;
|
||||
|
||||
if (!this->validate()) {
|
||||
cout << "Invalid Open Firmware partition content!" << endl;
|
||||
return;
|
||||
}
|
||||
if (!this->validate())
|
||||
return false;
|
||||
|
||||
// check if the user tries to change a flag
|
||||
for (i = 0; i < 8; i++) {
|
||||
@ -216,7 +213,7 @@ void OfNvramUtils::setenv(string var_name, string value)
|
||||
flag = 0;
|
||||
else {
|
||||
cout << "Invalid property value: " << value << endl;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
uint8_t flag_bit = 0x80U >> i;
|
||||
uint8_t of_flags = this->buf[12];
|
||||
@ -228,15 +225,14 @@ void OfNvramUtils::setenv(string var_name, string value)
|
||||
|
||||
this->buf[12] = of_flags;
|
||||
this->update_partition();
|
||||
cout << " ok" << endl; // mimic Forth
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// see if one of the standard properties should be changed
|
||||
if (of_vars.find(var_name) == of_vars.end()) {
|
||||
cout << "Attempt to change unknown variable " << var_name << endl;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto type = std::get<0>(of_vars.at(var_name));
|
||||
@ -248,7 +244,7 @@ void OfNvramUtils::setenv(string var_name, string value)
|
||||
num = str2env(value);
|
||||
} catch (invalid_argument& exc) {
|
||||
cout << exc.what() << endl;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
WRITE_DWORD_BE_A(&this->buf[offset], num);
|
||||
this->update_partition();
|
||||
@ -257,7 +253,7 @@ void OfNvramUtils::setenv(string var_name, string value)
|
||||
uint16_t str_offset = READ_WORD_BE_A(&this->buf[offset]);
|
||||
uint16_t str_len = READ_WORD_BE_A(&this->buf[offset+2]);
|
||||
|
||||
OfNvramHdr *hdr = (OfNvramHdr *)&this->buf[0];
|
||||
OfConfigHdrAppl *hdr = (OfConfigHdrAppl *)&this->buf[0];
|
||||
uint16_t here = READ_WORD_BE_A(&hdr->here);
|
||||
uint16_t top = READ_WORD_BE_A(&hdr->top);
|
||||
|
||||
@ -266,11 +262,13 @@ void OfNvramUtils::setenv(string var_name, string value)
|
||||
uint16_t new_top = top + str_len - value.length();
|
||||
if (new_top < here) {
|
||||
cout << "No room in the heap!" << endl;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove the old string
|
||||
std::memmove(&this->buf[top + str_len - OF_NVRAM_OFFSET], &this->buf[top - OF_NVRAM_OFFSET], str_offset - top);
|
||||
std::memmove(&this->buf[top + str_len - OF_NVRAM_OFFSET],
|
||||
&this->buf[top - OF_NVRAM_OFFSET], str_offset - top);
|
||||
|
||||
for (auto& var : of_vars) {
|
||||
auto type = std::get<0>(var.second);
|
||||
auto offset = std::get<1>(var.second);
|
||||
@ -299,7 +297,271 @@ void OfNvramUtils::setenv(string var_name, string value)
|
||||
|
||||
// update physical NVRAM
|
||||
this->update_partition();
|
||||
cout << " ok" << endl; // mimic Forth
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
uint8_t OfConfigChrp::checksum_hdr(const uint8_t* data)
|
||||
{
|
||||
uint16_t sum = data[0];
|
||||
|
||||
for (int i = 2; i < 16; i++) {
|
||||
sum += data[i];
|
||||
if (sum >= 256)
|
||||
sum = (sum + 1) & 0xFFU;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
bool OfConfigChrp::validate()
|
||||
{
|
||||
int i, pos, len;
|
||||
uint8_t sig;
|
||||
bool wip = true;
|
||||
bool of_part_found = false;
|
||||
|
||||
// search the entire 8KB NVRAM for CHRP OF config partition.
|
||||
// Bail out if an unknown partition or free space is encountered.
|
||||
// Skip over known partitions.
|
||||
for (pos = 0; wip && pos < 8192;) {
|
||||
sig = this->nvram_obj->read_byte(pos);
|
||||
switch (sig) {
|
||||
case NVRAM_SIG_OF_ENV:
|
||||
of_part_found = true;
|
||||
// fall-through
|
||||
case NVRAM_SIG_FREE:
|
||||
wip = false;
|
||||
break;
|
||||
case NVRAM_SIG_VPD:
|
||||
case NVRAM_SIG_DIAG:
|
||||
case NVRAM_SIG_OF_CFG:
|
||||
case NVRAM_SIG_MAC_OS:
|
||||
case NVRAM_SIG_ERR_LOG:
|
||||
// skip valid partitions we're not interested in
|
||||
len = (this->nvram_obj->read_byte(pos + 2) << 8) |
|
||||
this->nvram_obj->read_byte(pos + 3);
|
||||
if (!len || (len * 16) >= 8192)
|
||||
break;
|
||||
pos += len * 16;
|
||||
break;
|
||||
default:
|
||||
wip = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!of_part_found)
|
||||
return false;
|
||||
|
||||
OfConfigHdrChrp hdr;
|
||||
|
||||
// read OF partition header
|
||||
for (i = 0; i < sizeof(OfConfigHdrChrp); i++) {
|
||||
((uint8_t*)&hdr)[i] = this->nvram_obj->read_byte(pos + i);
|
||||
}
|
||||
|
||||
len = BYTESWAP_16(hdr.length) * 16;
|
||||
|
||||
// sanity checks
|
||||
if (hdr.sig != NVRAM_SIG_OF_ENV || len < 16 || len > (4096 + sizeof(OfConfigHdrChrp)))
|
||||
return false;
|
||||
|
||||
// calculate partition header checksum
|
||||
uint8_t chk_sum = this->checksum_hdr((uint8_t*)&hdr);
|
||||
|
||||
if (chk_sum != hdr.checksum)
|
||||
return false;
|
||||
|
||||
len -= sizeof(OfConfigHdrChrp);
|
||||
pos += sizeof(OfConfigHdrChrp);
|
||||
|
||||
this->data_offset = pos;
|
||||
|
||||
// read the entire partition into the local buffer
|
||||
for (i = 0; i < len; i++) {
|
||||
this->buf[i] = this->nvram_obj->read_byte(pos + i);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const OfConfigImpl::config_dict& OfConfigChrp::get_config_vars() {
|
||||
int len;
|
||||
|
||||
this->_config_vars.clear();
|
||||
|
||||
if (!this->validate())
|
||||
return _config_vars;
|
||||
|
||||
for (int pos = 0; pos < 4096;) {
|
||||
char *pname = (char *)&this->buf[pos];
|
||||
|
||||
// scan property name until '=' is encountered
|
||||
// or max length is reached
|
||||
for (len = 0; len < 32; pos++, len++) {
|
||||
if (pname[len] == '=' || pname[len] == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
// empty property name -> free space reached
|
||||
if (!len) {
|
||||
this->data_length = pos;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pname[len] != '=') {
|
||||
cout << "no = sign found or name > 31 chars" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
char prop_name[32];
|
||||
memcpy(prop_name, pname, len);
|
||||
prop_name[len] = '\0';
|
||||
|
||||
pos++; // skip past '='
|
||||
char *pval = (char *)&this->buf[pos];
|
||||
|
||||
// determine property value length
|
||||
for (len = 0; pos < 4096; pos++, len++) {
|
||||
if (pval[len] == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
// ensure each property value is null-terminated
|
||||
if (pos >= 4096) {
|
||||
cout << "ran off partition end" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
this->_config_vars.push_back(std::make_pair(prop_name, pval));
|
||||
pos++; // skip past null terminator
|
||||
}
|
||||
|
||||
return this->_config_vars;
|
||||
}
|
||||
|
||||
bool OfConfigChrp::update_partition() {
|
||||
unsigned pos = 0;
|
||||
|
||||
memset(this->buf, 0, 4096);
|
||||
|
||||
for (auto& var : this->_config_vars) {
|
||||
if ((var.first.length() + var.second.length() + 2) >= 4096) {
|
||||
cout << "No room in the partition!" << endl;
|
||||
return false;
|
||||
}
|
||||
memcpy(&this->buf[pos], var.first.c_str(), var.first.length());
|
||||
pos += var.first.length();
|
||||
this->buf[pos++] = '=';
|
||||
memcpy(&this->buf[pos], var.second.c_str(), var.second.length());
|
||||
pos += var.second.length();
|
||||
this->buf[pos++] = '\0';
|
||||
}
|
||||
|
||||
// write the entire partition back to NVRAM
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
this->nvram_obj->write_byte(this->data_offset + i, this->buf[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OfConfigChrp::set_var(std::string& var_name, std::string& value) {
|
||||
if (!this->validate())
|
||||
return false;
|
||||
|
||||
bool found = false;
|
||||
|
||||
// see if the user tries to change an existing property
|
||||
for (auto& var : this->_config_vars) {
|
||||
if (var.first == var_name) {
|
||||
found = true;
|
||||
|
||||
// see if we're about to change a flag
|
||||
if (var_name.back() == '?') {
|
||||
if (value != "true" && value != "false") {
|
||||
cout << "Flag value can be 'true' or 'false'" << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (value.length() > var.second.length()) {
|
||||
unsigned free_space = 4096 - this->data_length;
|
||||
if ((value.length() - var.second.length()) >= free_space) {
|
||||
cout << "No room for new data!" << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var.second = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
cout << "Attempt to change unknown variable " << var_name << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return this->update_partition();
|
||||
};
|
||||
|
||||
int OfConfigUtils::init()
|
||||
{
|
||||
this->nvram_obj = dynamic_cast<NVram*>(gMachineObj->get_comp_by_name("NVRAM"));
|
||||
return this->nvram_obj == nullptr;
|
||||
}
|
||||
|
||||
bool OfConfigUtils::open_container() {
|
||||
OfConfigImpl* cfg_obj;
|
||||
|
||||
if (this->cfg_impl == nullptr) {
|
||||
cfg_obj = new OfConfigAppl(this->nvram_obj);
|
||||
if (cfg_obj->validate()) {
|
||||
this->cfg_impl = std::unique_ptr<OfConfigImpl>(cfg_obj);
|
||||
return true;
|
||||
} else {
|
||||
delete(cfg_obj);
|
||||
|
||||
cfg_obj = new OfConfigChrp(this->nvram_obj);
|
||||
if (cfg_obj->validate()) {
|
||||
this->cfg_impl = std::unique_ptr<OfConfigImpl>(cfg_obj);
|
||||
return true;
|
||||
} else {
|
||||
delete(cfg_obj);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return this->cfg_impl->validate();
|
||||
}
|
||||
|
||||
cout << "No valid Open Firmware partition found!" << endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void OfConfigUtils::printenv() {
|
||||
OfConfigImpl::config_dict vars;
|
||||
|
||||
if (!this->open_container())
|
||||
return;
|
||||
|
||||
vars = this->cfg_impl->get_config_vars();
|
||||
|
||||
for (auto& var : vars) {
|
||||
cout << setw(34) << left << var.first << var.second << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void OfConfigUtils::setenv(string var_name, string value)
|
||||
{
|
||||
if (!this->open_container())
|
||||
return;
|
||||
|
||||
if (!this->cfg_impl->set_var(var_name, value)) {
|
||||
cout << " Please try again" << endl;
|
||||
} else {
|
||||
cout << " ok" << endl; // mimic Forth
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||
Copyright (C) 2018-22 divingkatae and maximum
|
||||
Copyright (C) 2018-23 divingkatae and maximum
|
||||
(theweirdo) spatium
|
||||
|
||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||
@ -19,20 +19,30 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** Apple/CHRP Open Firmware NVRAM partition definitions. */
|
||||
|
||||
#ifndef OF_NVRAM_H
|
||||
#define OF_NVRAM_H
|
||||
|
||||
#include <devices/common/nvram.h>
|
||||
|
||||
/** @file Utilities for working with the Apple Open Firmware NVRAM partition. */
|
||||
#include <cinttypes>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
/** ========== Apple Open Firmware 1.x/2.x partition definitions. ========== */
|
||||
#define OF_NVRAM_OFFSET 0x1800
|
||||
#define OF_NVRAM_SIG 0x1275
|
||||
#define OF_CFG_SIZE 0x800
|
||||
|
||||
// OF Variable types
|
||||
enum {
|
||||
OF_VAR_TYPE_INT = 1,
|
||||
OF_VAR_TYPE_STR = 2,
|
||||
OF_VAR_TYPE_INT = 1, // integer
|
||||
OF_VAR_TYPE_STR = 2, // string
|
||||
OF_VAR_TYPE_FLG = 3, // boolean flag
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@ -42,26 +52,97 @@ typedef struct {
|
||||
uint16_t checksum; // >nv.checksum partition checksum
|
||||
uint16_t here; // >nv.here offset to the next free byte (offset of after last string length; = 0x185c)
|
||||
uint16_t top; // >nv.top offset to the last free byte (offset of string with lowest offset; < 0x2000)
|
||||
} OfNvramHdr;
|
||||
} OfConfigHdrAppl;
|
||||
|
||||
class OfNvramUtils {
|
||||
/** ================== CHRP NVRAM partition definitions. ================== */
|
||||
|
||||
/** CHRP NVRAM partition signatures. */
|
||||
enum {
|
||||
NVRAM_SIG_OF_CFG = 0x50, // of-config (unused in Power Macintosh)
|
||||
NVRAM_SIG_VPD = 0x52, // of-vpd (unused in Power Macintosh)
|
||||
NVRAM_SIG_DIAG = 0x5F, // diagnostics partition
|
||||
NVRAM_SIG_OF_ENV = 0x70, // common partition with OF environment vars
|
||||
NVRAM_SIG_ERR_LOG = 0x72, // post-err-log
|
||||
NVRAM_SIG_FREE = 0x7F, // free space
|
||||
NVRAM_SIG_MAC_OS = 0xA0, // APL,MacOS75
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t sig; // partition signature, must be 0x70
|
||||
uint8_t checksum; // partition header checksum (sig, length & name)
|
||||
uint16_t length; // partition length in 16-byte blocks
|
||||
char name[12]; // null-terminated partition name
|
||||
} OfConfigHdrChrp;
|
||||
|
||||
// - interface
|
||||
class OfConfigImpl {
|
||||
public:
|
||||
OfNvramUtils() = default;
|
||||
~OfNvramUtils() = default;
|
||||
using config_dict = std::vector<std::pair<std::string, std::string>>;
|
||||
|
||||
virtual ~OfConfigImpl() = default;
|
||||
virtual bool validate() = 0;
|
||||
virtual const config_dict& get_config_vars() = 0;
|
||||
virtual bool set_var(std::string& name, std::string& val) = 0;
|
||||
};
|
||||
|
||||
// Old World implementation
|
||||
class OfConfigAppl : public OfConfigImpl {
|
||||
public:
|
||||
OfConfigAppl(NVram* nvram_obj) { this->nvram_obj = nvram_obj; };
|
||||
~OfConfigAppl() = default;
|
||||
|
||||
bool validate();
|
||||
const config_dict& get_config_vars();
|
||||
bool set_var(std::string& var_name, std::string& value);
|
||||
|
||||
protected:
|
||||
uint16_t checksum_partition();
|
||||
void update_partition();
|
||||
|
||||
private:
|
||||
NVram* nvram_obj = nullptr;
|
||||
uint8_t buf[OF_CFG_SIZE];
|
||||
int size = 0;
|
||||
config_dict _config_vars;
|
||||
};
|
||||
|
||||
// New World implementation
|
||||
class OfConfigChrp : public OfConfigImpl {
|
||||
public:
|
||||
OfConfigChrp(NVram* nvram_obj) { this->nvram_obj = nvram_obj; };
|
||||
~OfConfigChrp() = default;
|
||||
|
||||
bool validate();
|
||||
const config_dict& get_config_vars();
|
||||
bool set_var(std::string& var_name, std::string& value);
|
||||
|
||||
protected:
|
||||
uint8_t checksum_hdr(const uint8_t* data);
|
||||
bool update_partition();
|
||||
|
||||
private:
|
||||
NVram* nvram_obj = nullptr;
|
||||
uint8_t buf[4096];
|
||||
unsigned data_offset = 0; // offset to the OF config data
|
||||
unsigned data_length = 0; // length of the OF config data
|
||||
config_dict _config_vars;
|
||||
};
|
||||
|
||||
class OfConfigUtils {
|
||||
public:
|
||||
OfConfigUtils() = default;
|
||||
~OfConfigUtils() = default;
|
||||
|
||||
int init();
|
||||
void printenv();
|
||||
void setenv(std::string var_name, std::string value);
|
||||
|
||||
protected:
|
||||
bool validate();
|
||||
uint16_t checksum_partition();
|
||||
void update_partition();
|
||||
bool open_container();
|
||||
|
||||
private:
|
||||
NVram* nvram_obj = nullptr;
|
||||
int size = 0;
|
||||
uint8_t buf[0x800];
|
||||
std::unique_ptr<OfConfigImpl> cfg_impl = nullptr;
|
||||
NVram* nvram_obj = nullptr;
|
||||
};
|
||||
|
||||
#endif // OF_NVRAM_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user