MODULE UsbStorageBoot;
IMPORT
Machine, KernelLog, Disks, Plugins,
UsbUtilities, Usb, Usbdi, Base := UsbStorageBase, BOT := UsbStorageBot;
CONST
Name = "UsbStorageBoot";
Description = "USB Mass Storage Boot Driver";
Priority = 10;
BootDeviceName = "USB0";
VAR
assigned : BOOLEAN;
serialNumber : UsbUtilities.AsciiString;
PROCEDURE Probe(dev : Usbdi.UsbDevice; id : Usbdi.InterfaceDescriptor) : Usbdi.Driver;
VAR
protocol, i : LONGINT;
bulkInEndpoint, bulkOutEndpoint : LONGINT;
bot : BOT.BulkOnlyTransport;
description : Usbdi.Description;
driver : Base.StorageDriver;
BEGIN {EXCLUSIVE}
IF assigned THEN RETURN NIL; END;
IF id.bInterfaceClass # 8 THEN RETURN NIL END;
IF id.bInterfaceProtocol # 50H THEN RETURN NIL; END;
IF ~IsBootDevice(dev.descriptor(Usb.DeviceDescriptor)) THEN RETURN NIL; END;
CASE id.bInterfaceSubClass OF
1 : protocol := Base.ProtocolRBC; description := "Usb Reduced Block Command Drive";
|2 : protocol := Base.Protocol8020; description := "Usb SFF8020i ATAPI device";
|3 : protocol := Base.ProtocolQIC157; description := "Usb QIC-157 Tape device";
|4 : protocol := Base.ProtocolUFI; description := "Usb UFI Floppy drive";
|5 : protocol := Base.Protocol8070; description := "Usb SFF8070i ATAPI device";
|6 : protocol := Base.ProtocolUTS; description := "Usb Transparent SCSI device";
ELSE
RETURN NIL;
END;
IF (id.bNumEndpoints # 2) & (id.bNumEndpoints # 3) THEN RETURN NIL END;
FOR i := 0 TO id.bNumEndpoints - 1 DO
IF id.endpoints[i].type = Usbdi.BulkOut THEN
bulkOutEndpoint := id.endpoints[i].bEndpointAddress;
ELSIF id.endpoints[i].type = Usbdi.BulkIn THEN
bulkInEndpoint := id.endpoints[i].bEndpointAddress;
END;
END;
IF (bulkInEndpoint = 0) OR (bulkOutEndpoint = 0) THEN RETURN NIL END;
NEW(bot); driver := bot;
driver.bulkIn := bulkInEndpoint;
driver.bulkOut := bulkOutEndpoint;
driver.transportProtocol := protocol;
driver.transportMethod := Base.MethodBulkOnly;
driver.description := description;
assigned := TRUE;
RETURN driver;
END Probe;
PROCEDURE WaitForBootDevice;
VAR ignore : Plugins.Plugin;
BEGIN
KernelLog.Enter;
KernelLog.String("UsbStorageBoot: Booting from USB. Awaiting device "); KernelLog.String(BootDeviceName); KernelLog.String("...");
KernelLog.Exit;
ignore := Disks.registry.Await(BootDeviceName);
KernelLog.Enter;
KernelLog.String("UsbStorageBoot: Boot device "); KernelLog.String(BootDeviceName); KernelLog.String(" connected.");
KernelLog.Exit;
END WaitForBootDevice;
PROCEDURE IsBootDevice(descriptor : Usb.DeviceDescriptor) : BOOLEAN;
BEGIN
RETURN (serialNumber^ = "") OR
((serialNumber^ # "") & (descriptor.sSerialNumber # NIL) & (descriptor.sSerialNumber^ = serialNumber^));
END IsBootDevice;
PROCEDURE GetBootConfiguration;
VAR string : ARRAY 128 OF CHAR;
BEGIN
string := ""; Machine.GetConfig("SerialNumber", string);
serialNumber := UsbUtilities.NewString(string);
IF (serialNumber^ # "") THEN
KernelLog.Enter;
KernelLog.String("UsbStorageBoot: Boot device serial number: "); KernelLog.String(serialNumber^);
KernelLog.Exit;
END;
END GetBootConfiguration;
PROCEDURE Install*;
END Install;
BEGIN
GetBootConfiguration;
Usbdi.drivers.Add(Probe, Name, Description, Priority);
WaitForBootDevice;
END UsbStorageBoot.
UsbStorageBoot.Install ~ SystemTools.Free UsbStorageBoot ~