Commit 2e1d8076 authored by Eddie Kohler's avatar Eddie Kohler
Browse files

Initial handout code for 2021.

parent 00bfb093
...@@ -3,7 +3,8 @@ all: $(QEMUIMAGEFILES) ...@@ -3,7 +3,8 @@ all: $(QEMUIMAGEFILES)
# Place local configuration options, such as `CC=clang`, in # Place local configuration options, such as `CC=clang`, in
# `config.mk` so you don't have to list them every time. # `config.mk` so you don't have to list them every time.
-include config.mk CONFIG ?= config.mk
-include $(CONFIG)
# `$(V)` controls whether the makefiles print verbose commands (the shell # `$(V)` controls whether the makefiles print verbose commands (the shell
# commands run by Make) or brief commands (like `COMPILE`). # commands run by Make) or brief commands (like `COMPILE`).
...@@ -33,6 +34,9 @@ QEMUOPT = -net none -parallel $(LOG) -smp $(NCPU) ...@@ -33,6 +34,9 @@ QEMUOPT = -net none -parallel $(LOG) -smp $(NCPU)
ifeq ($(D),1) ifeq ($(D),1)
QEMUOPT += -d int,cpu_reset,guest_errors -no-reboot QEMUOPT += -d int,cpu_reset,guest_errors -no-reboot
endif endif
ifneq ($(NOGDB),1)
QEMUGDB ?= -gdb tcp::12949
endif
# Sets of object files # Sets of object files
...@@ -47,7 +51,7 @@ KERNEL_OBJS = $(OBJDIR)/k-exception.ko \ ...@@ -47,7 +51,7 @@ KERNEL_OBJS = $(OBJDIR)/k-exception.ko \
$(OBJDIR)/k-ahci.ko $(OBJDIR)/k-chkfs.ko $(OBJDIR)/k-chkfsiter.ko \ $(OBJDIR)/k-ahci.ko $(OBJDIR)/k-chkfs.ko $(OBJDIR)/k-chkfsiter.ko \
$(OBJDIR)/k-memviewer.ko $(OBJDIR)/lib.ko $(OBJDIR)/k-initfs.ko $(OBJDIR)/k-memviewer.ko $(OBJDIR)/lib.ko $(OBJDIR)/k-initfs.ko
PROCESSES = $(patsubst %.cc,%,$(wildcard p-*.cc)) PROCESSES ?= $(patsubst %.cc,%,$(wildcard p-*.cc))
PROCESS_LIB_OBJS = $(OBJDIR)/lib.uo $(OBJDIR)/u-lib.uo $(OBJDIR)/crc32c.uo PROCESS_LIB_OBJS = $(OBJDIR)/lib.uo $(OBJDIR)/u-lib.uo $(OBJDIR)/crc32c.uo
...@@ -107,7 +111,7 @@ $(OBJDIR)/bootentry.o: $(OBJDIR)/%.o: \ ...@@ -107,7 +111,7 @@ $(OBJDIR)/bootentry.o: $(OBJDIR)/%.o: \
$(OBJDIR)/%.uo: %.cc $(BUILDSTAMPS) $(OBJDIR)/%.uo: %.cc $(BUILDSTAMPS)
$(call cxxcompile,$(CXXFLAGS) -O1 -DCHICKADEE_PROCESS -c $< -o $@,COMPILE $<) $(call cxxcompile,$(CXXFLAGS) -O1 -DCHICKADEE_PROCESS -c $< -o $@,COMPILE $<)
$(OBJDIR)/%.uo: %.S $(OBJDIR)/u-asm.h $(KERNELBUILDSTAMPS) $(OBJDIR)/%.uo: %.S $(OBJDIR)/u-asm.h $(BUILDSTAMPS)
$(call assemble,-O2 -c $< -o $@,ASSEMBLE $<) $(call assemble,-O2 -c $< -o $@,ASSEMBLE $<)
...@@ -150,7 +154,7 @@ $(OBJDIR)/kernel: $(OBJDIR)/kernel.full $(OBJDIR)/mkchickadeesymtab ...@@ -150,7 +154,7 @@ $(OBJDIR)/kernel: $(OBJDIR)/kernel.full $(OBJDIR)/mkchickadeesymtab
$(OBJDIR)/%: $(OBJDIR)/%.full $(OBJDIR)/%: $(OBJDIR)/%.full
$(call run,$(OBJDUMP) -C -S -j .text -j .ctors $< >$@.asm) $(call run,$(OBJDUMP) -C -S -j .text -j .ctors $< >$@.asm)
$(call run,$(NM) -n $< >$@.sym) $(call run,$(NM) -n $< >$@.sym)
$(call run,$(OBJCOPY) -j .text -j .rodata -j .data -j .bss -j .ctors -j .init_array $<,STRIP,$@) $(call run,$(QUIETOBJCOPY) -j .text -j .rodata -j .data -j .bss -j .ctors -j .init_array $<,STRIP,$@)
$(OBJDIR)/bootsector: $(BOOT_OBJS) boot.ld $(OBJDIR)/bootsector: $(BOOT_OBJS) boot.ld
$(call link,-T boot.ld -o $@.full $(BOOT_OBJS),LINK) $(call link,-T boot.ld -o $@.full $(BOOT_OBJS),LINK)
...@@ -174,7 +178,7 @@ $(OBJDIR)/%.o: build/%.cc $(BUILDSTAMPS) ...@@ -174,7 +178,7 @@ $(OBJDIR)/%.o: build/%.cc $(BUILDSTAMPS)
$(call run,$(HOSTCXX) $(CPPFLAGS) $(HOSTCXXFLAGS) $(DEPCFLAGS) -c -o $@,HOSTCOMPILE,$<) $(call run,$(HOSTCXX) $(CPPFLAGS) $(HOSTCXXFLAGS) $(DEPCFLAGS) -c -o $@,HOSTCOMPILE,$<)
$(OBJDIR)/mkchickadeefs: build/mkchickadeefs.cc $(BUILDSTAMPS) $(OBJDIR)/mkchickadeefs: build/mkchickadeefs.cc $(BUILDSTAMPS)
$(call run,$(HOSTCXX) $(CPPFLAGS) $(HOSTCXXFLAGS) $(DEPCFLAGS) -o $@,HOSTCOMPILE,$<) $(call run,$(HOSTCXX) $(CPPFLAGS) $(HOSTCXXFLAGS) $(DEPCFLAGS) -g -o $@,HOSTCOMPILE,$<)
CHICKADEEFSCK_OBJS = $(OBJDIR)/chickadeefsck.o \ CHICKADEEFSCK_OBJS = $(OBJDIR)/chickadeefsck.o \
$(OBJDIR)/journalreplayer.o \ $(OBJDIR)/journalreplayer.o \
...@@ -212,12 +216,12 @@ QEMUIMG = -M q35 \ ...@@ -212,12 +216,12 @@ QEMUIMG = -M q35 \
run: run-$(QEMUDISPLAY) run: run-$(QEMUDISPLAY)
@: @:
run-graphic: $(QEMUIMAGEFILES) check-qemu run-gdb-report:
@echo '* Run `gdb -x build/chickadee.gdb` to connect gdb to qemu.' 1>&2 @if test "$(QEMUGDB)" = "-gdb tcp::12949"; then echo '* Run `gdb -x build/weensyos.gdb` to connect gdb to qemu.' 1>&2; fi
$(call run,$(QEMU_PRELOAD) $(QEMU) $(QEMUOPT) -gdb tcp::12949 $(QEMUIMG),QEMU $<) run-graphic: $(QEMUIMAGEFILES) check-qemu run-gdb-report
run-console: $(QEMUIMAGEFILES) check-qemu-console $(call run,$(QEMU_PRELOAD) $(QEMU) $(QEMUOPT) $(QEMUGDB) $(QEMUIMG),QEMU $<)
@echo '* Run `gdb -x build/chickadee.gdb` to connect gdb to qemu.' 1>&2 run-console: $(QEMUIMAGEFILES) check-qemu-console run-gdb-report
$(call run,$(QEMU) $(QEMUOPT) -curses -gdb tcp::12949 $(QEMUIMG),QEMU $<) $(call run,$(QEMU) $(QEMUOPT) -curses $(QEMUGDB) $(QEMUIMG),QEMU $<)
run-monitor: $(QEMUIMAGEFILES) check-qemu run-monitor: $(QEMUIMAGEFILES) check-qemu
$(call run,$(QEMU_PRELOAD) $(QEMU) $(QEMUOPT) -monitor stdio $(QEMUIMG),QEMU $<) $(call run,$(QEMU_PRELOAD) $(QEMU) $(QEMUOPT) -monitor stdio $(QEMUIMG),QEMU $<)
run-gdb: run-gdb-$(QEMUDISPLAY) run-gdb: run-gdb-$(QEMUDISPLAY)
......
...@@ -9,13 +9,16 @@ Quickstart: `make run` or `make run-PROGRAM` ...@@ -9,13 +9,16 @@ Quickstart: `make run` or `make run-PROGRAM`
Make targets Make targets
------------ ------------
Run `make NCPU=N run` to run with `N` virtual CPUs (default is 2). `make NCPU=N run` will run the OS with `N` virtual CPUs (default is 2). Close
the QEMU window, or type `q` inside it, to exit the OS.
Run `make SAN=1 run` to run with sanitizers. `make run-console` will run the OS in the console window.
Normally Chickadee’s debug log is written to `log.txt`. Run `make LOG=stdio `make SAN=1 run` to run with sanitizers enabled.
run` to redirect the debug log to the standard output, or `make
LOG=file:FILENAME run` to redirect it to `FILENAME`. Normally Chickadee’s debug log is written to `log.txt`. `make LOG=stdio run`
will redirect the debug log to the standard output, and `make
LOG=file:FILENAME run` will redirect it to `FILENAME`.
Run `make D=1 run` to ask QEMU to print verbose information about interrupts Run `make D=1 run` to ask QEMU to print verbose information about interrupts
and CPU resets to the standard error. This setting will also cause QEMU to and CPU resets to the standard error. This setting will also cause QEMU to
...@@ -29,6 +32,36 @@ default is `alloc`. ...@@ -29,6 +32,36 @@ default is `alloc`.
Troubleshooting Troubleshooting
--------------- ---------------
There are several ways to kill a recalcitrant QEMU (for instance, if your
OS has become unresponsive).
* If QEMU is running in its own graphical window, then close the window. This
will kill the embedded OS.
* If QEMU is running in a terminal window (in Docker, for instance), then
press `Alt-2`. This will bring up the QEMU Monitor, which looks like this:
```
compat_monitor0 console
QEMU 4.2.0 monitor - type 'help' for more information
(qemu)
```
Type `quit` and hit Return to kill the embedded OS and return to your
shell. If this leaves the terminal looking funny, enter the `reset` shell
command to restore it.
If `Alt-2` does not work, you may need to configure your terminal to
properly send the Alt key. For instance, on Mac OS X’s Terminal, go to
Terminal > Preferences > Keyboard and select “Use Option as Meta key”. You
can also configure a special keyboard shortcut that sends the `Escape 2`
sequence.
Run `make run-gdb` to start up the OS with support for GDB debugging. This
will start the OS, but not GDB. You must run `gdb -x build/weensyos.gdb` to
connect to the running emulator; when GDB connects, it will stop the OS and
wait for instructions.
If you experience runtime errors involving `obj/libqemu-nograb.so.1`, put If you experience runtime errors involving `obj/libqemu-nograb.so.1`, put
`QEMU_PRELOAD_LIBRARY=` in `config.mk`. This disables a shim we use that `QEMU_PRELOAD_LIBRARY=` in `config.mk`. This disables a shim we use that
prevents QEMU from grabbing the mouse. prevents QEMU from grabbing the mouse.
...@@ -41,7 +74,7 @@ Source files ...@@ -41,7 +74,7 @@ Source files
| File | Description | | File | Description |
| --------------- | ---------------------------- | | --------------- | ---------------------------- |
| `types.h` | Type definitions | | `types.h` | Type definitions |
| `lib.hh/cc` | Chickadee C library | | `lib.hh/cc` | C library |
| `x86-64.h` | x86-64 hardware definitions | | `x86-64.h` | x86-64 hardware definitions |
| `elf.h` | ELF64 structures | | `elf.h` | ELF64 structures |
...@@ -103,11 +136,11 @@ The main output of the build process is a disk image, ...@@ -103,11 +136,11 @@ The main output of the build process is a disk image,
could conceivably boot on real hardware! The build process also could conceivably boot on real hardware! The build process also
produces other files that can be useful to examine. produces other files that can be useful to examine.
| File | Description | | File | Description |
| ---------------------------- | ------------------------------------ | | -------------------------- | ------------------------------------ |
| `obj/kernel.asm` | Kernel assembly (with addresses) | | `obj/kernel.asm` | Kernel assembly (with addresses) |
| `obj/kernel.sym` | Kernel defined symbols | | `obj/kernel.sym` | Kernel defined symbols |
| `obj/p-allocator.asm`, `sym` | Same for process binaries | | `obj/p-PROCESS.asm`, `sym` | Same for process binaries |
[CS 161]: https://read.seas.harvard.edu/cs161/2020/ [CS 161]: https://read.seas.harvard.edu/cs161/2021/
[triple fault]: https://en.wikipedia.org/wiki/Triple_fault [triple fault]: https://en.wikipedia.org/wiki/Triple_fault
...@@ -59,9 +59,9 @@ init_boot_pagetable: ...@@ -59,9 +59,9 @@ init_boot_pagetable:
rep stosl rep stosl
# set up boot page table # set up boot page table
# 0x1000: L1 page table; entries 0, 256, and 511 point to: # 0x1000: L4 page table; entries 0, 256, and 511 point to:
# 0x2000: L2 page table; entries 0 and 510 map 1st 1GB of physmem # 0x2000: L3 page table; entries 0 and 510 map 1st 1GB of physmem
# This weird setup is the minimal page table that maps all of # This is the minimal page table that maps all of
# low-canonical, high-canonical, and kernel-text addresses to # low-canonical, high-canonical, and kernel-text addresses to
# the first 1GB of physical memory. # the first 1GB of physical memory.
movl $BOOT_PAGETABLE, %edi movl $BOOT_PAGETABLE, %edi
......
#! /bin/sh
onexit () {
test -n "$tmp" && rm -f "$tmp"
}
trap onexit 0
tmp=`mktemp /tmp/objcopy.XXXXXX`
"$@" 2> $tmp
v=$?
cat $tmp | grep -v "empty loadable segment" 1>&2
exit $v
...@@ -60,6 +60,8 @@ LDFLAGS := $(LDFLAGS) -Os --gc-sections -z max-page-size=0x1000 \ ...@@ -60,6 +60,8 @@ LDFLAGS := $(LDFLAGS) -Os --gc-sections -z max-page-size=0x1000 \
-static -nostdlib -nostartfiles -static -nostdlib -nostartfiles
LDFLAGS += $(shell $(LD) -m elf_x86_64 --help >/dev/null 2>&1 && echo -m elf_x86_64) LDFLAGS += $(shell $(LD) -m elf_x86_64 --help >/dev/null 2>&1 && echo -m elf_x86_64)
QUIETOBJCOPY = sh build/quietobjcopy.sh $(OBJCOPY)
# Dependencies # Dependencies
DEPSDIR := .deps DEPSDIR := .deps
...@@ -154,7 +156,7 @@ always: ...@@ -154,7 +156,7 @@ always:
# These targets don't correspond to files # These targets don't correspond to files
.PHONY: all always clean realclean distclean cleanfs fsck \ .PHONY: all always clean realclean distclean cleanfs fsck \
run run-graphic run-console run-monitor \ run run-graphic run-console run-monitor \
run-gdb run-gdb-graphic run-gdb-console \ run-gdb run-gdb-graphic run-gdb-console run-gdb-report \
check-qemu-console check-qemu kill \ check-qemu-console check-qemu kill \
run-% run-graphic-% run-console-% run-monitor-% \ run-% run-graphic-% run-console-% run-monitor-% \
run-gdb-% run-gdb-graphic-% run-gdb-console-% run-gdb-% run-gdb-graphic-% run-gdb-console-%
......
FROM ubuntu:focal
# set environment variables for tzdata
ARG TZ=America/New_York
ENV TZ ${TZ}
# include manual pages and documentation
RUN DEBIAN_FRONTEND=noninteractive apt-get update && yes | unminimize
# install GCC-related packages
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install \
binutils-doc \
cpp-doc \
gcc-doc \
g++ \
g++-multilib \
gdb \
gdb-doc \
glibc-doc \
libblas-dev \
liblapack-dev \
liblapack-doc \
libstdc++-10-doc \
make \
make-doc
# install clang-related packages
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install \
clang \
clang-10-doc \
lldb
# install qemu for pset 4 (sadly, this pulls in a lot of crap)
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install \
qemu-system-x86
# install programs used for system exploration
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install \
blktrace \
linux-tools-generic \
strace \
tcpdump
# install interactive programs (emacs, vim, nano, man, sudo, etc.)
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install \
bc \
curl \
dc \
emacs-nox \
git \
git-doc \
man \
micro \
nano \
sudo \
vim \
wget
# set up libraries
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install \
libreadline-dev \
locales \
wamerican
# install programs used for networking
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install \
dnsutils \
inetutils-ping \
net-tools \
netcat \
telnet \
traceroute
# set up default locale
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
# remove unneeded .deb files
RUN rm -r /var/lib/apt/lists/*
# set up passwordless sudo for user cs61-user
RUN useradd -m -s /bin/bash cs61-user && \
echo "cs61-user ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/cs61-init
# create binary reporting version of dockerfile
RUN (echo '#\!/bin/sh'; echo 'echo 5') > /usr/bin/cs61-docker-version; chmod ugo+rx,u+w,go-w /usr/bin/cs61-docker-version
# git build arguments
ARG USER=CS61\ User
ARG EMAIL=nobody@example.com
# configure your environment
USER cs61-user
RUN git config --global user.name "${USER}" && \
git config --global user.email "${EMAIL}" && \
(echo "(custom-set-variables"; echo " '(c-basic-offset 4)"; echo " '(indent-tabs-mode nil))") > ~/.emacs && \
(echo "set expandtab"; echo "set shiftwidth=4"; echo "set softtabstop=4") > ~/.vimrc && \
echo "add-auto-load-safe-path ~" > ~/.gdbinit
WORKDIR /home/cs61-user
# Initial version of this Dockerfile by Todd Morrill, CS 61 DCE student
CS 61/161 Docker
================
> **tl;dr**:
> * `docker build -t cs61:latest -f Dockerfile .` to build a Docker image
> * `docker system prune -a` to remove old Docker images
The [Docker][] container-based virtualization service lets you run a
minimal CS 161 environment, including a virtual Linux host, on a Mac
OS X or Windows host, without the overhead of a full virtual machine
solution like [VMware Workstation][], [VMware Fusion][], or
[VirtualBox][].
It should be possible to do *all* CS 161 problem sets on CS 61 Docker.
(However, you may prefer to set up a local environent.)
Advantages of Docker:
* Docker can start and stop virtual machines incredibly quickly.
* Docker-based virtual machines are leaner and take less space on your
machine.
* With Docker, you can easily *edit* your code in your home
*environment, but compile and run* it on a Linux host.
Disadvantages of Docker:
* Docker does not offer a full graphical environment. You will need to
run QEMU exclusively in the terminal.
* Docker technology is less user-friendly than virtual machines.
You’ll have to type weird commands.
* It will run slower.
## Preparing CS 161 Docker
To prepare to build your Docker environment:
1. Download and install [Docker][].
2. Clone a copy of the [chickadee repository][].
3. Change into the `chickadee/docker` directory.
To build your Docker environment, run this command. It will take a couple
minutes. You’ll want to re-run this command every time the Docker image
changes, but later runs should be much faster since they’ll take advantage of
your previous work.
```shellsession
$ docker build -t cs61:latest -f Dockerfile .
```
## Running Docker by script
The Chickadee repository contains a `run-docker` script that
provides good arguments and boots Docker into a view of the current
directory.
For example:
```shellsession
$ cd ~/chickadee
$ ./run-docker
cs61-user@a47f05ea5085:~/chickadee$ echo Hello, Linux
Hello, Linux
cs61-user@a47f05ea5085:~/chickadee$ exit
exit
$
```
The script plonks you into a virtual machine! A prompt like
`cs61-user@a47f05ea5085:~$` means that your terminal is connected to the VM.
You can execute any commands you want. To escape from the VM, type Control-D
or run the `exit` command.
The script assumes your Docker container is named `cs61:latest`, as it
was above.
### Running Docker by hand
If you don’t want to use the script, use a command like the following.
```shellsession
$ docker run -it --rm -v ~/chickadee:/home/cs61-user/chickadee cs61:latest
```
Explanation:
* `docker run` tells Docker to start a new virtual machine.
* `-it` says Docker should run interactively (`-i`) using a terminal (`-t`).
* `--rm` says Docker should remove the virtual machine when it is done.
* `-v LOCALDIR:LINUXDUR` says Docker should share a directory between your
host and the Docker virtual machine. Here, I’ve asked for the host’s
`~/chickadee` directory to be mapped inside the virtual machine onto the
`/home/cs61-user/chickadee` directory, which is the virtual machine
user’s `~/chickadee` directory.
* `cs61:latest` names the Docker image to run (namely, the one you built).
Here’s an example session:
```shellsession
$ docker run -it --rm -v ~/chickadee:/home/cs61-user/chickadee cs61:latest
cs61-user@a15e6c4c8dbe:~$ ls
cs61-lectures
cs61-user@a15e6c4c8dbe:~$ echo "Hello, world"
Hello, world
cs61-user@a15e6c4c8dbe:~$ cs61-docker-version
3
cs61-user@a15e6c4c8dbe:~$ exit
exit
$
```
[Docker]: https://docker.com/
[VMware Workstation]: https://www.vmware.com/products/workstation-player.html
[VMware Fusion]: https://www.vmware.com/products/fusion.html
[VirtualBox]: https://www.virtualbox.org/
[Chickadee repository]: https://github.com/cs161/chickadee/
...@@ -136,7 +136,7 @@ class ioapicstate { ...@@ -136,7 +136,7 @@ class ioapicstate {
inline lapicstate& lapicstate::get() { inline lapicstate& lapicstate::get() {
return *reinterpret_cast<lapicstate*>(pa2ka(lapic_pa)); return *pa2kptr<lapicstate*>(lapic_pa);
} }
inline uint32_t lapicstate::id() const { inline uint32_t lapicstate::id() const {
return read(reg_id) >> 24; return read(reg_id) >> 24;
...@@ -168,7 +168,7 @@ inline void lapicstate::write(int reg, uint32_t v) { ...@@ -168,7 +168,7 @@ inline void lapicstate::write(int reg, uint32_t v) {
} }
inline ioapicstate& ioapicstate::get() { inline ioapicstate& ioapicstate::get() {
return *reinterpret_cast<ioapicstate*>(pa2ka(ioapic_pa)); return *pa2kptr<ioapicstate*>(ioapic_pa);
} }
inline uint32_t ioapicstate::id() const { inline uint32_t ioapicstate::id() const {
return read(reg_id) >> 24; return read(reg_id) >> 24;
......
...@@ -8,21 +8,21 @@ class chkfs_fileiter { ...@@ -8,21 +8,21 @@ class chkfs_fileiter {
static constexpr size_t blocksize = chkfs::blocksize; static constexpr size_t blocksize = chkfs::blocksize;
// initialize an iterator for `ino` at file offset `off` // Initialize an iterator for `ino` at file offset `off`.
// The caller must have a reference on `ino`. // The caller must have a reference on `ino`.
chkfs_fileiter(chkfs::inode* ino, off_t off = 0); chkfs_fileiter(chkfs::inode* ino, off_t off = 0);
NO_COPY_OR_ASSIGN(chkfs_fileiter); NO_COPY_OR_ASSIGN(chkfs_fileiter);
~chkfs_fileiter(); ~chkfs_fileiter();
// return the inode // Return the inode
inline chkfs::inode* inode() const; inline chkfs::inode* inode() const;
// return the current file offset // Return the current file offset
inline off_t offset() const; inline off_t offset() const;
// return true iff the offset is within the file (i.e., in some extent) // Return true iff the offset is within the file (i.e., in some extent)
inline bool active() const; inline bool active() const;
// return true iff the offset points at data // Return true iff the offset does not point at data
inline bool present() const; inline bool empty() const;
// Return the block number corresponding to the current file offset. // Return the block number corresponding to the current file offset.
// Returns 0 if there is no block stored for the current offset. // Returns 0 if there is no block stored for the current offset.
...@@ -30,15 +30,15 @@ class chkfs_fileiter { ...@@ -30,15 +30,15 @@ class chkfs_fileiter {
// Return a buffer cache entry containing the current file offset’s data. // Return a buffer cache entry containing the current file offset’s data.
// Returns nullptr if there is no block stored for the current offset. // Returns nullptr if there is no block stored for the current offset.
inline bcentry* get_disk_entry() const; inline bcentry* get_disk_entry() const;
// return the file offset relative to the current block // Return the file offset relative to the current block
inline unsigned block_relative_offset() const; inline unsigned block_relative_offset() const;
// Move the iterator to file offset `off`. Returns `*this`. // Move the iterator to file offset `off`. Returns `*this`.
chkfs_fileiter& find(off_t off); chkfs_fileiter& find(off_t off);
// Like `find(offset() + delta)`. // Like `find(offset() + delta)`
inline chkfs_fileiter& operator+=(ssize_t delta); inline chkfs_fileiter& operator+=(ssize_t delta);
// Like `find(offset() - delta)`. // Like `find(offset() - delta)`
inline chkfs_fileiter& operator-=(ssize_t delta); inline chkfs_fileiter& operator-=(ssize_t delta);
...@@ -104,11 +104,11 @@ inline bool chkfs_fileiter::active() const { ...@@ -104,11 +104,11 @@ inline bool chkfs_fileiter::active() const {
inline unsigned chkfs_fileiter::block_relative_offset() const { inline unsigned chkfs_fileiter::block_relative_offset() const {
return off_ % blocksize; return off_ % blocksize;
} }
inline bool chkfs_fileiter::present() const { inline bool chkfs_fileiter::empty() const {
return eptr_ && eptr_->first != 0; return !eptr_ || eptr_->first == 0;
} }
inline auto chkfs_fileiter::blocknum() const -> blocknum_t { inline auto chkfs_fileiter::blocknum() const -> blocknum_t {
if (eptr_ && eptr_->first != 0) { if (!empty()) {
return eptr_->first + (off_ - eoff_) / blocksize; return eptr_->first + (off_ - eoff_) / blocksize;
} else { } else {
return 0; return 0;
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#define KEY_NUMLOCK 0xFE #define KEY_NUMLOCK 0xFE
#define KEY_SCROLLLOCK 0xFF #define KEY_SCROLLLOCK 0xFF
#define CKEY(cn) 0x80 + cn #define CKEY(cn) (0x80 + cn)
static const uint8_t keymap[256] = { static const uint8_t keymap[256] = {
/*0x00*/ 0, 033, CKEY(0), CKEY(1), CKEY(2), CKEY(3), CKEY(4), CKEY(5), /*0x00*/ 0, 033, CKEY(0), CKEY(1), CKEY(2), CKEY(3), CKEY(4), CKEY(5),
...@@ -122,10 +122,6 @@ int keyboard_readc() { ...@@ -122,10 +122,6 @@ int keyboard_readc() {
// the global `keyboardstate` singleton // the global `keyboardstate` singleton
keyboardstate keyboardstate::kbd; keyboardstate keyboardstate::kbd;
keyboardstate::keyboardstate()
: pos_(0), len_(0), eol_(0), state_(boot) {
}
void keyboardstate::handle_interrupt() { void keyboardstate::handle_interrupt() {
auto irqs = lock_.lock(); auto irqs = lock_.lock();
...@@ -209,22 +205,39 @@ void keyboardstate::consume(size_t n) { ...@@ -209,22 +205,39 @@ void keyboardstate::consume(size_t n) {
consolestate consolestate::console; consolestate consolestate::console;