mirror of
https://github.com/akuker/RASCSI.git
synced 2026-10-25 12:02:59 +00:00
Validate that the declared MODE SELECT parameter list fits in the transfer buffer and contains a complete command header. Validate the block-descriptor list against the remaining parameter-list length before skipping it. Reject truncated mode-page headers and page bodies before reading them. Report ILLEGAL REQUEST / PARAMETER LIST LENGTH ERROR for truncated headers, block descriptors, and mode pages, as required by SCSI-2 8.2.8; retain INVALID FIELD IN PARAMETER LIST for complete but invalid fields. Update the hard-disk and magneto-optical fixtures to send complete Format Device pages with their actual MODE SELECT parameter-list lengths. Add regression coverage for truncated headers, descriptors, page headers, and page bodies.
133 lines
3.4 KiB
C++
133 lines
3.4 KiB
C++
//---------------------------------------------------------------------------
|
|
//
|
|
// SCSI Target Emulator PiSCSI
|
|
// for Raspberry Pi
|
|
//
|
|
// Copyright (C) 2022-2023 Uwe Seimet
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "mocks.h"
|
|
#include "shared/piscsi_exceptions.h"
|
|
#include "devices/scsihd.h"
|
|
|
|
void ScsiHdTest_SetUpModePages(map<int, vector<byte>>& pages)
|
|
{
|
|
EXPECT_EQ(5, pages.size()) << "Unexpected number of mode pages";
|
|
EXPECT_EQ(12, pages[1].size());
|
|
EXPECT_EQ(24, pages[3].size());
|
|
EXPECT_EQ(24, pages[4].size());
|
|
EXPECT_EQ(12, pages[8].size());
|
|
EXPECT_EQ(30, pages[48].size());
|
|
}
|
|
|
|
TEST(ScsiHdTest, Inquiry)
|
|
{
|
|
TestInquiry::Inquiry(SCHD, device_type::direct_access, scsi_level::scsi_2, "PiSCSI ", 0x1f, false);
|
|
|
|
TestInquiry::Inquiry(SCHD, device_type::direct_access, scsi_level::scsi_1_ccs, "PiSCSI ", 0x1f, false, "file.hd1");
|
|
}
|
|
|
|
TEST(ScsiHdTest, SupportsSaveParameters)
|
|
{
|
|
MockSCSIHD hd(0, false);
|
|
|
|
EXPECT_TRUE(hd.SupportsSaveParameters());
|
|
}
|
|
|
|
TEST(ScsiHdTest, FinalizeSetup)
|
|
{
|
|
MockSCSIHD hd(0, false);
|
|
|
|
hd.SetSectorSizeInBytes(1024);
|
|
EXPECT_THROW(hd.FinalizeSetup(0), io_exception) << "Device has 0 blocks";
|
|
}
|
|
|
|
TEST(ScsiHdTest, GetProductData)
|
|
{
|
|
MockSCSIHD hd_kb(0, false);
|
|
MockSCSIHD hd_mb(0, false);
|
|
MockSCSIHD hd_gb(0, false);
|
|
|
|
const path filename = CreateTempFile(1);
|
|
hd_kb.SetFilename(string(filename));
|
|
hd_kb.SetSectorSizeInBytes(1024);
|
|
hd_kb.SetBlockCount(1);
|
|
hd_kb.FinalizeSetup(0);
|
|
string s = hd_kb.GetProduct();
|
|
EXPECT_NE(string::npos, s.find("1 KiB"));
|
|
|
|
hd_mb.SetFilename(string(filename));
|
|
hd_mb.SetSectorSizeInBytes(1024);
|
|
hd_mb.SetBlockCount(1'048'576 / 1024);
|
|
hd_mb.FinalizeSetup(0);
|
|
s = hd_mb.GetProduct();
|
|
EXPECT_NE(string::npos, s.find("1 MiB"));
|
|
|
|
hd_gb.SetFilename(string(filename));
|
|
hd_gb.SetSectorSizeInBytes(1024);
|
|
hd_gb.SetBlockCount(10'737'418'240 / 1024);
|
|
hd_gb.FinalizeSetup(0);
|
|
s = hd_gb.GetProduct();
|
|
EXPECT_NE(string::npos, s.find("10 GiB"));
|
|
remove(filename);
|
|
}
|
|
|
|
TEST(ScsiHdTest, GetSectorSizes)
|
|
{
|
|
MockSCSIHD hd(0, false);
|
|
|
|
const auto& sector_sizes = hd.GetSupportedSectorSizes();
|
|
EXPECT_EQ(4, sector_sizes.size());
|
|
|
|
EXPECT_TRUE(sector_sizes.contains(512));
|
|
EXPECT_TRUE(sector_sizes.contains(1024));
|
|
EXPECT_TRUE(sector_sizes.contains(2048));
|
|
EXPECT_TRUE(sector_sizes.contains(4096));
|
|
}
|
|
|
|
TEST(ScsiHdTest, SetUpModePages)
|
|
{
|
|
map<int, vector<byte>> pages;
|
|
MockSCSIHD hd(0, false);
|
|
|
|
// Non changeable
|
|
hd.SetUpModePages(pages, 0x3f, false);
|
|
ScsiHdTest_SetUpModePages(pages);
|
|
|
|
// Changeable
|
|
pages.clear();
|
|
hd.SetUpModePages(pages, 0x3f, true);
|
|
ScsiHdTest_SetUpModePages(pages);
|
|
}
|
|
|
|
TEST(ScsiHdTest, ModeSelect)
|
|
{
|
|
MockSCSIHD hd({ 512 });
|
|
vector<int> cmd(10);
|
|
vector<uint8_t> buf(32);
|
|
|
|
hd.SetSectorSizeInBytes(512);
|
|
|
|
// PF
|
|
cmd[1] = 0x10;
|
|
// Page 3 (Device Format Page)
|
|
buf[4] = 0x03;
|
|
// 22 bytes (standard format page length)
|
|
buf[5] = 0x16;
|
|
// 512 bytes per sector (offset 12 from page start = offset 16 from buffer start)
|
|
buf[16] = 0x02;
|
|
EXPECT_NO_THROW(hd.ModeSelect(scsi_command::eCmdModeSelect6, cmd, buf, 28)) << "MODE SELECT(6) is supported";
|
|
buf[4] = 0;
|
|
buf[5] = 0;
|
|
buf[16] = 0;
|
|
|
|
// Page 3 (Device Format Page)
|
|
buf[8] = 0x03;
|
|
// 22 bytes (standard format page length)
|
|
buf[9] = 0x16;
|
|
// 512 bytes per sector (offset 12 from page start = offset 20 from buffer start)
|
|
buf[20] = 0x02;
|
|
EXPECT_NO_THROW(hd.ModeSelect(scsi_command::eCmdModeSelect10, cmd, buf, 32)) << "MODE SELECT(10) is supported";
|
|
}
|