diff --git a/boot-programs/devices.hhp b/boot-programs/devices.hhp index 9d198f8..ff12a9e 100644 --- a/boot-programs/devices.hhp +++ b/boot-programs/devices.hhp @@ -23,20 +23,65 @@ // List interface. template // -struct List : public Kernel::Cap: - List (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): - // TODO +struct List : public Kernel::Caps: + List (Kernel::Caps c = Kernel::Cap ()) : Kernel::Caps (c): + List <_T> create (unsigned size, Kernel::Memory mem = Kernel::my_memory): + return List <_T> (mem.create_caps (size)) + void set (unsigned idx, _T value): + return Kernel::Caps::set (idx, value) + _T get (unsigned idx): + return _T (Kernel::Caps::get (idx)) +/// A block of data with a size and content. Any character can be stored in it (including '\0'). struct String : public Kernel::Cap: String (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): - // TODO + enum request: + GET_SIZE = 0x2001 + GET_CHARS + GET_PAGE + _END_MARKER + /// Get the size of the string. + Kernel::Num get_size (): + return call (CAP_MASTER_DIRECT | GET_SIZE) + /// Get exactly 16 characters. The index must be word-aligned. + char *get_chars (Kernel::Num idx, char buffer[16]): + call (CAP_MASTER_DIRECT | GET_CHARS, idx) + unsigned *b = (unsigned *)buffer + b[0] = Kernel::recv.data[0].l + b[1] = Kernel::recv.data[0].h + b[2] = Kernel::recv.data[1].l + b[3] = Kernel::recv.data[1].h + return buffer + /// Get a page from the string. This need not be implemented for strings smaller than PAGE_SIZE. The index must be page-aligned. + Cap get_page (Kernel::Num idx, Kernel::Page ret = Kernel::my_memory.create_page ()): + ocall (ret, CAP_MASTER_DIRECT | GET_PAGE, idx) + return ret + +/// A writable String. +struct WString : public String: + WString (Kernel::Cap c = Kernel::Cap ()) : String (c): + enum request: + TRUNCATE = String::_END_MARKER + SET_CHARS + SET_PAGE + _END_MARKER + /// Set the size of the string. Strings may have a limit to this setting. + void truncate (Kernel::Num size): + call (CAP_MASTER_DIRECT | TRUNCATE, size) + /// Set exactly 4 characters. The index must be word-aligned. + void set_chars (Kernel::Num idx, char buffer[4]): + call (Kernel::Num (CAP_MASTER_DIRECT | SET_CHARS, *(unsigned *)buffer), idx) + /// Overwrite a page from the string. This need not be implemented for strings smaller than PAGE_SIZE. The index must be page-aligned. The caller may lose the frame in the transaction. + void set_page (Kernel::Num idx, Kernel::Page page): + ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx) // Keyboard interface. struct Keyboard : public Kernel::Cap: Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): enum request: - SET_CB = 1 + SET_CB = WString::_END_MARKER GET_KEYS + _END_MARKER // At event: the callback is called with a keycode. One bit defines if it's a press or release event. enum constant: RELEASE = 1 << 31 @@ -46,16 +91,17 @@ struct Keyboard : public Kernel::Cap: // Get a list of keys on this keyboard. The key codes start at zero with no gaps. List get_keys (): icall (CAP_MASTER_DIRECT | GET_KEYS) - return Kernel::get_arg () + return List (Kernel::get_arg ()) // Display interface. struct Display : public Kernel::Cap: Display (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): enum request: - EOF_CB = 1 + EOF_CB = Keyboard::_END_MARKER CREATE_FB USE_FB GET_INFO + _END_MARKER // Register an end-of-frame callback. // At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events. void set_eof_cb (Kernel::Cap cb): @@ -83,9 +129,10 @@ struct Display : public Kernel::Cap: struct File : public Kernel::Cap: File (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): enum request: - INFO = 1 + INFO = Display::_END_MARKER CLOSE MAP_HANDLE + _END_MARKER // Get information about the file. Kernel::Num get_info (unsigned type): return icall (Kernel::Num (CAP_MASTER_DIRECT | INFO, type)) @@ -101,12 +148,13 @@ struct File : public Kernel::Cap: struct Directory : public File: Directory (Kernel::Cap c = Kernel::Cap ()) : File (c): enum request: - GET_SIZE = 1 + GET_SIZE = File::_END_MARKER GET_NAME GET_FILE GET_FILE_INFO CREATE_FILE DELETE_FILE + _END_MARKER // Get the number of entries in this directory. Kernel::Num get_size (): return call (CAP_MASTER_DIRECT | GET_SIZE) @@ -133,8 +181,9 @@ struct Directory : public File: struct Stream : public File: Stream (Kernel::Cap c = Kernel::Cap ()) : File (c): enum request: - READ = 1 + READ = Directory::_END_MARKER WRITE + _END_MARKER // Try to read size bytes. Returns the number of bytes successfully read. Kernel::Num read (Kernel::Num size): return icall (CAP_MASTER_DIRECT | READ, size) @@ -146,9 +195,10 @@ struct Stream : public File: struct Seekable : public File: Seekable (Kernel::Cap c = Kernel::Cap ()) : File (c): enum request: - READ = 1 + READ = Stream::_END_MARKER WRITE TRUNCATE + _END_MARKER // Try to read size bytes from position idx. Returns the number of bytes successfully read. Kernel::Num read (Kernel::Num idx, unsigned size): return icall (Kernel::Num (CAP_MASTER_DIRECT | READ, size), idx) diff --git a/invoke.ccp b/invoke.ccp index c00616a..f7d8520 100644 --- a/invoke.ccp +++ b/invoke.ccp @@ -708,6 +708,16 @@ static void print_cap (kCapRef cap, kCapRef self): static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c): kCaps *caps = (kCapsP)protected_data.l switch cmd: + case Kernel::Caps::GET & REQUEST_MASK: + if c->data[1].l >= caps->size: + dpanic (0, "invalid index for get caps") + return + kCapability *ret = caps->cap (c->data[1].l) + reply_cap ((unsigned)ret->target, ret->protected_data, ((unsigned)ret->target & ~KERNEL_MASK) == 0 ? &((kObject *)ret->target)->refs : &ret->target->capabilities) + return + case Kernel::Caps::GET_SIZE & REQUEST_MASK: + reply_num (caps->size) + return case Kernel::Caps::SET & REQUEST_MASK: if c->data[1].l >= caps->size: dpanic (0, "invalid index for set caps") @@ -715,6 +725,9 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da caps->clone (c->data[1].l, c->arg, c->copy[1]) reply_num (0) return + case Kernel::Caps::TRUNCATE & REQUEST_MASK: + dpanic (0, "truncate caps is not implemented yet.") + return case Kernel::Caps::PRINT & REQUEST_MASK: if c->data[1].l >= caps->size: dpanic (0, "invalid caps for print") diff --git a/iris.hhp b/iris.hhp index bd654ec..394a728 100644 --- a/iris.hhp +++ b/iris.hhp @@ -353,12 +353,22 @@ namespace Kernel: enum request: // Not an operation; this capability can be used in Thread::USE_SLOT. USE = CAPTYPE_CAPS + 1 + GET + GET_SIZE SET + TRUNCATE PRINT unsigned use (unsigned slot = alloc_slot ()): return my_thread.use (*this, slot) + Cap get (unsigned idx): + call (CAP_MASTER_DIRECT | GET, idx) + return get_arg () + unsigned get_size (): + return call (CAP_MASTER_DIRECT | GET_SIZE).l void set (unsigned idx, Cap cap): ocall (cap, CAP_MASTER_DIRECT | SET, idx) + void truncate (unsigned new_size): + call (CAP_MASTER_DIRECT | TRUNCATE, new_size) void print (unsigned idx): invoke (CAP_MASTER_DIRECT | PRINT, idx) diff --git a/plan b/plan index 3560761..5e9608e 100644 --- a/plan +++ b/plan @@ -1,5 +1,2 @@ -kernel capabilities: 1 per aktie; bevat code in plaats van bitmask. CREATE ipv DEGRADE. -protected data in receiver -message: a0-a3: data0; data1; protectedL; protectedH caps zonder size limit? invoke ipc: try sync; try receiver memory; try caller memory; fail.