scsihd: fix READ_CAPACITY_10 command.

Also bump internal buffer size to 2 MB
to temporarily fix buffer overflows.
This commit is contained in:
Maxim Poliakovski 2022-12-14 16:14:37 +01:00
parent dee225ee8f
commit a189c94980
6 changed files with 35 additions and 14 deletions

View File

@ -22,6 +22,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
/** @file ATA hard disk emulation. */
#include <devices/common/ata/atahd.h>
#include <cstring>
#include <sys/stat.h>
#include <fstream>
#include <string>
@ -99,7 +101,7 @@ int AtaHardDisk::perform_command()
}
case IDENTIFY_DEVICE: {
this->r_status |= DRQ;
memcpy(buffer, ide_hd_id, 512);
std::memcpy(buffer, ide_hd_id, 512);
this->r_status &= ~(DRQ);
break;
}

View File

@ -83,7 +83,7 @@ private:
int bytes_out = 0;
TrackDescriptor tracks[CDROM_MAX_TRACKS];
char data_buf[1 << 16]; // TODO: proper buffer management
char data_buf[1 << 18]; // TODO: proper buffer management
};
#endif // SCSI_CDROM_H

View File

@ -24,6 +24,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <loguru.hpp>
#include <cinttypes>
#include <cstring>
void ScsiDevice::notify(ScsiBus* bus_obj, ScsiMsg msg_type, int param)
{

View File

@ -22,11 +22,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
/** @file Generic SCSI Hard Disk emulation. */
#include <devices/common/scsi/scsi.h>
#include <devices/common/scsi/scsi_hd.h>
#include <devices/common/scsi/scsihd.h>
#include <devices/deviceregistry.h>
#include <loguru.hpp>
#include <machines/machinebase.h>
#include <machines/machineproperties.h>
#include <loguru.hpp>
#include <memaccess.h>
#include <fstream>
#include <cstring>
@ -50,6 +51,7 @@ void ScsiHardDisk::insert_image(std::string filename) {
int rc = stat(filename.c_str(), &stat_buf);
if (!rc) {
this->img_size = stat_buf.st_size;
this->total_blocks = (this->img_size + HDD_SECTOR_SIZE - 1) / HDD_SECTOR_SIZE;
} else {
ABORT_F("ScsiHardDisk: could not determine file size using stat()");
}
@ -73,7 +75,8 @@ void ScsiHardDisk::process_command() {
uint8_t* cmd = this->cmd_buf;
if (cmd[0] != 0 && cmd[0] != 8 && cmd[0] != 0xA && cmd[0] != 0x28 && cmd[0] != 0x2A) {
if (cmd[0] != 0 && cmd[0] != 8 && cmd[0] != 0xA && cmd[0] != 0x28
&& cmd[0] != 0x2A && cmd[0] != 0x25) {
ABORT_F("SCSI-HD: untested command 0x%X", cmd[0]);
}
@ -214,16 +217,30 @@ void ScsiHardDisk::mode_sense_6(uint8_t page_code, uint8_t subpage_code, uint8_t
}
void ScsiHardDisk::read_capacity_10() {
uint32_t sec_limit = (this->img_size >> 9);
uint32_t lba = READ_DWORD_BE_U(&this->cmd_buf[2]);
std::memset(img_buffer, 0, sizeof(img_buffer));
if (this->cmd_buf[1] & 1) {
ABORT_F("SCSI-HD: RelAdr bit set in READ_CAPACITY_10");
}
img_buffer[0] = (sec_limit >> 24) & 0xFF;
img_buffer[1] = (sec_limit >> 16) & 0xFF;
img_buffer[2] = (sec_limit >> 8) & 0xFF;
img_buffer[3] = sec_limit & 0xFF;
if (!(this->cmd_buf[8] & 1) && lba) {
LOG_F(ERROR, "SCSI-HD: non-zero LBA for PMI=0");
this->status = ScsiStatus::CHECK_CONDITION;
this->sense = ScsiSense::ILLEGAL_REQ;
this->switch_phase(ScsiPhase::STATUS);
return;
}
img_buffer[6] = 2;
uint32_t last_lba = this->total_blocks - 1;
uint32_t blk_len = HDD_SECTOR_SIZE;
WRITE_DWORD_BE_A(&img_buffer[0], last_lba);
WRITE_DWORD_BE_A(&img_buffer[4], blk_len);
this->cur_buf_cnt = 8;
this->msg_buf[0] = ScsiMessage::COMMAND_COMPLETE;
this->switch_phase(ScsiPhase::DATA_IN);
}

View File

@ -63,9 +63,10 @@ protected:
private:
std::fstream hdd_img;
uint64_t img_size;
int total_blocks;
uint64_t file_offset = 0;
char img_buffer[1 << 17]; // TODO: add proper buffer management!
char img_buffer[1 << 21]; // TODO: add proper buffer management!
uint32_t cur_buf_cnt = 0;
uint8_t error = ScsiError::NO_ERROR;

View File

@ -28,7 +28,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <devices/common/machineid.h>
#include <devices/common/scsi/scsi.h>
#include <devices/common/scsi/scsicdrom.h>
#include <devices/common/scsi/scsi_hd.h>
#include <devices/common/scsi/scsihd.h>
#include <devices/memctrl/hmc.h>
#include <loguru.hpp>
#include <machines/machinebase.h>