usbdrv Read from USB flash drive
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
iso_root
|
||||
img_root
|
||||
mop3.iso
|
||||
bochs-log.txt
|
||||
bochs-com1.txt
|
||||
|
||||
30
aux/limine_img_amd64.sh
Executable file
30
aux/limine_img_amd64.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
|
||||
make -C boot/limine
|
||||
rm -rf img_root
|
||||
mkdir -p img_root/boot/limine
|
||||
mkdir -p img_root/EFI/BOOT
|
||||
|
||||
cp -v kernel/build/kernel.elf img_root/boot/
|
||||
cp -v boot/limine/limine-bios.sys boot/limine/limine.conf img_root/boot/limine/
|
||||
cp -v boot/limine/limine-bios-cd.bin boot/limine/limine-uefi-cd.bin img_root/boot/limine/
|
||||
cp -v boot/limine/BOOTX64.EFI boot/limine/BOOTIA32.EFI img_root/EFI/BOOT/
|
||||
cp -v mop3dist.tar.lz4 img_root/boot/
|
||||
|
||||
dd if=/dev/zero of=mop3.img bs=1M count=64
|
||||
|
||||
parted -s mop3.img mklabel msdos mkpart primary fat32 1MiB 100% set 1 boot on
|
||||
|
||||
LOOPDEV=$(sudo losetup -Pf --show mop3.img)
|
||||
sudo mkfs.fat -F 32 ${LOOPDEV}p1
|
||||
|
||||
mkdir -p mnt
|
||||
sudo mount ${LOOPDEV}p1 mnt
|
||||
|
||||
sudo cp -rv img_root/* mnt/
|
||||
|
||||
sudo umount mnt
|
||||
sudo losetup -d $LOOPDEV
|
||||
rmdir mnt
|
||||
|
||||
boot/limine/limine bios-install mop3.img
|
||||
19
aux/write_img.sh
Executable file
19
aux/write_img.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Requires sudo
|
||||
# USAGE: ./aux/write_img.sh /dev/sda
|
||||
|
||||
TARGET="$1"
|
||||
|
||||
if [ -z "$TARGET" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -b "$TARGET" ]; then
|
||||
echo "Not a block device"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -x
|
||||
|
||||
dd if=./mop3.img of="$TARGET" bs=4M status=progress oflag=direct conv=notrunc,sync && sync
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <device/storage/usbdrv.h>
|
||||
#include <device/usb/xhci.h>
|
||||
#include <devices.h>
|
||||
#include <libk/align.h>
|
||||
#include <libk/endianess.h>
|
||||
#include <libk/string.h>
|
||||
#include <limine/requests.h>
|
||||
@@ -14,7 +15,10 @@
|
||||
#include <sys/debug.h>
|
||||
#include <sys/stall.h>
|
||||
|
||||
/* REF: https://en.wikipedia.org/wiki/SCSI */
|
||||
/* REF:
|
||||
* https://en.wikipedia.org/wiki/SCSI
|
||||
* https://www.seagate.com/files/staticfiles/support/docs/manual/Interface%20manuals/100293068j.pdf
|
||||
*/
|
||||
|
||||
static int usb_ms_send_cbw (struct xhci* xhci, struct xhci_usb_device* usb_device,
|
||||
uint8_t bulk_out_endpoint, uintptr_t cbw_phys, uint64_t* lockflags) {
|
||||
@@ -147,6 +151,79 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usb_ms_scsi_read (struct xhci* xhci, struct xhci_usb_device* usb_device,
|
||||
uint8_t bulk_in_endpoint, uint8_t bulk_out_endpoint,
|
||||
uint8_t* out_buffer, uint32_t lba, uint16_t sector_count,
|
||||
size_t sector_size, uint64_t* lockflags) {
|
||||
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||
int ret;
|
||||
|
||||
uintptr_t cbw_phys = pmm_alloc (1);
|
||||
struct usb_ms_cbw* cbw = (struct usb_ms_cbw*)(cbw_phys + (uintptr_t)hhdm->offset);
|
||||
memset (cbw, 0, PAGE_SIZE);
|
||||
|
||||
size_t data_pages = div_align_up (sector_count * sector_size, PAGE_SIZE);
|
||||
uintptr_t data_phys = pmm_alloc (data_pages);
|
||||
uint8_t* data = (uint8_t*)(data_phys + (uintptr_t)hhdm->offset);
|
||||
memset (data, 0, PAGE_SIZE * data_pages);
|
||||
|
||||
uintptr_t csw_phys = pmm_alloc (1);
|
||||
struct usb_ms_csw* csw = (struct usb_ms_csw*)(csw_phys + (uintptr_t)hhdm->offset);
|
||||
memset (csw, 0, PAGE_SIZE);
|
||||
|
||||
uint8_t cdb[10] = {
|
||||
0x28,
|
||||
0x00,
|
||||
/* LBA */
|
||||
(uint8_t)((lba & 0xFF000000) >> 24),
|
||||
(uint8_t)((lba & 0x00FF0000) >> 16),
|
||||
(uint8_t)((lba & 0x0000FF00) >> 8),
|
||||
(uint8_t)((lba & 0xFF)),
|
||||
0x00,
|
||||
/* Transfer Length */
|
||||
(uint8_t)((sector_count & 0xFF00) >> 8),
|
||||
(uint8_t)((sector_count & 0x00FF)),
|
||||
0x00,
|
||||
};
|
||||
|
||||
cbw->signature = USB_CBW_SIGNATURE;
|
||||
cbw->tag = 0x12345678;
|
||||
cbw->dir = 0x80;
|
||||
cbw->lun = 0;
|
||||
cbw->cmd_len = sizeof (cdb);
|
||||
cbw->length = sector_count * sector_size;
|
||||
memcpy (cbw->data, cdb, sizeof (cdb));
|
||||
|
||||
if ((ret = usb_ms_send_cbw (xhci, usb_device, bulk_out_endpoint, cbw_phys, lockflags)) < 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((ret = usb_ms_read_data (xhci, usb_device, bulk_in_endpoint, data_phys,
|
||||
sector_count * sector_size, lockflags)) < 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((ret = usb_ms_read_csw (xhci, usb_device, bulk_in_endpoint, csw_phys, lockflags)) < 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (csw->status != 0 || csw->signature != USB_CSW_SIGNATURE) {
|
||||
DEBUG ("Failed to read sectors. CSW status=%u residue=%u\n", csw->status, csw->residue);
|
||||
ret = -ST_USB_CTRL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
memcpy (out_buffer, data, sector_count * sector_size);
|
||||
|
||||
ret = ST_OK;
|
||||
|
||||
done:
|
||||
pmm_free (cbw_phys, 1);
|
||||
pmm_free (data_phys, data_pages);
|
||||
pmm_free (csw_phys, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void usbdrv_setup_endpoints (struct usbdrv* usbdrv) {
|
||||
for (size_t ep = 0; ep < usbdrv->usb_device->endpoints_count; ep++) {
|
||||
struct xhci_usb_device_endpoint* endpoint = &usbdrv->usb_device->endpoints[ep];
|
||||
@@ -175,9 +252,34 @@ static void usbdrv_setup_endpoints (struct usbdrv* usbdrv) {
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_DEVICE_OP (usbdrv_read) {}
|
||||
DEFINE_DEVICE_OP (usbdrv_read) {
|
||||
uint64_t fd;
|
||||
|
||||
DEFINE_DEVICE_OP (usbdrv_write) {}
|
||||
if (a1 == NULL || a2 == NULL || a3 == NULL)
|
||||
return -ST_BAD_ADDRESS_SPACE;
|
||||
|
||||
size_t sector = *(size_t*)a1;
|
||||
size_t sector_count = *(size_t*)a2;
|
||||
uint8_t* buffer = a3;
|
||||
|
||||
struct usbdrv* usbdrv = device->udata;
|
||||
|
||||
spin_unlock (&device->lock, *lockflags);
|
||||
spin_lock (&usbdrv->xhci->device->lock, &fd);
|
||||
spin_lock (&device->lock, lockflags);
|
||||
|
||||
int ret = usb_ms_scsi_read (usbdrv->xhci, usbdrv->usb_device, usbdrv->bulk_in.endpoint_addr,
|
||||
usbdrv->bulk_out.endpoint_addr, buffer, sector, sector_count,
|
||||
usbdrv->sector_size, &fd);
|
||||
|
||||
spin_unlock (&device->lock, *lockflags);
|
||||
spin_unlock (&usbdrv->xhci->device->lock, fd);
|
||||
spin_lock (&device->lock, lockflags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFINE_DEVICE_OP (usbdrv_write) { return -ST_XDRV_WRITE_ERROR; }
|
||||
|
||||
DEFINE_DEVICE_OP (usbdrv_get_device_type) {
|
||||
if (a1 == NULL)
|
||||
@@ -190,11 +292,34 @@ DEFINE_DEVICE_OP (usbdrv_get_device_type) {
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
DEFINE_DEVICE_OP (usbdrv_get_sector_size) {}
|
||||
DEFINE_DEVICE_OP (usbdrv_get_sector_size) {
|
||||
if (a1 == NULL)
|
||||
return -ST_BAD_ADDRESS_SPACE;
|
||||
|
||||
DEFINE_DEVICE_OP (usbdrv_get_size) {}
|
||||
size_t* secsize = (size_t*)a1;
|
||||
|
||||
struct usbdrv* usbdrv = device->udata;
|
||||
|
||||
*secsize = usbdrv->sector_size;
|
||||
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
DEFINE_DEVICE_OP (usbdrv_get_size) {
|
||||
if (a1 == NULL)
|
||||
return -ST_BAD_ADDRESS_SPACE;
|
||||
|
||||
size_t* size = (size_t*)a1;
|
||||
|
||||
struct usbdrv* usbdrv = device->udata;
|
||||
|
||||
*size = (usbdrv->sector_size * usbdrv->sector_count);
|
||||
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
DEFINE_DEVICE_INIT (usbdrv_init) {
|
||||
uint64_t fd;
|
||||
int ret;
|
||||
struct usbdrv_init* init = arg;
|
||||
|
||||
@@ -209,6 +334,8 @@ DEFINE_DEVICE_INIT (usbdrv_init) {
|
||||
|
||||
device->udata = usbdrv;
|
||||
|
||||
spin_lock (&usbdrv->xhci->device->lock, &fd);
|
||||
|
||||
usbdrv_setup_endpoints (usbdrv);
|
||||
|
||||
ret =
|
||||
@@ -223,15 +350,23 @@ DEFINE_DEVICE_INIT (usbdrv_init) {
|
||||
usbdrv->bulk_out.endpoint_addr, init->lockflags);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
free (usbdrv);
|
||||
spin_unlock (&usbdrv->xhci->device->lock, fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = usb_ms_scsi_read_capacity (usbdrv->xhci, usbdrv->usb_device, usbdrv->bulk_in.endpoint_addr,
|
||||
usbdrv->bulk_out.endpoint_addr, &usbdrv->sector_size,
|
||||
&usbdrv->sector_count, init->lockflags);
|
||||
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
free (usbdrv);
|
||||
spin_unlock (&usbdrv->xhci->device->lock, fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
spin_unlock (&usbdrv->xhci->device->lock, fd);
|
||||
|
||||
DEBUG ("sector_count = %zu, sector_size = %u\n", usbdrv->sector_count, usbdrv->sector_size);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <device/def_device_op.h>
|
||||
#include <device/device.h>
|
||||
#include <device/storage/partitions.h>
|
||||
#include <device/storage/usbdrv.h>
|
||||
#include <device/usb/usb.h>
|
||||
#include <device/usb/xhci.h>
|
||||
@@ -16,7 +17,13 @@ static atomic_int usb_ms_counter = 0;
|
||||
static struct device* usb_ms_init (struct xhci* xhci, struct xhci_usb_device* usb_device,
|
||||
struct proc* proc, struct reschedule_ctx* rctx,
|
||||
uint64_t* lockflags) {
|
||||
static device_op_func_t ops[] = {0};
|
||||
static device_op_func_t ops[] = {
|
||||
[XDRV_GET_SIZE] = &usbdrv_get_size,
|
||||
[XDRV_GET_SECTOR_SIZE] = &usbdrv_get_sector_size,
|
||||
[XDRV_GET_DEVICE_TYPE] = &usbdrv_get_device_type,
|
||||
[XDRV_READ] = &usbdrv_read,
|
||||
[XDRV_WRITE] = &usbdrv_write,
|
||||
};
|
||||
|
||||
struct usbdrv_init init = {
|
||||
.xhci = xhci,
|
||||
@@ -27,8 +34,13 @@ static struct device* usb_ms_init (struct xhci* xhci, struct xhci_usb_device* us
|
||||
char key[30];
|
||||
snprintf (key, sizeof (key), "usbdrv%d", atomic_fetch_add (&usb_ms_counter, 1));
|
||||
|
||||
return device_create (DEVICE_TYPE_DRIVE, key, ops, lengthof (ops), &usbdrv_init, &usbdrv_fini,
|
||||
&init, proc, rctx);
|
||||
struct device* device = device_create (DEVICE_TYPE_DRIVE, key, ops, lengthof (ops), &usbdrv_init,
|
||||
&usbdrv_fini, &init, proc, rctx);
|
||||
|
||||
if (device != NULL)
|
||||
device_probe_partitions (proc, rctx, device);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
struct usb_driver_info usb_driver_infos[USB_DRIVER_MAX_MATCHES] = {
|
||||
|
||||
@@ -918,8 +918,12 @@ static void xhci_poll_setup_init_ifs (struct xhci* xhci, struct xhci_usb_device*
|
||||
if (if_->desc.if_class == info->if_class &&
|
||||
if_->desc.if_subclass == info->if_subclass &&
|
||||
if_->desc.if_proto == info->if_proto) {
|
||||
spin_unlock (&xhci->device->lock, *lockflags);
|
||||
|
||||
struct device* device = info->init (xhci, usb_device, thiscpu->kproc, &rctx, lockflags);
|
||||
|
||||
spin_lock (&xhci->device->lock, lockflags);
|
||||
|
||||
if (device == NULL)
|
||||
DEBUG ("USB driver failed to initialize. Skipping device!\n");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user