#1226 - Detection of Rpi version checking refactor

This commit is contained in:
Tony Kuker 2024-05-28 03:12:35 +00:00
parent 4650f2bd88
commit 839bc0c009
8 changed files with 1235 additions and 79 deletions

13
cpp/.clangformat Normal file
View File

@ -0,0 +1,13 @@
BasedOnStyle: Microsoft
IndentWidth: 4
AlwaysBreakAfterReturnType: None
AllowShortFunctionsOnASingleLine: Empty
KeepEmptyLinesAtTheStartOfBlocks: false
BreakBeforeBraces: Linux
AlignEscapedNewlines: Left
AlignTrailingComments: True
AllowShortEnumsOnASingleLine: True
AlignConsecutiveAssignments: Consecutive
ColumnLimit: 120
PointerAlignment: Left

View File

@ -0,0 +1,100 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator PiSCSI
// for Raspberry Pi
//
// Copyright (C) 2024 akuker
//
// [ Detect Raspberry Pi version information ]
//
// The Raspberry Pi version detection is based upon the example code
// provided by the Raspberry Pi foundation:
// https://github.com/raspberrypi/documentation/blob/develop/documentation/asciidoc/computers/raspberry-pi/revision-codes.adoc
//
//---------------------------------------------------------------------------
#include "rpi_revision_code.h"
#include <array>
#include <cstdio>
#include <cstdlib>
#include <fmt/core.h>
#include <iostream>
#include <memory>
#include <spdlog/spdlog.h>
#include <stdexcept>
#include <string>
Rpi_Revision_Code::Rpi_Revision_Code(const string &cpuinfo_path) {
std::string cmd = "cat " + cpuinfo_path + "| awk '/Revision/ {print $3}'";
std::array<char, 128> buffer;
std::string result;
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"),
pclose);
if (!pipe) {
printf("Unable to parse the /proc/cpuinfo. Are you running as root?");
spdlog::error(
"Unable to parse the /proc/cpuinfo. Are you running as root?");
SetValid(false);
} else {
SetValid(true);
while (fgets(buffer.data(), static_cast<int>(buffer.size()), pipe.get()) !=
nullptr) {
result += buffer.data();
}
// Remove trailing newline
size_t nl_position = result.find('\n');
if (nl_position != string::npos) {
result.erase(nl_position);
}
if (result.length() > 8) {
spdlog::warn("The revision code is too long. It may be truncated.");
SetValid(false);
}
if (result.length() < 6) {
spdlog::warn("The revision code is too short. It may be padded.");
SetValid(false);
}
rpi_revcode = strtol(result.c_str(), NULL, 16);
if (rpi_revcode == 0xFFFFFFFF) {
spdlog::warn(
"The revision code is invalid. This may be a hardware issue.");
SetValid(false);
}
if (!valid_rpi_version_type(Type())) {
spdlog::warn("Invalid CPU type detected {}. Please raise Github issue",
(uint32_t)Type());
SetValid(false);
}
if (!valid_memory_size_type(MemorySize())) {
spdlog::info("Invalid memory size detected {}. Please raise Github issue",
(uint8_t)MemorySize());
// The amount of memory available doesn't matter to PiSCSI
}
if (!valid_manufacturer_type(Manufacturer())) {
spdlog::info(
"Invalid manufacturer type detected {}. Please raise Github issue",
(uint8_t)Manufacturer());
// The manufacturer doesn't matter to PiSCSI
}
if (!valid_cpu_type(Processor())) {
spdlog::warn("Invalid CPU type detected {}. Please raise Github issue",
(uint8_t)Processor());
SetValid(false);
}
if (!IsValid()) {
string hex_rev_code = fmt::format("{:08X}", rpi_revcode);
spdlog::warn("Raspberry Pi Revision code is: {} result code: {}",
hex_rev_code.c_str(), result.c_str());
}
}
}
uint32_t Rpi_Revision_Code::extract_bits(int start_bit, int size) {
unsigned mask = ((1 << size) - 1) << start_bit;
return (rpi_revcode & mask) >> start_bit;
}

150
cpp/hal/rpi_revision_code.h Normal file
View File

@ -0,0 +1,150 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator PiSCSI
// for Raspberry Pi
//
// Copyright (C) 2024 akuker
//
// [ Detect Raspberry Pi version information ]
//
// The Raspberry Pi version detection is based upon the example code
// provided by the Raspberry Pi foundation:
// https://github.com/raspberrypi/documentation/blob/develop/documentation/asciidoc/computers/raspberry-pi/revision-codes.adoc
//
//---------------------------------------------------------------------------
#pragma once
#include <cstdint>
#include <stdio.h>
#include <string>
#include <type_traits>
using namespace std;
//===========================================================================
//
// Raspberry Pi Revision Information
//
// With the launch of the Raspberry Pi 2, new-style revision codes were
// introduced. Rather than being sequential, each bit of the hex code
// represents a piece of information about the revision.
//
//===========================================================================
class Rpi_Revision_Code {
public:
enum class memory_size_type : uint8_t {
MEM_256MB = 0,
MEM_512MB = 1,
MEM_1GB = 2,
MEM_2GB = 3,
MEM_4GB = 4,
MEM_8GB = 5,
MEM_INVALID = 0x7,
};
bool valid_memory_size_type(memory_size_type value) {
return (value >= memory_size_type::MEM_256MB &&
value <= memory_size_type::MEM_8GB);
}
enum class manufacturer_type : uint8_t {
SonyUK = 0,
Egoman = 1,
Embest2 = 2,
SonyJapan = 3,
Embest4 = 4,
Stadium = 5,
MANUFACTURER_INVALID = 0xF,
};
bool valid_manufacturer_type(manufacturer_type value) {
return (value >= manufacturer_type::SonyUK &&
value <= manufacturer_type::Stadium);
}
enum class cpu_type : uint8_t {
BCM2835 = 0,
BCM2836 = 1,
BCM2837 = 2,
BCM2711 = 3,
BCM2712 = 4,
CPU_TYPE_INVALID = 0xF,
};
bool valid_cpu_type(cpu_type value) {
return (value >= cpu_type::BCM2835 && value <= cpu_type::BCM2712);
}
enum class rpi_version_type : uint8_t {
rpi_version_A = 0,
rpi_version_B = 1,
rpi_version_Aplus = 2,
rpi_version_Bplus = 3,
rpi_version_2B = 4,
rpi_version_Alpha = 5, // (early prototype)
rpi_version_CM1 = 6,
rpi_version_3B = 8,
rpi_version_Zero = 9,
rpi_version_CM3 = 0xa,
rpi_version_ZeroW = 0xc,
rpi_version_3Bplus = 0xd,
rpi_version_3Aplus = 0xe,
rpi_version_InternalUseOnly1 = 0xf,
rpi_version_CM3plus = 0x10,
rpi_version_4B = 0x11,
rpi_version_Zero2W = 0x12,
rpi_version_400 = 0x13,
rpi_version_CM4 = 0x14,
rpi_version_CM4S = 0x15,
rpi_version_InternalUseOnly2 = 0x16,
rpi_version_5 = 0x17,
rpi_version_invalid = 0xFF
};
bool valid_rpi_version_type(rpi_version_type value) {
return (value >= rpi_version_type::rpi_version_A &&
value <= rpi_version_type::rpi_version_5);
}
public:
Rpi_Revision_Code(const std::string &cpuinfo_path = "/proc/cpuinfo");
Rpi_Revision_Code(uint32_t value) : rpi_revcode(value){};
~Rpi_Revision_Code() = default;
private:
uint32_t extract_bits(int start_bit, int size);
public:
uint8_t Revision() {
return (uint8_t)extract_bits(0, 4);
} //: 4; // (bits 0-3)
rpi_version_type Type() {
return (rpi_version_type)extract_bits(4, 8);
} //: // (bits 4-11)
cpu_type Processor() { return (cpu_type)extract_bits(12, 4); } // (bits 12-15)
manufacturer_type Manufacturer() {
return (manufacturer_type)extract_bits(16, 4);
} // (bits 16-19)
memory_size_type MemorySize() {
return (memory_size_type)extract_bits(20, 3);
} // (bits 20-22)
// 1: new-style revision
// 0: old-style revision
bool NewStyle() { return (bool)extract_bits(23, 1); } // (bit 23)
// 0: Warranty is intact
// 1: Warranty has been voided by overclocking
bool Waranty() { return (bool)extract_bits(25, 1); } // (bit 25)
// 0: OTP reading allowed
// 1: OTP reading disallowed
bool OtpRead() { return (bool)extract_bits(29, 1); } // (bit 29)
// 0: OTP programming allowed
// 1: OTP programming disallowed
bool OtpProgram() { return (bool)extract_bits(30, 1); } // (bit 30)
// 0: Overvoltage allowed
// 1: Overvoltage disallowed
bool Overvoltage() { return (bool)extract_bits(31, 3); } // (bit 31)
bool IsValid() { return is_valid; }
void SetValid(bool val) { is_valid = val; }
private:
uint32_t rpi_revcode;
bool is_valid = true;
};

View File

@ -18,10 +18,11 @@
SBC_Version::sbc_version_type SBC_Version::sbc_version = sbc_version_type::sbc_unknown;
// TODO: THESE NEED TO BE VALIDATED!!!!
const string SBC_Version::str_raspberry_pi_1 = "Raspberry Pi 1";
const string SBC_Version::str_raspberry_pi_2_3 = "Raspberry Pi 2/3";
const string SBC_Version::str_raspberry_pi_4 = "Raspberry Pi 4";
const string SBC_Version::str_unknown_sbc = "Unknown SBC";
const string SBC_Version::str_raspberry_pi_1 = "Raspberry Pi 1";
const string SBC_Version::str_raspberry_pi_2_3 = "Raspberry Pi 2/3";
const string SBC_Version::str_raspberry_pi_4 = "Raspberry Pi 4";
const string SBC_Version::str_raspberry_pi_5 = "Raspberry Pi 5";
const string SBC_Version::str_unknown_sbc = "Unknown SBC";
// The strings in this table should align with the 'model' embedded
// in the device tree. This can be aquired by running:
@ -39,8 +40,7 @@ const map<string, SBC_Version::sbc_version_type, less<>> SBC_Version::proc_devic
{"Raspberry Pi 4 Model ", sbc_version_type::sbc_raspberry_pi_4},
{"Raspberry Pi 400 ", sbc_version_type::sbc_raspberry_pi_4},
{"Raspberry Pi Zero W", sbc_version_type::sbc_raspberry_pi_1},
{"Raspberry Pi Zero", sbc_version_type::sbc_raspberry_pi_1}
};
{"Raspberry Pi Zero", sbc_version_type::sbc_raspberry_pi_1}};
const string SBC_Version::m_device_tree_model_path = "/proc/device-tree/model";
@ -51,13 +51,16 @@ const string SBC_Version::m_device_tree_model_path = "/proc/device-tree/model";
//---------------------------------------------------------------------------
string SBC_Version::GetAsString()
{
switch (sbc_version) {
switch (sbc_version)
{
case sbc_version_type::sbc_raspberry_pi_1:
return str_raspberry_pi_1;
case sbc_version_type::sbc_raspberry_pi_2_3:
return str_raspberry_pi_2_3;
case sbc_version_type::sbc_raspberry_pi_4:
return str_raspberry_pi_4;
case sbc_version_type::sbc_raspberry_pi_5:
return str_raspberry_pi_5;
default:
return str_unknown_sbc;
}
@ -78,10 +81,11 @@ void SBC_Version::Init()
{
ifstream input_stream(SBC_Version::m_device_tree_model_path);
if (input_stream.fail()) {
if (input_stream.fail())
{
#if defined(__x86_64__) || defined(__X86__)
// We expect this to fail on x86
spdlog::warn("Detected " + GetAsString());
spdlog::warn("Detected " + GetAsString());
sbc_version = sbc_version_type::sbc_unknown;
return;
#else
@ -94,12 +98,14 @@ void SBC_Version::Init()
str_buffer << input_stream.rdbuf();
const string device_tree_model = str_buffer.str();
for (const auto& [key, value] : proc_device_tree_mapping) {
if (device_tree_model.starts_with(key)) {
sbc_version = value;
spdlog::info("Detected " + GetAsString());
return;
}
for (const auto &[key, value] : proc_device_tree_mapping)
{
if (device_tree_model.starts_with(key))
{
sbc_version = value;
spdlog::info("Detected " + GetAsString());
return;
}
}
sbc_version = sbc_version_type::sbc_raspberry_pi_4;
@ -108,7 +114,8 @@ void SBC_Version::Init()
bool SBC_Version::IsRaspberryPi()
{
switch (sbc_version) {
switch (sbc_version)
{
case sbc_version_type::sbc_raspberry_pi_1:
case sbc_version_type::sbc_raspberry_pi_2_3:
case sbc_version_type::sbc_raspberry_pi_4:
@ -123,9 +130,11 @@ bool SBC_Version::IsRaspberryPi()
uint32_t SBC_Version::GetDeviceTreeRanges(const char *filename, uint32_t offset)
{
uint32_t address = ~0;
if (FILE *fp = fopen(filename, "rb"); fp) {
if (FILE *fp = fopen(filename, "rb"); fp)
{
fseek(fp, offset, SEEK_SET);
if (array<uint8_t, 4> buf; fread(buf.data(), 1, buf.size(), fp) == buf.size()) {
if (array<uint8_t, 4> buf; fread(buf.data(), 1, buf.size(), fp) == buf.size())
{
address = (int)buf[0] << 24 | (int)buf[1] << 16 | (int)buf[2] << 8 | (int)buf[3] << 0;
}
fclose(fp);
@ -137,7 +146,8 @@ uint32_t SBC_Version::GetDeviceTreeRanges(const char *filename, uint32_t offset)
uint32_t SBC_Version::GetPeripheralAddress(void)
{
uint32_t address = GetDeviceTreeRanges("/proc/device-tree/soc/ranges", 4);
if (address == 0) {
if (address == 0)
{
address = GetDeviceTreeRanges("/proc/device-tree/soc/ranges", 8);
}
address = (address == (uint32_t)~0) ? 0x20000000 : address;
@ -151,11 +161,14 @@ uint32_t SBC_Version::GetPeripheralAddress(void)
size_t len = sizeof(buf);
uint32_t address;
if (sysctlbyname("hw.model", buf, &len, NULL, 0) || strstr(buf, "ARM1176JZ-S") != buf) {
if (sysctlbyname("hw.model", buf, &len, NULL, 0) || strstr(buf, "ARM1176JZ-S") != buf)
{
// Failed to get CPU model || Not BCM2835
// use the address of BCM283[67]
address = 0x3f000000;
} else {
}
else
{
// Use BCM2835 address
address = 0x20000000;
}

View File

@ -24,39 +24,42 @@ using namespace std;
//===========================================================================
class SBC_Version
{
public:
// Type of Single Board Computer
enum class sbc_version_type : uint8_t {
sbc_unknown = 0,
sbc_raspberry_pi_1,
sbc_raspberry_pi_2_3,
sbc_raspberry_pi_4
};
public:
// Type of Single Board Computer
enum class sbc_version_type : uint8_t
{
sbc_unknown = 0,
sbc_raspberry_pi_1,
sbc_raspberry_pi_2_3,
sbc_raspberry_pi_4,
sbc_raspberry_pi_5
};
SBC_Version() = delete;
~SBC_Version() = delete;
SBC_Version() = delete;
~SBC_Version() = delete;
static void Init();
static void Init();
static sbc_version_type GetSbcVersion();
static sbc_version_type GetSbcVersion();
static bool IsRaspberryPi();
static bool IsRaspberryPi();
static string GetAsString();
static string GetAsString();
static uint32_t GetPeripheralAddress();
static uint32_t GetPeripheralAddress();
private:
static sbc_version_type sbc_version;
private:
static sbc_version_type sbc_version;
static const string str_raspberry_pi_1;
static const string str_raspberry_pi_2_3;
static const string str_raspberry_pi_4;
static const string str_unknown_sbc;
static const string str_raspberry_pi_1;
static const string str_raspberry_pi_2_3;
static const string str_raspberry_pi_4;
static const string str_raspberry_pi_5;
static const string str_unknown_sbc;
static const map<std::string, sbc_version_type, less<>> proc_device_tree_mapping;
static const map<std::string, sbc_version_type, less<>> proc_device_tree_mapping;
static const string m_device_tree_model_path;
static const string m_device_tree_model_path;
static uint32_t GetDeviceTreeRanges(const char *filename, uint32_t offset);
static uint32_t GetDeviceTreeRanges(const char *filename, uint32_t offset);
};

View File

@ -0,0 +1,836 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator PiSCSI
// for Raspberry Pi
//
// Copyright (C) 2024 akuker
//
//---------------------------------------------------------------------------
#include "hal/rpi_revision_code.h"
#include "mocks.h"
#include <cstdlib>
#include "test/test_shared.h"
#include <list>
#include <filesystem>
static string create_cpu_info(uint32_t revision)
{
std::stringstream cpuinfo_stream;
cpuinfo_stream << "Hardware : BCM";
cpuinfo_stream << GenerateRandomString(4);
cpuinfo_stream << "\nRevision : ";
cpuinfo_stream << std::hex << revision;
cpuinfo_stream << "\nSerial : ";
cpuinfo_stream << GenerateRandomString(32);
cpuinfo_stream << "\n";
// printf("CPU INFO:\n%s\n----", cpuinfo_stream.str().c_str());
return cpuinfo_stream.str();
}
typedef struct
{
uint32_t rev_code;
uint8_t revision;
Rpi_Revision_Code::rpi_version_type type;
Rpi_Revision_Code::cpu_type processor;
Rpi_Revision_Code::manufacturer_type manufacturer;
Rpi_Revision_Code::memory_size_type memorysize;
bool newstyle;
bool waranty;
bool otpread;
bool otpprogram;
bool overvoltage;
bool isvalid;
} rpi_revision_test_case;
std::list<rpi_revision_test_case> test_cases =
{
{
.rev_code = 0x900021,
.revision = 1,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_Aplus,
.processor = Rpi_Revision_Code::cpu_type::BCM2835,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_512MB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0x900032,
.revision = 2,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_Bplus,
.processor = Rpi_Revision_Code::cpu_type::BCM2835,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_512MB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0x900092,
.revision = 2,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_Zero,
.processor = Rpi_Revision_Code::cpu_type::BCM2835,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_512MB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0x900093,
.revision = 3,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_Zero,
.processor = Rpi_Revision_Code::cpu_type::BCM2835,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_512MB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0x9000c1,
.revision = 1,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_ZeroW,
.processor = Rpi_Revision_Code::cpu_type::BCM2835,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_512MB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0x9020e0,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_3Aplus,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_512MB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0x9020e1,
.revision = 1,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_3Aplus,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_512MB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0x920092,
.revision = 2,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_Zero,
.processor = Rpi_Revision_Code::cpu_type::BCM2835,
.manufacturer = Rpi_Revision_Code::manufacturer_type::Embest2,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_512MB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0x920093,
.revision = 3,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_Zero,
.processor = Rpi_Revision_Code::cpu_type::BCM2835,
.manufacturer = Rpi_Revision_Code::manufacturer_type::Embest2,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_512MB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0x900061,
.revision = 1,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_CM1,
.processor = Rpi_Revision_Code::cpu_type::BCM2835,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_512MB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa01040,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_2B,
.processor = Rpi_Revision_Code::cpu_type::BCM2836,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa01041,
.revision = 1,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_2B,
.processor = Rpi_Revision_Code::cpu_type::BCM2836,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa02082,
.revision = 2,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_3B,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa020a0,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_CM3,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa020d3,
.revision = 3,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_3Bplus,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa020d4,
.revision = 4,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_3Bplus,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa02042,
.revision = 2,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_2B,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa21041,
.revision = 1,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_2B,
.processor = Rpi_Revision_Code::cpu_type::BCM2836,
.manufacturer = Rpi_Revision_Code::manufacturer_type::Embest2,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa22042,
.revision = 2,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_2B,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::Embest2,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa22082,
.revision = 2,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_3B,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::Embest2,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa220a0,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_CM3,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::Embest2,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa32082,
.revision = 2,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_3B,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyJapan,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa52082,
.revision = 2,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_3B,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::Stadium,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa22083,
.revision = 3,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_3B,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::Embest2,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa02100,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_CM3plus,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa03111,
.revision = 1,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_4B,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xb03111,
.revision = 1,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_4B,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_2GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xb03112,
.revision = 2,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_4B,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_2GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xb03114,
.revision = 4,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_4B,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_2GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xb03115,
.revision = 5,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_4B,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_2GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xc03111,
.revision = 1,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_4B,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_4GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xc03112,
.revision = 2,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_4B,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_4GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xc03114,
.revision = 4,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_4B,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_4GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xc03115,
.revision = 5,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_4B,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_4GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xd03114,
.revision = 4,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_4B,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_8GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xd03115,
.revision = 5,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_4B,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_8GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xc03130,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_400,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_4GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xa03140,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_CM4,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_1GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xb03140,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_CM4,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_2GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xc03140,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_CM4,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_4GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xd03140,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_CM4,
.processor = Rpi_Revision_Code::cpu_type::BCM2711,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_8GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0x902120,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_Zero2W,
.processor = Rpi_Revision_Code::cpu_type::BCM2837,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_512MB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xc04170,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_5,
.processor = Rpi_Revision_Code::cpu_type::BCM2712,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_4GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
.rev_code = 0xd04170,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_5,
.processor = Rpi_Revision_Code::cpu_type::BCM2712,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_8GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
// Test Overvoltage flag
.rev_code = 0x80d04170,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_5,
.processor = Rpi_Revision_Code::cpu_type::BCM2712,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_8GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = true,
.isvalid = true,
},
{
// Test OTP Program flag
.rev_code = 0x40d04170,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_5,
.processor = Rpi_Revision_Code::cpu_type::BCM2712,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_8GB,
.newstyle = true,
.waranty = false,
.otpread = false,
.otpprogram = true,
.overvoltage = false,
.isvalid = true,
},
{
// Test OTP Read flag
.rev_code = 0x20d04170,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_5,
.processor = Rpi_Revision_Code::cpu_type::BCM2712,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_8GB,
.newstyle = true,
.waranty = false,
.otpread = true,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
// Test Waranty flag
.rev_code = 0x02d04170,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_5,
.processor = Rpi_Revision_Code::cpu_type::BCM2712,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_8GB,
.newstyle = true,
.waranty = true,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
// Test New Style
.rev_code = 0x00504170,
.revision = 0,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_5,
.processor = Rpi_Revision_Code::cpu_type::BCM2712,
.manufacturer = Rpi_Revision_Code::manufacturer_type::SonyUK,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_8GB,
.newstyle = false,
.waranty = false,
.otpread = false,
.otpprogram = false,
.overvoltage = false,
.isvalid = true,
},
{
// Invalid Test
.rev_code = 0xFFFFFFFF,
.revision = 0xF,
.type = Rpi_Revision_Code::rpi_version_type::rpi_version_invalid,
.processor = Rpi_Revision_Code::cpu_type::CPU_TYPE_INVALID,
.manufacturer = Rpi_Revision_Code::manufacturer_type::MANUFACTURER_INVALID,
.memorysize = Rpi_Revision_Code::memory_size_type::MEM_INVALID,
.newstyle = true,
.waranty = true,
.otpread = true,
.otpprogram = true,
.overvoltage = true,
.isvalid = false,
},
};
TEST(RpiRevisionCode, Initialization)
{
const string cpuinfo_file = "/proc/cpuinfo";
for (rpi_revision_test_case tc : test_cases)
{
// debug
// printf("Test case: %x\n", tc.rev_code);
string cpuinfo_str = create_cpu_info(tc.rev_code);
path cpuinfo_path = CreateTempFileWithString(cpuinfo_file, cpuinfo_str);
unique_ptr<Rpi_Revision_Code> rpi_info(new Rpi_Revision_Code(cpuinfo_path.string()));
EXPECT_EQ(rpi_info->Revision(), tc.revision);
EXPECT_EQ(rpi_info->Type(), tc.type);
EXPECT_EQ(rpi_info->Processor(), tc.processor);
EXPECT_EQ(rpi_info->Manufacturer(), tc.manufacturer);
EXPECT_EQ(rpi_info->MemorySize(), tc.memorysize);
EXPECT_EQ(rpi_info->NewStyle(), tc.newstyle);
EXPECT_EQ(rpi_info->Waranty(), tc.waranty);
EXPECT_EQ(rpi_info->OtpRead(), tc.otpread);
EXPECT_EQ(rpi_info->OtpProgram(), tc.otpprogram);
EXPECT_EQ(rpi_info->Overvoltage(), tc.overvoltage);
EXPECT_EQ(rpi_info->IsValid(), tc.isvalid);
DeleteTempFile(cpuinfo_file);
}
}

View File

@ -16,6 +16,8 @@
#include <sstream>
#include <unistd.h>
#include <vector>
#include <string>
#include <random>
using namespace std;
using namespace filesystem;
@ -26,40 +28,43 @@ const path test_data_temp_path(temp_directory_path() /
path(fmt::format("piscsi-test-{}",
getpid()))); // NOSONAR Publicly writable directory is fine here
pair<shared_ptr<MockAbstractController>, shared_ptr<PrimaryDevice>> CreateDevice(PbDeviceType type, const string& extension)
pair<shared_ptr<MockAbstractController>, shared_ptr<PrimaryDevice>> CreateDevice(PbDeviceType type, const string &extension)
{
DeviceFactory device_factory;
auto controller = make_shared<NiceMock<MockAbstractController>>(0);
auto controller = make_shared<NiceMock<MockAbstractController>>(0);
auto device = device_factory.CreateDevice(type, 0, extension);
device->Init({});
EXPECT_TRUE(controller->AddDevice(device));
return { controller, device };
return {controller, device};
}
void TestInquiry::Inquiry(PbDeviceType type, device_type t, scsi_level l, const string& ident, int additional_length,
bool removable, const string& extension)
void TestInquiry::Inquiry(PbDeviceType type, device_type t, scsi_level l, const string &ident, int additional_length,
bool removable, const string &extension)
{
auto [controller, device] = CreateDevice(type, extension);
// ALLOCATION LENGTH
controller->SetCmdByte(4, 255);
controller->SetCmdByte(4, 255);
EXPECT_CALL(*controller, DataIn());
device->Dispatch(scsi_command::eCmdInquiry);
const vector<uint8_t>& buffer = controller->GetBuffer();
const vector<uint8_t> &buffer = controller->GetBuffer();
EXPECT_EQ(t, static_cast<device_type>(buffer[0]));
EXPECT_EQ(removable ? 0x80 : 0x00, buffer[1]);
EXPECT_EQ(l, static_cast<scsi_level>(buffer[2]));
EXPECT_EQ(l > scsi_level::scsi_2 ? scsi_level::scsi_2 : l, static_cast<scsi_level>(buffer[3]));
EXPECT_EQ(additional_length, buffer[4]);
string product_data;
if (ident.size() == 24) {
if (ident.size() == 24)
{
ostringstream s;
s << ident << setw(2) << setfill('0') << piscsi_major_version << setw(2) << piscsi_minor_version;
product_data = s.str();
} else {
}
else
{
product_data = ident;
}
EXPECT_TRUE(!memcmp(product_data.c_str(), &buffer[8], 28));
@ -82,8 +87,8 @@ pair<int, path> OpenTempFile()
path CreateTempFile(int size)
{
const auto data = vector<byte>(size);
return CreateTempFileWithData(data);
const auto data = vector<byte>(size);
return CreateTempFileWithData(data);
}
path CreateTempFileWithData(const span<const byte> data)
@ -99,36 +104,52 @@ path CreateTempFileWithData(const span<const byte> data)
// TODO Replace old-fashinoned C I/O by C++ streams I/O.
// This also avoids potential issues with data type sizes and there is no need for c_str().
void CreateTempFileWithData(const string& filename, vector<uint8_t>& data)
void CreateTempFileWithData(const string &filename, vector<uint8_t> &data)
{
path new_filename = test_data_temp_path;
new_filename += path(filename);
create_directories(new_filename.parent_path());
FILE* fp = fopen(new_filename.c_str(), "wb");
if (fp == nullptr) {
FILE *fp = fopen(new_filename.c_str(), "wb");
if (fp == nullptr)
{
cerr << "ERROR: Unable to open file '" << new_filename << "'";
return;
}
if (const size_t size_written = fwrite(&data[0], sizeof(uint8_t), data.size(), fp);
size_written != sizeof(vector<uint8_t>::value_type) * data.size()) {
cerr << "ERROR: Expected to write " << sizeof(vector<uint8_t>::value_type) * data.size() << " bytes"
<< ", but only wrote " << data.size() << " to '" << filename << "'";
size_written != sizeof(vector<uint8_t>::value_type) * data.size())
{
cerr << "ERROR: Expected to write " << sizeof(vector<uint8_t>::value_type) * data.size() << " bytes"
<< ", but only wrote " << data.size() << " to '" << filename << "'";
}
fclose(fp);
}
// TODO Move this code, it is not shared
void DeleteTempFile(const string& filename)
path CreateTempFileWithString(const string &filename, const string &data)
{
path temp_file = test_data_temp_path;
temp_file += path(filename);
remove(temp_file);
path new_filename = test_data_temp_path;
new_filename += path(filename);
// printf("XXXXXXX Creating file '%s' with \n'%s'\n", new_filename.c_str(), data.c_str());
create_directories(new_filename.parent_path());
std::ofstream out(new_filename);
out << data;
out.close();
return path(new_filename);
}
string ReadTempFileToString(const string& filename)
// TODO Move this code, it is not shared
void DeleteTempFile(const string &filename)
{
path temp_file = test_data_temp_path;
temp_file += path(filename);
remove(temp_file);
}
string ReadTempFileToString(const string &filename)
{
const path temp_file = test_data_temp_path / path(filename);
ifstream in(temp_file);
@ -138,17 +159,33 @@ string ReadTempFileToString(const string& filename)
return buffer.str();
}
int GetInt16(const vector<byte>& buf, int offset)
int GetInt16(const vector<byte> &buf, int offset)
{
assert(buf.size() > static_cast<size_t>(offset) + 1);
return (to_integer<int>(buf[offset]) << 8) | to_integer<int>(buf[offset + 1]);
}
uint32_t GetInt32(const vector<byte>& buf, int offset)
uint32_t GetInt32(const vector<byte> &buf, int offset)
{
assert(buf.size() > static_cast<size_t>(offset) + 3);
return (to_integer<uint32_t>(buf[offset]) << 24) | (to_integer<uint32_t>(buf[offset + 1]) << 16) |
(to_integer<uint32_t>(buf[offset + 2]) << 8) | to_integer<uint32_t>(buf[offset + 3]);
}
std::string GenerateRandomString(int length)
{
static const std::string characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, static_cast<int>(characters.size() - 1));
std::string result;
result.reserve(length);
for (int i = 0; i < length; ++i)
{
result += characters[dis(gen)];
}
return result;
}

View File

@ -25,25 +25,29 @@ class MockAbstractController;
extern const path test_data_temp_path;
pair<shared_ptr<MockAbstractController>, shared_ptr<PrimaryDevice>> CreateDevice(PbDeviceType, const string& = "");
pair<shared_ptr<MockAbstractController>, shared_ptr<PrimaryDevice>> CreateDevice(PbDeviceType, const string & = "");
pair<int, path> OpenTempFile();
path CreateTempFile(int);
path CreateTempFileWithData(span<const byte>);
// create a file with the specified data
void CreateTempFileWithData(const string&, vector<uint8_t>&);
void CreateTempFileWithData(const string &, vector<uint8_t> &);
path CreateTempFileWithString(const string &filename, const string &data);
void DeleteTempFile(const string&);
void DeleteTempFile(const string &);
string ReadTempFileToString(const string& filename);
string ReadTempFileToString(const string &filename);
int GetInt16(const vector<byte>&, int);
uint32_t GetInt32(const vector<byte>&, int);
int GetInt16(const vector<byte> &, int);
uint32_t GetInt32(const vector<byte> &, int);
std::string GenerateRandomString(int);
// This class is needed in order to be declared as friend, required to have access to AbstractController::SetCmdByte
class TestInquiry {
class TestInquiry
{
public:
static void Inquiry(PbDeviceType, scsi_defs::device_type, scsi_defs::scsi_level, const string&, int, bool,
const string& = "");
static void Inquiry(PbDeviceType, scsi_defs::device_type, scsi_defs::scsi_level, const string &, int, bool,
const string & = "");
};