From 839bc0c00963e3655f824f62e8bc6ba9d3bbc3c0 Mon Sep 17 00:00:00 2001 From: Tony Kuker Date: Tue, 28 May 2024 03:12:35 +0000 Subject: [PATCH] #1226 - Detection of Rpi version checking refactor --- cpp/.clangformat | 13 + cpp/hal/rpi_revision_code.cpp | 100 ++++ cpp/hal/rpi_revision_code.h | 150 +++++ cpp/hal/sbc_version.cpp | 55 +- cpp/hal/sbc_version.h | 51 +- cpp/test/rpi_revision_code_test.cpp | 836 ++++++++++++++++++++++++++++ cpp/test/test_shared.cpp | 87 ++- cpp/test/test_shared.h | 22 +- 8 files changed, 1235 insertions(+), 79 deletions(-) create mode 100644 cpp/.clangformat create mode 100644 cpp/hal/rpi_revision_code.cpp create mode 100644 cpp/hal/rpi_revision_code.h create mode 100644 cpp/test/rpi_revision_code_test.cpp diff --git a/cpp/.clangformat b/cpp/.clangformat new file mode 100644 index 00000000..003462ac --- /dev/null +++ b/cpp/.clangformat @@ -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 + diff --git a/cpp/hal/rpi_revision_code.cpp b/cpp/hal/rpi_revision_code.cpp new file mode 100644 index 00000000..439ec07e --- /dev/null +++ b/cpp/hal/rpi_revision_code.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +Rpi_Revision_Code::Rpi_Revision_Code(const string &cpuinfo_path) { + std::string cmd = "cat " + cpuinfo_path + "| awk '/Revision/ {print $3}'"; + + std::array buffer; + std::string result; + std::unique_ptr 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(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; +} \ No newline at end of file diff --git a/cpp/hal/rpi_revision_code.h b/cpp/hal/rpi_revision_code.h new file mode 100644 index 00000000..ab0e26dd --- /dev/null +++ b/cpp/hal/rpi_revision_code.h @@ -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 +#include +#include +#include + +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; +}; diff --git a/cpp/hal/sbc_version.cpp b/cpp/hal/sbc_version.cpp index cd334ad3..d35a7e62 100644 --- a/cpp/hal/sbc_version.cpp +++ b/cpp/hal/sbc_version.cpp @@ -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> 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 buf; fread(buf.data(), 1, buf.size(), fp) == buf.size()) { + if (array 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; } diff --git a/cpp/hal/sbc_version.h b/cpp/hal/sbc_version.h index c51100e4..4b8b870e 100644 --- a/cpp/hal/sbc_version.h +++ b/cpp/hal/sbc_version.h @@ -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> proc_device_tree_mapping; + static const map> 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); }; diff --git a/cpp/test/rpi_revision_code_test.cpp b/cpp/test/rpi_revision_code_test.cpp new file mode 100644 index 00000000..23ef616a --- /dev/null +++ b/cpp/test/rpi_revision_code_test.cpp @@ -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 +#include "test/test_shared.h" +#include +#include + +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 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_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); + } +} diff --git a/cpp/test/test_shared.cpp b/cpp/test/test_shared.cpp index 3ab8ad29..22194e93 100644 --- a/cpp/test/test_shared.cpp +++ b/cpp/test/test_shared.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include 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> CreateDevice(PbDeviceType type, const string& extension) +pair, shared_ptr> CreateDevice(PbDeviceType type, const string &extension) { DeviceFactory device_factory; - auto controller = make_shared>(0); + auto controller = make_shared>(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& buffer = controller->GetBuffer(); + const vector &buffer = controller->GetBuffer(); EXPECT_EQ(t, static_cast(buffer[0])); EXPECT_EQ(removable ? 0x80 : 0x00, buffer[1]); EXPECT_EQ(l, static_cast(buffer[2])); EXPECT_EQ(l > scsi_level::scsi_2 ? scsi_level::scsi_2 : l, static_cast(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 OpenTempFile() path CreateTempFile(int size) { - const auto data = vector(size); - return CreateTempFileWithData(data); + const auto data = vector(size); + return CreateTempFileWithData(data); } path CreateTempFileWithData(const span data) @@ -99,36 +104,52 @@ path CreateTempFileWithData(const span 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& data) +void CreateTempFileWithData(const string &filename, vector &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::value_type) * data.size()) { - cerr << "ERROR: Expected to write " << sizeof(vector::value_type) * data.size() << " bytes" - << ", but only wrote " << data.size() << " to '" << filename << "'"; + size_written != sizeof(vector::value_type) * data.size()) + { + cerr << "ERROR: Expected to write " << sizeof(vector::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& buf, int offset) +int GetInt16(const vector &buf, int offset) { assert(buf.size() > static_cast(offset) + 1); return (to_integer(buf[offset]) << 8) | to_integer(buf[offset + 1]); } -uint32_t GetInt32(const vector& buf, int offset) +uint32_t GetInt32(const vector &buf, int offset) { assert(buf.size() > static_cast(offset) + 3); return (to_integer(buf[offset]) << 24) | (to_integer(buf[offset + 1]) << 16) | (to_integer(buf[offset + 2]) << 8) | to_integer(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(characters.size() - 1)); + + std::string result; + result.reserve(length); + for (int i = 0; i < length; ++i) + { + result += characters[dis(gen)]; + } + return result; +} \ No newline at end of file diff --git a/cpp/test/test_shared.h b/cpp/test/test_shared.h index 8c87f294..8cf32c9f 100644 --- a/cpp/test/test_shared.h +++ b/cpp/test/test_shared.h @@ -25,25 +25,29 @@ class MockAbstractController; extern const path test_data_temp_path; -pair, shared_ptr> CreateDevice(PbDeviceType, const string& = ""); +pair, shared_ptr> CreateDevice(PbDeviceType, const string & = ""); pair OpenTempFile(); path CreateTempFile(int); path CreateTempFileWithData(span); // create a file with the specified data -void CreateTempFileWithData(const string&, vector&); +void CreateTempFileWithData(const string &, vector &); +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&, int); -uint32_t GetInt32(const vector&, int); +int GetInt16(const vector &, int); +uint32_t GetInt32(const vector &, 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 & = ""); };