modular filesystem driver wip

This commit is contained in:
minjaesong
2022-08-15 00:13:51 +09:00
parent f213dfe165
commit c3efa36a0d
4 changed files with 326 additions and 96 deletions

View File

@@ -55,102 +55,99 @@ function bootFromFirst() {
else bootFromPort(port)
}
function drawHeader() {
let th = con.getmaxyx()[1]
let fillerspc = ' '.repeat((th - 28) / 2)
con.move(1,1)
con.reset_graphics()
print(' ')
con.addch(17);con.curs_right()
con.video_reverse()
print(fillerspc)
print('OpenBIOS Setup Utility')
print(fillerspc)
con.video_reverse()
con.addch(16);con.curs_right()
print(' ')
}
function drawMenubar() {
for (let i = 0; i < configMenus.length; i++) {
con.reset_graphics()
con.move(3 + 2*i, configMenuX)
if (i == configuratorMenu)
con.video_reverse()
print(configMenus[i])
}
}
function clearInfoArea() {
}
function printSysInfo() {
con.move(3,configContentsX)
let rtmin=(sys.currentTimeInMills()/60000)|0
let min=rtmin%60
let h=((rtmin/60)|0)%24
let od=((rtmin/1440)|0)%120
let d=(od%30)+1
let m=((rtmin/43200)|0)%4
let dw=od%7 // 0 for Mondag
if (119==od) dw=7 // Verddag
let y=((rtmin/5184000)|0)+125
print(`Current Time \xE7${y} ${["Spring","Summer","Autumn","Winter"][m]} ${d} ${["Mondag","Tysdag","Midtveke","Torsdag","Fredag","Laurdag","Sundag","Verddag"][dw]} ${(''+h).padStart(2,'0')}:${(''+min).padStart(2,'0')}`)
let ut = (sys.uptime()/1000)|0
let uh = (ut/3600)|0
let um = ((ut/60)|0)%60
let us = ut%60
con.move(4,configContentsX-1)
print(`System uptime ${uh}h${um}m${us}s`)
con.move(6,configContentsX)
print(` User RAM ${system.maxmem()>>>10} Kbytes`)
con.move(7,configContentsX)
print(`Video RAM ${256*sys.peek(-131084)} Kbytes`)
}
function printSerialDevs() {
}
function printExpCards() {
}
function printBMS() {
}
const configMenuX = 4
const configContentsX = 28
let configuratorMenu = 0
const configMenus = [" System Info ", " Serial Devices ", " Expansion Cards ", " Power Status "]
const menuFunctions = [printSysInfo, printSerialDevs, printExpCards, printBMS]
function runConfigurator() {
sys.unsetSysrq()
con.clear()
con.move(2,2);print("Devices:")
for (let i = 0; i < 4; i++) {
con.move(i*2+4, 2)
let bootableMark = (bootable[i]) ? "* " : " "
drawHeader()
drawMenubar()
let deviceName = undefined
try {
com.sendMessage(i, "DEVNAM\x17")
deviceName = com.fetchResponse(i).substring(0,40)
}
catch (e) {
deviceName = `(device not connected)`
}
println(bootableMark + `Serial port #${i+1}: ` + deviceName)
}
let bootnum = undefined
while (true) {
con.move(12,1)
con.curs_set(1)
print("\n Hit 1, 2, 3 or 4 to boot from the specified device: ")
let dev = Number(read())
serial.println(dev)
if (Number.isInteger(dev) && dev >= 1 && dev <= 4) {
bootnum = dev - 1
break
}
}
bootFromPort(bootnum)
}
///////////////////////////////////////////////////////////////////////////////
// Perform memtest
if (!SKIP_MEMTEST) {
let memptr = 0
let reportedMemsize = system.maxmem()
const memtestptn = (reportedMemsize >= 4194304) ?
[
[0x00,0xFF,0xAA,0x55]
] : (reportedMemsize >= 1048576) ?
[
[0x00,0xFF,0xAA,0x55 , 0x69,0x0F,0xA5,0x1E]
] : (reportedMemsize >= 262144) ?
[
[0x00,0xFF,0xAA,0x55 , 0x69,0x0F,0xA5,0x1E , 0xC7,0x71,0x8E,0xE3 , 0xCA,0xFE,0xBA,0xBE]
] :
[
[0x00,0xFF,0xAA,0x55 , 0x69,0x0F,0xA5,0x1E , 0xC7,0x71,0x8E,0xE3 , 0xCA,0xFE,0xBA,0xBE],
[0xFF,0xFF,0xFF,0xFF , 0xFF,0xFF,0xFF,0xFF , 0xFF,0xFF,0xFF,0xFF , 0xFF,0xFF,0xFF,0xFF]
]
con.move(2,1)
print(" 000 KB OK")
try {
while (memptr < (8 << 20)) {
// just print a number
con.move(2,1)
var memptrtext = ""+(1 + ((memptr) >> 10))
print((memptrtext < 10) ? " 00"+memptrtext : (memptrtext < 100) ? " 0"+memptrtext : (memptrtext < 1000) ? " "+memptrtext : memptrtext)
// perform memory test
for (var ptn = 0; ptn < memtestptn.length; ptn++) {
for (var bi = 0; bi < memtestptn[ptn].length; bi++) {
sys.poke(memptr + bi, memtestptn[ptn][bi])
if (memtestptn[ptn][bi] != sys.peek(memptr + bi)) throw "Memory Error"
}
/*for (var bi = 0; bi < memtestptn[ptn].length; bi++) {
sys.poke(memptr + bi, 255 - memtestptn[ptn][bi])
if (255 - memtestptn[ptn][bi] != sys.peek(memptr + bi)) throw "Memory Error"
}*/
}
memptr += memtestptn[0].length
}
throw undefined
}
catch (e) {
if (e == "Memory Error")
println(" "+e)
else
println(" KB OK!")
}
clearInfoArea()
menuFunctions[configuratorMenu]()
}
///////////////////////////////////////////////////////////////////////////////
showSplash()
showHowtoEnterMenu()

View File

@@ -35,10 +35,13 @@ function generateRandomHashStr(len) {
const _TVDOS = {};
_TVDOS.VERSION = "1.0";
_TVDOS.DRIVES = {}; // Object where key-value pair is <drive-letter> : [serial-port, drive-number]
_TVDOS.DRIVEFS = {}; // filesystem driver for the drive letter
// actually figure out the drive letter association
// Drive A is always the device we're currently on
_TVDOS.DRIVES["A"] = _BIOS.FIRST_BOOTABLE_PORT;
_TVDOS.DRIVES["A"] = _BIOS.FIRST_BOOTABLE_PORT
_TVDOS.DRIVEFS["A"] = "SERIAL"
//TODO
_TVDOS.DRV = {}
_TVDOS.getPath = function() {
@@ -59,7 +62,221 @@ Object.freeze(_TVDOS);
///////////////////////////////////////////////////////////////////////////////
_TVDOS.DRV.FS = {}
class TVDOSFileDescriptor {
constructor(path, driverString) {
path = path.replaceAll("\\", "/")
// oh well...
while (path.endsWith("/")) {
path = path.substring(0, path.length - 1)
}
this.path = path
this.driverString = driverString
this.driver = _TVDOS.DRV.FS[driverString]
this.driveLetter = path[0]
}
get size() {
return this.driver.getFileLen()
}
/** reads the file bytewise and puts it to the specified memory address
* @param count optional -- how many bytes to read
* @param offset optional -- how many bytes to skip initially
*/
pread(ptr, count, offset) {
this.driver.pread(this, ptr, count, offset)
}
/** @return bytewise contents of the file in JS array */
bread() {
return this.driver.bread(this)
}
/** @return textwise contents of the file in JS string */
sread() {
return this.driver.sread(this)
}
/** writes the bytes stored in the memory[ptr .. ptr+count-1] to file[offset .. offset+count-1]
* - @param offset is optional
*/
pwrite(ptr, count, offset) {
this.driver.pwrite(this, ptr, count, offset)
}
/** @param bytes bytewise contents to write, in JS array */
bwrite(bytes) {
this.driver.bwrite(this, bytes)
}
/** @param string stringwise contents to write, in JS array */
swrite(string) {
this.driver.swrite(this, string)
}
flush() {
this.driver.flush(this)
}
close() {
this.driver.close(this)
}
get isDirectory() {
return this.driver.isDirectory(this)
}
get name() {
return this.split("/").last()
}
list() {
if (!this.isDirectory()) throw Error(`File is not a directory: ${this.path}`)
return this.driver.listFiles(this)
}
/** When the file does not exist, mkfile() will be called; if you want to make a directory, use mkdir() */
touch() {
return this.driver.touch(this)
}
/** Creates the directory named by this abstract pathname, including any necessary but nonexistent parent directories */
mkDir() {
return this.driver.mkDir(this)
}
mkFile() {
return this.driver.mkFile(this)
}
delete() {
return this.driver.delete(this)
}
}
_TVDOS.DRV.FS.SERIAL = {}
_TVDOS.DRV.FS.SERIAL._toPorts = (driveLetter) => {
if (driveLetter.toUpperCase === undefined) {
throw Error("'"+driveLetter+"' (type: "+typeof driveLetter+") is not a valid drive letter")
}
var port = _TVDOS.DRIVES[driveLetter.toUpperCase()]
if (port === undefined) {
throw Error("Drive letter '" + driveLetter.toUpperCase() + "' does not exist")
}
return port
}
_TVDOS.DRV.FS.SERIAL._close = (portNo) => {
com.sendMessage(portNo, "CLOSE")
}
_TVDOS.DRV.FS.SERIAL._flush = (portNo) => {
com.sendMessage(portNo, "FLUSH")
}
_TVDOS.DRV.FS.SERIAL.close = (fd) => {
let portNo = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
com.sendMessage(portNo, "CLOSE")
}
_TVDOS.DRV.FS.SERIAL.flush = (fd) => {
let portNo = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
com.sendMessage(portNo, "FLUSH")
}
_TVDOS.DRV.FS.SERIAL.getFileLen = (driveLetter) => {
let port = _TVDOS.DRV.FS.SERIAL._toPorts(driveLetter)
com.sendMessage(port[0], "GETLEN")
var response = com.getStatusCode(port[0])
if (135 == response) {
throw Error("File not opened")
}
if (response < 0 || response >= 128) {
throw Error("Reading a file failed with "+response)
}
return Number(com.pullMessage(port[0]))
}
// TODO pread replaces DMA.comToRam
// TODO pwrite replaces DMA.ramToCom
_TVDOS.DRV.FS.SERIAL.sread = (fd) => {
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
com.sendMessage(port[0], "READ")
let response = com.getStatusCode(port[0])
if (135 == response) {
throw Error("File not opened")
}
if (response < 0 || response >= 128) {
throw Error("Reading a file failed with "+response)
}
return com.pullMessage(port[0])
}
_TVDOS.DRV.FS.SERIAL.swrite = (fd, str) => {
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
com.sendMessage(port[0], "WRITE"+string.length)
let response = com.getStatusCode(port[0])
if (135 == response) {
throw Error("File not opened")
}
if (response < 0 || response >= 128) {
throw Error("Writing a file failed with "+response)
}
com.sendMessage(port[0], string)
_TVDOS.DRV.FS.SERIAL._flush(port[0]);_TVDOS.DRV.FS.SERIAL._close(port[0])
}
_TVDOS.DRV.FS.SERIAL.bread = (fd) => {
let str = _TVDOS.DRV.FS.SERIAL.readAll(fd.driveLetter)
let bytes = new Uint8Array(str.length)
for (let i = 0; i < str.length; i++) {
bytes[i] = str.charCodeAt(i)
}
return bytes
}
_TVDOS.DRV.FS.SERIAL.bwrite = (fd, bytes) => { // pwrite replaces DMA.ramToCom
let string = String.fromCharCode.apply(null, bytes) // no spreading: has length limit
_TVDOS.DRV.FS.SERIAL.swrite(fd, string)
}
_TVDOS.DRV.FS.SERIAL.isDirectory = (fd) => {
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
com.sendMessage(port[0], "LISTFILES")
let response = com.getStatusCode(port[0])
return (response === 0)
}
_TVDOS.DRV.FS.SERIAL.listFiles = (fd) => {
TODO()
}
_TVDOS.DRV.FS.SERIAL.touch = (fd) => {
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
com.sendMessage(port[0], "TOUCH")
let response = com.getStatusCode(port[0])
return (response === 0)
}
_TVDOS.DRV.FS.SERIAL.mkDir = (fd) => {
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
com.sendMessage(port[0], "MKDIR")
let response = com.getStatusCode(port[0])
if (response < 0 || response >= 128) {
var status = com.getDeviceStatus(port[0])
throw Error(`Creating a directory failed with (${response}): ${status.message}\n`)
}
return (response === 0) // possible status codes: 0 (success), 1 (fail)
}
_TVDOS.DRV.FS.SERIAL.mkFile = (fd) => {
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
com.sendMessage(port[0], "MKFILE")
let response = com.getStatusCode(port[0])
return (response === 0)
}
_TVDOS.DRV.FS.SERIAL.delete = (fd) => {
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
com.sendMessage(port[0], "DELETE")
let response = com.getStatusCode(port[0])
return (response === 0)
}
Object.freeze(_TVDOS.DRV.FS.SERIAL)
///////////////////////////////////////////////////////////////////////////////
const filesystem = {};
filesystem._toPorts = (driveLetter) => {
if (driveLetter.toUpperCase === undefined) {
throw Error("'"+driveLetter+"' (type: "+typeof driveLetter+") is not a valid drive letter");
@@ -71,11 +288,12 @@ filesystem._toPorts = (driveLetter) => {
return port
};
filesystem._close = (portNo) => {
com.sendMessage(portNo, "CLOSE");
};
com.sendMessage(portNo, "CLOSE")
}
filesystem._flush = (portNo) => {
com.sendMessage(portNo, "FLUSH");
};
com.sendMessage(portNo, "FLUSH")
}
// @return disk status code (0 for successful operation)
// throws if:
// - java.lang.NullPointerException if path is null
@@ -182,6 +400,21 @@ Object.freeze(filesystem);
///////////////////////////////////////////////////////////////////////////////
const files = {}
/** This function only creates a file descriptor; will not actually interact with the drives yet. */
files.open = (fullpath) => {
if (fullpath[1] != '/' && fullpath[1] != '\\') throw Error("Expected full path with drive letter")
let driveLetter = fullpath[0].toUpperCase()
let driver = _TVDOS.DRIVEFS[driveLetter]
return new TVDOSFileDescriptor(fullpath, driver)
}
Object.freeze(files)
///////////////////////////////////////////////////////////////////////////////
const input = {};
const inputwork = {};

View File

@@ -97,7 +97,7 @@ class VM(
fun findPeribyType(searchTerm: String): PeripheralEntry? {
for (i in 0..peripheralSlots) {
for (i in 0 until peripheralSlots) {
if (peripheralTable[i].type == searchTerm) return peripheralTable[i]
}
return null

View File

@@ -33,8 +33,8 @@ public class AppLoader {
// VM vm = new VM(64 << 10, new TheRealWorld(), new VMProgramRom[]{TandemBios.INSTANCE, BasicRom.INSTANCE});
// VM vm = new VM(128 << 10, new TheRealWorld(), new VMProgramRom[]{BasicBios.INSTANCE, WPBios.INSTANCE});
// VM vm = new VM("./assets", 8192 << 10, new TheRealWorld(), new VMProgramRom[]{TsvmBios.INSTANCE});
VM vm = new VM("./assets", 8192 << 10, new TheRealWorld(), new VMProgramRom[]{OpenBios.INSTANCE});
VM pipvm = new VM("./assets", 4096, new TheRealWorld(), new VMProgramRom[]{PipBios.INSTANCE, PipROM.INSTANCE});
VM vm = new VM("./assets", 8192 << 10, new TheRealWorld(), new VMProgramRom[]{OpenBios.INSTANCE}, 8);
VM pipvm = new VM("./assets", 4096, new TheRealWorld(), new VMProgramRom[]{PipBios.INSTANCE, PipROM.INSTANCE}, 8);
String diskPath = "assets/disk0";