├── .github └── workflows │ └── deploy.yaml ├── .gitignore ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── build.sh ├── embed_files.py ├── file_template.js ├── gen_pdf.py ├── init ├── pdflinux.js ├── requirements.txt ├── tinyemu ├── Changelog ├── MIT-LICENSE.txt ├── Makefile ├── Makefile.js ├── Makefile.pdfjs ├── VERSION ├── aes.c ├── aes.h ├── block_net.c ├── build_filelist.c ├── cutils.c ├── cutils.h ├── fbuf.h ├── fs.c ├── fs.h ├── fs_disk.c ├── fs_net.c ├── fs_utils.c ├── fs_utils.h ├── fs_wget.c ├── fs_wget.h ├── ide.c ├── ide.h ├── iomem.c ├── iomem.h ├── js │ └── lib.js ├── jsemu.c ├── json.c ├── json.h ├── list.h ├── machine.c ├── machine.h ├── netinit.sh ├── pci.c ├── pci.h ├── pckbd.c ├── ps2.c ├── ps2.h ├── readme.txt ├── riscv_cpu.c ├── riscv_cpu.h ├── riscv_cpu_fp_template.h ├── riscv_cpu_priv.h ├── riscv_cpu_template.h ├── riscv_machine.c ├── sdl.c ├── sha256.c ├── sha256.h ├── simplefb.c ├── slirp │ ├── bootp.c │ ├── bootp.h │ ├── cksum.c │ ├── debug.h │ ├── if.c │ ├── if.h │ ├── ip.h │ ├── ip_icmp.c │ ├── ip_icmp.h │ ├── ip_input.c │ ├── ip_output.c │ ├── libslirp.h │ ├── main.h │ ├── mbuf.c │ ├── mbuf.h │ ├── misc.c │ ├── misc.h │ ├── sbuf.c │ ├── sbuf.h │ ├── slirp.c │ ├── slirp.h │ ├── slirp_config.h │ ├── socket.c │ ├── socket.h │ ├── tcp.h │ ├── tcp_input.c │ ├── tcp_output.c │ ├── tcp_subr.c │ ├── tcp_timer.c │ ├── tcp_timer.h │ ├── tcp_var.h │ ├── tcpip.h │ ├── tftp.h │ ├── udp.c │ └── udp.h ├── softfp.c ├── softfp.h ├── softfp_template.h ├── softfp_template_icvt.h ├── splitimg.c ├── temu.c ├── vga.c ├── virtio.c ├── virtio.h ├── vmmouse.c ├── x86_cpu.c ├── x86_cpu.h └── x86_machine.c ├── vm_32.cfg ├── vm_64.cfg └── web ├── favicon.ico ├── favicon_128.png ├── index.css └── index.html /.github/workflows/deploy.yaml: -------------------------------------------------------------------------------- 1 | 2 | on: [push] 3 | 4 | jobs: 5 | publish: 6 | runs-on: ubuntu-latest 7 | if: github.ref == 'refs/heads/main' 8 | permissions: 9 | contents: read 10 | deployments: write 11 | 12 | name: Publish to Cloudflare Pages 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v3 16 | 17 | - name: Build 18 | run: | 19 | python3 -m venv .venv 20 | source .venv/bin/activate 21 | pip3 install -r requirements.txt 22 | ./build.sh 23 | du -sh out/* 24 | 25 | - name: Publish to Cloudflare Pages 26 | uses: cloudflare/pages-action@v1 27 | with: 28 | apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} 29 | accountId: b8079ffa92c97010f2a8d759e24cc782 30 | projectName: linuxpdf 31 | directory: out 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /emsdk 2 | /.venv/ 3 | /out/ 4 | /build 5 | 6 | *.js.d 7 | *.js.o 8 | *.wasm 9 | *.wat 10 | riscvemu32*.js 11 | riscvemu64*.js -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "clangd.fallbackFlags": [ 3 | "-I${workspaceFolder}/emsdk/fastcomp/emscripten/system/include" 4 | ] 5 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LinuxPDF 2 | 3 | This is Linux running inside a PDF file via a RISC-V emulator, which is based on [TinyEMU](https://bellard.org/tinyemu/). 4 | 5 | Try it here: [linux.pdf](https://linux.doompdf.dev/linux.pdf) 6 | 7 | https://github.com/user-attachments/assets/7e992dd1-41a5-4d32-87cc-878b395e3d92 8 | 9 | See also: [DoomPDF](https://github.com/ading2210/doompdf) 10 | 11 | ## Explanation 12 | 13 | This works in a very similar way to my previous [DoomPDF](https://github.com/ading2210/doompdf) project. 14 | 15 | You might expect PDF files to only be comprised of static documents, but surprisingly, the PDF file format supports Javascript with its own separate standard library. Modern browsers (Chromium, Firefox) implement this as part of their PDF engines. However, the APIs that are available in the browser are much more limited. 16 | 17 | The full specfication for the JS in PDFs was only ever implemented by Adobe Acrobat, and it contains some ridiculous things like the ability to do [3D rendering](https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/JS_API_AcroJS.html#annot3d), make [HTTP requests](https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/JS_API_AcroJS.html#net-http), and [detect every monitor connected to the user's system](https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/JS_API_AcroJS.html#monitor). However, on Chromium and other browsers, only a tiny subset of this API was ever implemented, due to obvious security concerns. With this, we can do whatever computation we want, just with some very limited IO. 18 | 19 | C code can be compiled to run within a PDF using an old version of Emscripten that targets [asm.js](https://en.wikipedia.org/wiki/Asm.js) instead of WebAssembly. With this, I can compile a modified version of the TinyEMU RISC-V emulator to asm.js, which can be run within the PDF. For the input and output, I reused the same display code that I used for DoomPDF. It works by using a separate text field for each row of pixels in the screen, whose contents are set to various ASCII characters. For inputs, there is a virtual keyboard implemented with a bunch of buttons, and a text box you can type in to send keystrokes to the VM. 20 | 21 | The largest problem here is with the emulator's performance. For example, the Linux kernel takes about 30-60 seconds to boot up within the PDF, which over 100x slower than normal. Unfortunately, there's no way to fix this, since the version of V8 that Chrome's PDF engine uses has its [JIT compiler disabled](https://source.chromium.org/chromium/_/pdfium/pdfium/+/012fe571c9fe430da68dbcd2f5ba21758db0ae15:fpdfsdk/fpdf_view.cpp;l=1211-1214;drc=b69783fd189976dd4625c7dcd9c07921b94d4a3c;bpv=0;bpt=0), destroying its performance. 22 | 23 | For the root filesystem, there are both 64 and 32 bit versions possible. The default is a 32 bit buildroot system (which was prebuilt and taken from the original TinyEMU examples), and also a 64 bit Alpine Linux system. The 64 bit emulator is about twice as slow however, so it's normally not used. 24 | 25 | ## Build Instructions 26 | 27 | Clone this repository and run the following commands: 28 | ``` 29 | python3 -m venv .venv 30 | source .venv/bin/activate 31 | pip3 install -r requirements.txt 32 | ./build.sh 33 | ``` 34 | If you want to build the 64 bit rather than 32 bit version, edit `build.sh` and change the `BITS="32"` line. 35 | 36 | The `build.sh` script will download Emscripten `1.39.20` automatically. You must be on Linux to build this. 37 | 38 | The generated files will be in the `out/` directory. Then you can run `(cd out; python3 -m http.server)` to serve the files on a web server. 39 | 40 | ## Credits 41 | 42 | This project was made by [@ading2210](https://github.com/ading2210/). 43 | 44 | The RISC-V emulator is forked from [TinyEMU](https://bellard.org/tinyemu/), which was written by [Fabrice Bellard](https://bellard.org/). 45 | 46 | ## License 47 | 48 | This repository is licensed under the GNU GPL v3. 49 | 50 | ``` 51 | ading2210/linuxpdf - Linux running inside a PDF file 52 | Copyright (C) 2025 ading2210 53 | 54 | This program is free software: you can redistribute it and/or modify 55 | it under the terms of the GNU General Public License as published by 56 | the Free Software Foundation, either version 3 of the License, or 57 | (at your option) any later version. 58 | 59 | This program is distributed in the hope that it will be useful, 60 | but WITHOUT ANY WARRANTY; without even the implied warranty of 61 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 62 | GNU General Public License for more details. 63 | 64 | You should have received a copy of the GNU General Public License 65 | along with this program. If not, see . 66 | ``` 67 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -x 5 | 6 | BITS="32" 7 | 8 | if [ ! -d "./emsdk" ]; then 9 | git clone https://github.com/emscripten-core/emsdk.git --branch 1.39.20 10 | ./emsdk/emsdk install 1.39.20-fastcomp 11 | ./emsdk/emsdk activate 1.39.20-fastcomp 12 | fi 13 | 14 | source ./emsdk/emsdk_env.sh >/dev/null 2>&1 15 | source ./.venv/bin/activate >/dev/null 2>&1 16 | 17 | mkdir -p out build 18 | if [ ! -f "build/vm.tar.gz" ]; then 19 | wget "https://bellard.org/tinyemu/diskimage-linux-riscv-2018-09-23.tar.gz" -O build/vm.tar.gz 20 | fi 21 | if [ ! -d "build/vm" ]; then 22 | tar -xf build/vm.tar.gz -C build 23 | mv build/diskimage* build/vm 24 | fi 25 | 26 | if [ "$1" = "clean" ]; then 27 | emmake make -C tinyemu/ -f Makefile.pdfjs clean 28 | fi 29 | emmake make -C tinyemu/ -f Makefile.pdfjs -j$(nproc --all) 30 | 31 | 32 | if [ ! -f "build/pako.min.js" ]; then 33 | wget "https://cdn.jsdelivr.net/npm/pako@2.1.0/dist/pako.min.js" -O "build/pako.min.js" 34 | fi 35 | 36 | if [ ! -f "build/build_files" ]; then 37 | gcc tinyemu/build_filelist.c tinyemu/fs_utils.c tinyemu/cutils.c -o build/build_files 38 | fi 39 | 40 | get_alpine_rootfs() { 41 | wget https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/riscv64/latest-releases.yaml -O build/alpine-releases.yaml 42 | download_filename="$(grep "alpine-minirootfs-" build/alpine-releases.yaml | head -n1 | awk '{print $NF}')" 43 | download_url="https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/riscv64/$download_filename" 44 | wget "$download_url" -O "build/$download_filename" 45 | mkdir -p "build/alpine" 46 | tar -xf "build/$download_filename" -C "build/alpine" 47 | 48 | #install base packages 49 | echo "nameserver 1.1.1.1" > "build/alpine/etc/resolv.conf" 50 | sudo chroot "build/alpine" apk add --no-cache agetty fastfetch nano htop 51 | 52 | #set up autologin 53 | echo "tty1::respawn:/sbin/agetty --autologin root tty0 linux" > "build/alpine/etc/inittab" 54 | echo "#!/bin/sh 55 | mount -t proc none /proc 56 | mount -t sysfs none /sys 57 | hostname -F /etc/hostname 58 | echo 'VM boot complete' > /dev/hvc0 59 | fastfetch -l small" > "build/alpine/root/.profile" 60 | chmod +x "build/alpine/root/.profile" 61 | 62 | #set hostname and motd 63 | echo "linuxpdf" > "build/alpine/etc/hostname" 64 | echo -n "" > "build/alpine/etc/motd" 65 | 66 | #compile demos 67 | mkdir -p build/alpine/root/demos/ 68 | git clone "https://github.com/kevinboone/fblife" build/alpine/root/demos/fblife 69 | echo '#!/bin/sh 70 | set -e 71 | set +x 72 | apk add --no-cache gcc make musl-dev linux-headers 73 | 74 | cd /root/demos/fblife 75 | echo -e "#include \n$(cat src/defs.h)" > src/defs.h 76 | make 77 | mv fblife /root/ 78 | 79 | cd / 80 | apk del gcc make musl-dev linux-headers 81 | rm -rf /root/demos 82 | ' > build/alpine/tmp/setup.sh 83 | chmod +x build/alpine/tmp/setup.sh 84 | sudo chroot "build/alpine" /bin/sh /tmp/setup.sh 85 | } 86 | 87 | get_img_rootfs() { 88 | mkdir -p build/mountpoint 89 | sudo mount -o ro build/vm/root-riscv$BITS.bin build/mountpoint 90 | sudo cp -ar build/mountpoint build/root 91 | sudo cp -ar ./init build/root/sbin/init 92 | sudo umount build/mountpoint 93 | rm -rf build/mountpoint 94 | } 95 | 96 | #use a 9pfs mount for the root - more efficient 97 | build_files() { 98 | [ "$BITS" = "64" ] && root_dir="build/alpine" || root_dir="build/root" 99 | if [ ! -d "$root_dir" ]; then 100 | if [ "$BITS" = "64" ]; then 101 | get_alpine_rootfs 102 | else 103 | get_img_rootfs 104 | fi 105 | fi 106 | 107 | if [ ! -d "build/files" ]; then 108 | mkdir -p build/files/root 109 | sudo build/build_files "$root_dir" build/files/root 110 | fi 111 | } 112 | 113 | #use a block device for the root 114 | build_disk() { 115 | if [ ! -d "build/files/disk" ]; then 116 | mkdir -p build/files/disk 117 | cp build/vm/root-riscv$BITS.bin build/files/disk/root.bin 118 | 119 | block_size="256" 120 | ( 121 | cd build/files/disk 122 | split -b "${block_size}K" -d -a 9 --additional-suffix=".bin" root.bin "blk" 123 | rm root.bin 124 | ) 125 | num_blocks="$(find build/files/disk/ -name 'blk*.bin' | wc -l)" 126 | echo " 127 | { 128 | block_size: $block_size, 129 | n_block: $num_blocks, 130 | } 131 | " > build/files/disk/info.txt 132 | fi 133 | } 134 | 135 | build_files 136 | cp vm_$BITS.cfg build/vm/bbl$BITS.bin build/vm/kernel-riscv$BITS.bin build/files 137 | 138 | python3 embed_files.py file_template.js build/files/ build/files.js 139 | cat build/pako.min.js build/files.js pdflinux.js tinyemu/js/riscvemu$BITS.js > out/compiled.js 140 | 141 | python3 gen_pdf.py out/compiled.js out/linux.pdf 142 | cp web/* out -------------------------------------------------------------------------------- /embed_files.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import pathlib 3 | import json 4 | import base64 5 | import zlib 6 | 7 | if len(sys.argv) < 4: 8 | print("not enough arguments.") 9 | sys.exit(1) 10 | 11 | js_path = pathlib.Path(sys.argv[1]).resolve() 12 | files_dir = pathlib.Path(sys.argv[2]).resolve() 13 | out_path = pathlib.Path(sys.argv[3]).resolve() 14 | 15 | files = {} 16 | for file_path in files_dir.rglob("*"): 17 | if file_path.is_dir(): 18 | continue 19 | rel_path = str(file_path.relative_to(files_dir)) 20 | data = file_path.read_bytes() 21 | data_compressed = zlib.compress(data, level=9) 22 | data_b64 = base64.b64encode(data_compressed) 23 | files[rel_path] = data_b64.decode() 24 | 25 | js = js_path.read_text() 26 | js = js.replace("__files_data__", json.dumps(files)) 27 | 28 | out_path.write_text(js) -------------------------------------------------------------------------------- /file_template.js: -------------------------------------------------------------------------------- 1 | //https://stackoverflow.com/a/41106346/21330993 2 | function b64_to_uint8array(str) { 3 | const abc = [..."ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"]; // base64 alphabet 4 | let result = []; 5 | 6 | for(let i=0; i abc.indexOf(x).toString(2).padStart(6,0)).join(''); 9 | let bytes = bin.match(/.{1,8}/g).map(x=> +('0b'+x)); 10 | result.push(...bytes.slice(0,3 - (str[4*i+2]=="=") - (str[4*i+3]=="="))); 11 | } 12 | return new Uint8Array(result); 13 | } 14 | 15 | var embedded_files = __files_data__; 16 | for (let filename in embedded_files) { 17 | embedded_files[filename] = pako.inflate(b64_to_uint8array(embedded_files[filename])); 18 | } -------------------------------------------------------------------------------- /gen_pdf.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from pdfrw import PdfWriter 4 | from pdfrw.objects.pdfname import PdfName 5 | from pdfrw.objects.pdfstring import PdfString 6 | from pdfrw.objects.pdfdict import PdfDict 7 | from pdfrw.objects.pdfarray import PdfArray 8 | 9 | def create_script(js): 10 | action = PdfDict() 11 | action.S = PdfName.JavaScript 12 | action.JS = "try {"+js+"} catch (e) {app.alert(e.stack || e)}" 13 | return action 14 | 15 | def create_page(width, height): 16 | page = PdfDict() 17 | page.Type = PdfName.Page 18 | page.MediaBox = PdfArray([0, 0, width, height]) 19 | 20 | page.Resources = PdfDict() 21 | page.Resources.Font = PdfDict() 22 | page.Resources.Font.F1 = PdfDict() 23 | page.Resources.Font.F1.Type = PdfName.Font 24 | page.Resources.Font.F1.Subtype = PdfName.Type1 25 | page.Resources.Font.F1.BaseFont = PdfName.Courier 26 | 27 | return page 28 | 29 | def create_field(name, x, y, width, height, value="", f_type=PdfName.Tx): 30 | annotation = PdfDict() 31 | annotation.Type = PdfName.Annot 32 | annotation.Subtype = PdfName.Widget 33 | annotation.FT = f_type 34 | annotation.Ff = 2 35 | annotation.Rect = PdfArray([x, y, x + width, y + height]) 36 | annotation.T = PdfString.encode(name) 37 | annotation.V = PdfString.encode(value) 38 | 39 | annotation.BS = PdfDict() 40 | annotation.BS.W = 0 41 | 42 | appearance = PdfDict() 43 | appearance.Type = PdfName.XObject 44 | appearance.SubType = PdfName.Form 45 | appearance.FormType = 1 46 | appearance.BBox = PdfArray([0, 0, width, height]) 47 | appearance.Matrix = PdfArray([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]) 48 | 49 | return annotation 50 | 51 | def create_text(x, y, size, txt): 52 | return f""" 53 | BT 54 | /F1 {size} Tf 55 | {x} {y} Td ({txt}) Tj 56 | ET 57 | """ 58 | 59 | def create_button(name, x, y, width, height, value): 60 | button = create_field(name, x, y, width, height, f_type=PdfName.Btn) 61 | button.AA = PdfDict() 62 | button.Ff = 65536 63 | button.MK = PdfDict() 64 | button.MK.BG = PdfArray([0.90]) 65 | button.MK.CA = value 66 | return button 67 | 68 | def create_key_buttons(keys_info): 69 | buttons = [] 70 | for info in keys_info: 71 | key = info["key"] 72 | name = "button_" + key 73 | value = info.get("value") or key 74 | button = create_button(name, info["x"], info["y"], info["width"], info["height"], value) 75 | button.AA = PdfDict() 76 | if info.get("toggle"): 77 | button.AA.D = create_script(f"button_toggle('{key}')") 78 | else: 79 | button.AA.D = create_script(f"button_down('{key}')") 80 | button.AA.U = create_script(f"button_up('{key}')") 81 | 82 | buttons.append(button) 83 | return buttons 84 | 85 | def create_keys_row(keys, x, y, width, height, gap): 86 | buttons = [] 87 | for i, key in enumerate(keys): 88 | name = "button_" + key 89 | new_x = x + i * (width + gap) 90 | button = create_button(name, new_x, y, width, height, key.upper()) 91 | button.AA = PdfDict() 92 | if key == "'": 93 | key = "\\'" 94 | button.AA.D = create_script(f"button_down('{key}')") 95 | button.AA.U = create_script(f"button_up('{key}')") 96 | buttons.append(button) 97 | return buttons 98 | 99 | if __name__ == "__main__": 100 | with open(sys.argv[1]) as f: 101 | js = f.read() 102 | 103 | width = 360 104 | height = 200 105 | scale = 2 106 | 107 | writer = PdfWriter() 108 | page = create_page(width * scale-8, height * scale + 220) 109 | page.AA = PdfDict() 110 | page.AA.O = create_script(js) 111 | 112 | fields = [] 113 | for i in range(0, height): 114 | field = create_field(f"field_{i}", 0, i*scale + 220, width*scale-8, scale, "") 115 | fields.append(field) 116 | for i in range(0, 25): 117 | field = create_field(f"console_{i}", 8, 8 + i*8, 200, 8, "") 118 | fields.append(field) 119 | 120 | fields.append(create_field("speed_indicator", 582, 170, 97, 12, "Loading...")) 121 | fields.append(create_field("key_status", 220, 50, 200, 12, "Pressed:")) 122 | input_field = create_field(f"key_input", 500, 50, 179, 12, "Type here for keyboard inputs.") 123 | input_field.AA = PdfDict() 124 | input_field.AA.K = create_script("key_pressed(event.change)") 125 | fields.append(input_field) 126 | 127 | fields += create_key_buttons([ 128 | dict(key="Esc", x=220, y=170, width=20, height=12), 129 | dict(key="`", x=220, y=148, width=12, height=16), 130 | dict(key="Backspace", value="<----", x=550, y=148, width=50, height=16), 131 | 132 | dict(key="Tab", x=220, y=128, width=24, height=16), 133 | dict(key="\\", x=562, y=128, width=38, height=16), 134 | 135 | dict(key="CapsLock", value="Caps", x=220, y=108, width=30, height=16), 136 | dict(key="Enter", x=542, y=108, width=58, height=16), 137 | 138 | dict(key="Shift", x=220, y=88, width=44, height=16, toggle=True), 139 | dict(key="RShift", x=530, y=88, width=70, height=16), 140 | 141 | dict(key="Ctrl", x=220, y=68, width=36, height=16, toggle=True), 142 | dict(key="Alt", x=260, y=68, width=36, height=16, toggle=True), 143 | dict(key="Space", x=300, y=68, width=174, height=16), 144 | dict(key="RAlt", value="Alt", x=480, y=68, width=36, height=16, toggle=True), 145 | dict(key="ContextMenu", value="Menu", x=522, y=68, width=36, height=16), 146 | dict(key="RCtrl", value="Ctrl", x=564, y=68, width=36, height=16, toggle=True), 147 | 148 | dict(key="Home", x=608, y=148, width=32, height=16), 149 | dict(key="Insert", value="Ins", x=608, y=128, width=32, height=16), 150 | dict(key="Delete", value="Del", x=608, y=108, width=32, height=16), 151 | dict(key="End", x=646, y=148, width=32, height=16), 152 | dict(key="PgUp", x=646, y=128, width=32, height=16), 153 | dict(key="PgDn", x=646, y=108, width=32, height=16), 154 | 155 | dict(key="ArrowUp", value="^", x=633, y=88, width=20, height=16), 156 | dict(key="ArrowLeft", value="<", x=608, y=68, width=20, height=16), 157 | dict(key="ArrowDown", value="v", x=633, y=68, width=20, height=16), 158 | dict(key="ArrowRight", value=">", x=658, y=68, width=20, height=16), 159 | ]) 160 | fields += create_keys_row([f"F{i}" for i in range(1, 13)], 246, 170, 22, 12, 6) 161 | fields += create_keys_row("1234567890-=", 238, 148, 20, 16, 6) 162 | fields += create_keys_row("qwertyuiop[]", 250, 128, 20, 16, 6) 163 | fields += create_keys_row("asdfghjkl;'", 256, 108, 20, 16, 6) 164 | fields += create_keys_row("zxcvbnm,./", 270, 88, 20, 16, 6) 165 | 166 | page.Contents = PdfDict() 167 | page.Contents.stream = "\n".join([ 168 | create_text(220, 190, 24, "LinuxPDF"), 169 | create_text(220, 22, 8, "Source code: https://github.com/ading2210/linuxpdf"), 170 | create_text(220, 10, 8, "Note: This PDF only works in Chromium-based browsers."), 171 | create_text(520, 22, 8, "To send keystrokes to the VM, use the"), 172 | create_text(520, 10, 8, "buttons or type in the box above."), 173 | create_text(220, 36, 8, "=" * 100) 174 | ]) 175 | 176 | page.Annots = PdfArray(fields) 177 | writer.addpage(page) 178 | writer.write(sys.argv[2]) -------------------------------------------------------------------------------- /init: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #this is the init script that runs inside the vm (for 32 bit rootfs only) 4 | 5 | export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin 6 | export HOME=/root 7 | export TERM=linux 8 | 9 | mount -a 10 | 11 | ifconfig lo 127.0.0.1 12 | 13 | cd $HOME 14 | 15 | while /bin/true; do 16 | clear 17 | echo "Welcome to LinuxPDF" 18 | echo 19 | echo "This is a riscv32 emulator based on" 20 | echo "TinyEMU, modified to run inside a PDF." 21 | echo 22 | echo "Source code:" 23 | echo "https://github.com/ading2210/linuxpdf" 24 | echo 25 | setsid sh; 26 | 27 | done 28 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pdfrw -------------------------------------------------------------------------------- /tinyemu/Changelog: -------------------------------------------------------------------------------- 1 | 2019-12-21: 2 | 3 | - added complete JSLinux demo 4 | - RISC-V: added initrd support 5 | - RISC-V: fixed FMIN/FMAX instructions 6 | 7 | 2018-09-23: 8 | 9 | - added support for separate RISC-V BIOS and kernel 10 | 11 | 2018-09-15: 12 | 13 | - renamed to TinyEMU (temu) 14 | - single executable for all emulated machines 15 | 16 | 2018-08-29: 17 | 18 | - compilation fixes 19 | 20 | 2017-08-06: 21 | 22 | - added JSON configuration file 23 | - added graphical display with SDL 24 | - added VirtIO input support 25 | - added PCI bus and VirtIO PCI support 26 | - x86: added IDE, PS/2, vmmouse and VGA devices 27 | - added user mode network interface 28 | 29 | 2017-06-10: 30 | 31 | - RISCV: avoid unnecessary kernel patches 32 | - x86: accept standard kernel images 33 | 34 | 2017-05-25: 35 | 36 | - RISCV: faster emulation (1.4x) 37 | - Support of user level ISA version 2.2 and priviledged architecture 38 | version 1.10 39 | - added small x86 emulator (x86emu) based on KVM 40 | - modified the fs_net network protocol to match the vfsync protocol 41 | - handle console resize 42 | - JS emulator: 43 | - added scrollbar in terminal 44 | - added file import and export 45 | - added copy/paste support 46 | -------------------------------------------------------------------------------- /tinyemu/MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2017 Fabrice Bellard 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /tinyemu/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # TinyEMU 3 | # 4 | # Copyright (c) 2016-2018 Fabrice Bellard 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | # if set, network filesystem is enabled. libcurl and libcrypto 26 | # (openssl) must be installed. 27 | CONFIG_FS_NET=y 28 | # SDL support (optional) 29 | CONFIG_SDL=y 30 | # if set, compile the 128 bit emulator. Note: the 128 bit target does 31 | # not compile if gcc does not support the int128 type (32 bit hosts). 32 | CONFIG_INT128=y 33 | # build x86 emulator 34 | CONFIG_X86EMU=y 35 | # win32 build (not usable yet) 36 | #CONFIG_WIN32=y 37 | # user space network redirector 38 | CONFIG_SLIRP=y 39 | 40 | ifdef CONFIG_WIN32 41 | CROSS_PREFIX=i686-w64-mingw32- 42 | EXE=.exe 43 | else 44 | CROSS_PREFIX= 45 | EXE= 46 | endif 47 | CC=$(CROSS_PREFIX)gcc 48 | STRIP=$(CROSS_PREFIX)strip 49 | CFLAGS=-O2 -Wall -g -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -MMD 50 | CFLAGS+=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\" 51 | LDFLAGS= 52 | 53 | bindir=/usr/local/bin 54 | INSTALL=install 55 | 56 | PROGS+= temu$(EXE) 57 | ifndef CONFIG_WIN32 58 | ifdef CONFIG_FS_NET 59 | PROGS+=build_filelist splitimg 60 | endif 61 | endif 62 | 63 | all: $(PROGS) 64 | 65 | EMU_OBJS:=virtio.o pci.o fs.o cutils.o iomem.o simplefb.o \ 66 | json.o machine.o temu.o 67 | 68 | ifdef CONFIG_SLIRP 69 | CFLAGS+=-DCONFIG_SLIRP 70 | EMU_OBJS+=$(addprefix slirp/, bootp.o ip_icmp.o mbuf.o slirp.o tcp_output.o cksum.o ip_input.o misc.o socket.o tcp_subr.o udp.o if.o ip_output.o sbuf.o tcp_input.o tcp_timer.o) 71 | endif 72 | 73 | ifndef CONFIG_WIN32 74 | EMU_OBJS+=fs_disk.o 75 | EMU_LIBS=-lrt 76 | endif 77 | ifdef CONFIG_FS_NET 78 | CFLAGS+=-DCONFIG_FS_NET 79 | EMU_OBJS+=fs_net.o fs_wget.o fs_utils.o block_net.o 80 | EMU_LIBS+=-lcurl -lcrypto 81 | ifdef CONFIG_WIN32 82 | EMU_LIBS+=-lwsock32 83 | endif # CONFIG_WIN32 84 | endif # CONFIG_FS_NET 85 | ifdef CONFIG_SDL 86 | EMU_LIBS+=-lSDL 87 | EMU_OBJS+=sdl.o 88 | CFLAGS+=-DCONFIG_SDL 89 | ifdef CONFIG_WIN32 90 | LDFLAGS+=-mwindows 91 | endif 92 | endif 93 | 94 | EMU_OBJS+=riscv_machine.o softfp.o riscv_cpu32.o riscv_cpu64.o 95 | ifdef CONFIG_INT128 96 | CFLAGS+=-DCONFIG_RISCV_MAX_XLEN=128 97 | EMU_OBJS+=riscv_cpu128.o 98 | else 99 | CFLAGS+=-DCONFIG_RISCV_MAX_XLEN=64 100 | endif 101 | ifdef CONFIG_X86EMU 102 | CFLAGS+=-DCONFIG_X86EMU 103 | EMU_OBJS+=x86_cpu.o x86_machine.o ide.o ps2.o vmmouse.o pckbd.o vga.o 104 | endif 105 | 106 | temu$(EXE): $(EMU_OBJS) 107 | $(CC) $(LDFLAGS) -o $@ $^ $(EMU_LIBS) 108 | 109 | riscv_cpu32.o: riscv_cpu.c 110 | $(CC) $(CFLAGS) -DMAX_XLEN=32 -c -o $@ $< 111 | 112 | riscv_cpu64.o: riscv_cpu.c 113 | $(CC) $(CFLAGS) -DMAX_XLEN=64 -c -o $@ $< 114 | 115 | riscv_cpu128.o: riscv_cpu.c 116 | $(CC) $(CFLAGS) -DMAX_XLEN=128 -c -o $@ $< 117 | 118 | build_filelist: build_filelist.o fs_utils.o cutils.o 119 | $(CC) $(LDFLAGS) -o $@ $^ -lm 120 | 121 | splitimg: splitimg.o 122 | $(CC) $(LDFLAGS) -o $@ $^ 123 | 124 | install: $(PROGS) 125 | $(STRIP) $(PROGS) 126 | $(INSTALL) -m755 $(PROGS) "$(DESTDIR)$(bindir)" 127 | 128 | %.o: %.c 129 | $(CC) $(CFLAGS) -c -o $@ $< 130 | 131 | clean: 132 | rm -f *.o *.d *~ $(PROGS) slirp/*.o slirp/*.d slirp/*~ 133 | 134 | -include $(wildcard *.d) 135 | -include $(wildcard slirp/*.d) 136 | -------------------------------------------------------------------------------- /tinyemu/Makefile.js: -------------------------------------------------------------------------------- 1 | # 2 | # TinyEMU emulator 3 | # 4 | # Copyright (c) 2016-2018 Fabrice Bellard 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | # Build the Javascript version of TinyEMU 26 | EMCC=emcc 27 | EMCFLAGS=-O2 --llvm-opts 2 -Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -MMD -fno-strict-aliasing -DCONFIG_FS_NET 28 | #EMCFLAGS+=-Werror 29 | EMLDFLAGS=-O3 --memory-init-file 0 --closure 0 -s NO_EXIT_RUNTIME=1 -s NO_FILESYSTEM=1 -s "EXPORTED_FUNCTIONS=['_console_queue_char','_vm_start','_fs_import_file','_display_key_event','_display_mouse_event','_display_wheel_event','_net_write_packet','_net_set_carrier']" -s 'EXTRA_EXPORTED_RUNTIME_METHODS=["ccall", "cwrap"]' -s BINARYEN_TRAP_MODE=clamp --js-library js/lib.js 30 | EMLDFLAGS_ASMJS:=$(EMLDFLAGS) -s WASM=0 31 | EMLDFLAGS_WASM:=$(EMLDFLAGS) -s WASM=1 -s TOTAL_MEMORY=67108864 -s ALLOW_MEMORY_GROWTH=1 32 | 33 | PROGS=js/riscvemu32.js js/riscvemu32-wasm.js js/riscvemu64.js js/riscvemu64-wasm.js 34 | 35 | all: $(PROGS) 36 | 37 | JS_OBJS=jsemu.js.o softfp.js.o virtio.js.o fs.js.o fs_net.js.o fs_wget.js.o fs_utils.js.o simplefb.js.o pci.js.o json.js.o block_net.js.o 38 | JS_OBJS+=iomem.js.o cutils.js.o aes.js.o sha256.js.o 39 | 40 | RISCVEMU64_OBJS=$(JS_OBJS) riscv_cpu64.js.o riscv_machine.js.o machine.js.o 41 | RISCVEMU32_OBJS=$(JS_OBJS) riscv_cpu32.js.o riscv_machine.js.o machine.js.o 42 | 43 | js/riscvemu64.js: $(RISCVEMU64_OBJS) js/lib.js 44 | $(EMCC) $(EMLDFLAGS_ASMJS) -o $@ $(RISCVEMU64_OBJS) 45 | 46 | js/riscvemu32.js: $(RISCVEMU32_OBJS) js/lib.js 47 | $(EMCC) $(EMLDFLAGS_ASMJS) -o $@ $(RISCVEMU32_OBJS) 48 | 49 | js/riscvemu64-wasm.js: $(RISCVEMU64_OBJS) js/lib.js 50 | $(EMCC) $(EMLDFLAGS_WASM) -o $@ $(RISCVEMU64_OBJS) 51 | 52 | js/riscvemu32-wasm.js: $(RISCVEMU32_OBJS) js/lib.js 53 | $(EMCC) $(EMLDFLAGS_WASM) -o $@ $(RISCVEMU32_OBJS) 54 | 55 | riscv_cpu32.js.o: riscv_cpu.c 56 | $(EMCC) $(EMCFLAGS) -DMAX_XLEN=32 -DCONFIG_RISCV_MAX_XLEN=32 -c -o $@ $< 57 | 58 | riscv_cpu64.js.o: riscv_cpu.c 59 | $(EMCC) $(EMCFLAGS) -DMAX_XLEN=64 -DCONFIG_RISCV_MAX_XLEN=64 -c -o $@ $< 60 | 61 | 62 | %.js.o: %.c 63 | $(EMCC) $(EMCFLAGS) -c -o $@ $< 64 | 65 | -include $(wildcard *.d) 66 | -------------------------------------------------------------------------------- /tinyemu/Makefile.pdfjs: -------------------------------------------------------------------------------- 1 | # 2 | # TinyEMU emulator 3 | # 4 | # Copyright (c) 2016-2018 Fabrice Bellard 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | # Build the Javascript version of TinyEMU 26 | EMCC=emcc 27 | EMCFLAGS=-O3 --llvm-opts 2 -Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DDEBUG_VIRTIO -MMD -fno-strict-aliasing -DCONFIG_FS_NET 28 | EMCFLAGS+=-Wno-fastcomp -sSINGLE_FILE=1 -g 29 | EMLDFLAGS=-O3 -g --memory-init-file 0 --closure 0 -s NO_EXIT_RUNTIME=1 -s "EXPORTED_FUNCTIONS=['_console_queue_char','_vm_start','_fs_import_file','_display_key_event','_display_mouse_event','_display_wheel_event','_net_write_packet','_net_set_carrier','_virt_machine_run']" -s 'EXTRA_EXPORTED_RUNTIME_METHODS=["ccall", "cwrap", "UTF8ToString", "dynCall"]' -s BINARYEN_TRAP_MODE=clamp --js-library js/lib.js 30 | EMLDFLAGS_ASMJS:=$(EMLDFLAGS) -s WASM=0 -Wno-fastcomp -sSINGLE_FILE=1 -sASSERTIONS=2 -sTOTAL_MEMORY=208mb -sENVIRONMENT=shell 31 | EMLDFLAGS_WASM:=$(EMLDFLAGS) -s WASM=1 -s TOTAL_MEMORY=67108864 -s ALLOW_MEMORY_GROWTH=1 -Wno-fastcomp -sSINGLE_FILE=1 32 | 33 | PROGS=js/riscvemu32.js js/riscvemu32-wasm.js js/riscvemu64.js js/riscvemu64-wasm.js 34 | 35 | all: $(PROGS) 36 | 37 | JS_OBJS=jsemu.js.o softfp.js.o virtio.js.o fs.js.o fs_net.js.o fs_wget.js.o fs_utils.js.o simplefb.js.o pci.js.o json.js.o block_net.js.o 38 | JS_OBJS+=iomem.js.o cutils.js.o aes.js.o sha256.js.o 39 | 40 | RISCVEMU64_OBJS=$(JS_OBJS) riscv_cpu64.js.o riscv_machine.js.o machine.js.o 41 | RISCVEMU32_OBJS=$(JS_OBJS) riscv_cpu32.js.o riscv_machine.js.o machine.js.o 42 | 43 | js/riscvemu64.js: $(RISCVEMU64_OBJS) js/lib.js 44 | $(EMCC) $(EMLDFLAGS_ASMJS) -o $@ $(RISCVEMU64_OBJS) 45 | 46 | js/riscvemu32.js: $(RISCVEMU32_OBJS) js/lib.js 47 | $(EMCC) $(EMLDFLAGS_ASMJS) -o $@ $(RISCVEMU32_OBJS) 48 | 49 | js/riscvemu64-wasm.js: $(RISCVEMU64_OBJS) js/lib.js 50 | $(EMCC) $(EMLDFLAGS_WASM) -o $@ $(RISCVEMU64_OBJS) 51 | 52 | js/riscvemu32-wasm.js: $(RISCVEMU32_OBJS) js/lib.js 53 | $(EMCC) $(EMLDFLAGS_WASM) -o $@ $(RISCVEMU32_OBJS) 54 | 55 | riscv_cpu32.js.o: riscv_cpu.c 56 | $(EMCC) $(EMCFLAGS) -DMAX_XLEN=32 -DCONFIG_RISCV_MAX_XLEN=32 -c -o $@ $< 57 | 58 | riscv_cpu64.js.o: riscv_cpu.c 59 | $(EMCC) $(EMCFLAGS) -DMAX_XLEN=64 -DCONFIG_RISCV_MAX_XLEN=64 -c -o $@ $< 60 | 61 | 62 | %.js.o: %.c 63 | $(EMCC) $(EMCFLAGS) -c -o $@ $< 64 | 65 | -include $(wildcard *.d) 66 | 67 | clean: 68 | rm -rf *.js.d *.js.o js/*.wasm $(PROGS) -------------------------------------------------------------------------------- /tinyemu/VERSION: -------------------------------------------------------------------------------- 1 | 2019-12-21 2 | -------------------------------------------------------------------------------- /tinyemu/aes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenSSL compatible AES header 3 | * 4 | * Copyright (c) 2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef AES_H 25 | #define AES_H 26 | 27 | #define AES_MAXNR 14 28 | #define AES_BLOCK_SIZE 16 29 | 30 | struct aes_key_st { 31 | uint32_t rd_key[4 *(AES_MAXNR + 1)]; 32 | int rounds; 33 | }; 34 | typedef struct aes_key_st AES_KEY; 35 | 36 | int AES_set_encrypt_key(const unsigned char *userKey, const int bits, 37 | AES_KEY *key); 38 | int AES_set_decrypt_key(const unsigned char *userKey, const int bits, 39 | AES_KEY *key); 40 | 41 | void AES_encrypt(const unsigned char *in, unsigned char *out, 42 | const AES_KEY *key); 43 | void AES_decrypt(const unsigned char *in, unsigned char *out, 44 | const AES_KEY *key); 45 | void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, 46 | const unsigned long length, const AES_KEY *key, 47 | unsigned char *ivec, const int enc); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /tinyemu/cutils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Misc C utilities 3 | * 4 | * Copyright (c) 2016-2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "cutils.h" 34 | 35 | void *mallocz(size_t size) 36 | { 37 | void *ptr; 38 | ptr = malloc(size); 39 | if (!ptr) 40 | return NULL; 41 | memset(ptr, 0, size); 42 | return ptr; 43 | } 44 | 45 | void pstrcpy(char *buf, int buf_size, const char *str) 46 | { 47 | int c; 48 | char *q = buf; 49 | 50 | if (buf_size <= 0) 51 | return; 52 | 53 | for(;;) { 54 | c = *str++; 55 | if (c == 0 || q >= buf + buf_size - 1) 56 | break; 57 | *q++ = c; 58 | } 59 | *q = '\0'; 60 | } 61 | 62 | char *pstrcat(char *buf, int buf_size, const char *s) 63 | { 64 | int len; 65 | len = strlen(buf); 66 | if (len < buf_size) 67 | pstrcpy(buf + len, buf_size - len, s); 68 | return buf; 69 | } 70 | 71 | int strstart(const char *str, const char *val, const char **ptr) 72 | { 73 | const char *p, *q; 74 | p = str; 75 | q = val; 76 | while (*q != '\0') { 77 | if (*p != *q) 78 | return 0; 79 | p++; 80 | q++; 81 | } 82 | if (ptr) 83 | *ptr = p; 84 | return 1; 85 | } 86 | 87 | void dbuf_init(DynBuf *s) 88 | { 89 | memset(s, 0, sizeof(*s)); 90 | } 91 | 92 | void dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len) 93 | { 94 | size_t end, new_size; 95 | new_size = end = offset + len; 96 | if (new_size > s->allocated_size) { 97 | new_size = max_int(new_size, s->allocated_size * 3 / 2); 98 | s->buf = realloc(s->buf, new_size); 99 | s->allocated_size = new_size; 100 | } 101 | memcpy(s->buf + offset, data, len); 102 | if (end > s->size) 103 | s->size = end; 104 | } 105 | 106 | void dbuf_putc(DynBuf *s, uint8_t c) 107 | { 108 | dbuf_write(s, s->size, &c, 1); 109 | } 110 | 111 | void dbuf_putstr(DynBuf *s, const char *str) 112 | { 113 | dbuf_write(s, s->size, (const uint8_t *)str, strlen(str)); 114 | } 115 | 116 | void dbuf_free(DynBuf *s) 117 | { 118 | free(s->buf); 119 | memset(s, 0, sizeof(*s)); 120 | } 121 | -------------------------------------------------------------------------------- /tinyemu/cutils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * C utilities 3 | * 4 | * Copyright (c) 2016 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef CUTILS_H 25 | #define CUTILS_H 26 | 27 | #include 28 | 29 | #define likely(x) __builtin_expect(!!(x), 1) 30 | #define unlikely(x) __builtin_expect(!!(x), 0) 31 | #define force_inline inline __attribute__((always_inline)) 32 | #define no_inline __attribute__((noinline)) 33 | #define __maybe_unused __attribute__((unused)) 34 | 35 | #define xglue(x, y) x ## y 36 | #define glue(x, y) xglue(x, y) 37 | #define stringify(s) tostring(s) 38 | #define tostring(s) #s 39 | 40 | #ifndef offsetof 41 | #define offsetof(type, field) ((size_t) &((type *)0)->field) 42 | #endif 43 | #define countof(x) (sizeof(x) / sizeof(x[0])) 44 | 45 | #define DLL_PUBLIC __attribute__ ((visibility ("default"))) 46 | 47 | #ifndef _BOOL_defined 48 | #define _BOOL_defined 49 | #undef FALSE 50 | #undef TRUE 51 | 52 | typedef int BOOL; 53 | enum { 54 | FALSE = 0, 55 | TRUE = 1, 56 | }; 57 | #endif 58 | 59 | /* this test works at least with gcc */ 60 | #if defined(__SIZEOF_INT128__) 61 | #define HAVE_INT128 62 | #endif 63 | 64 | #ifdef HAVE_INT128 65 | typedef __int128 int128_t; 66 | typedef unsigned __int128 uint128_t; 67 | #endif 68 | 69 | static inline int max_int(int a, int b) 70 | { 71 | if (a > b) 72 | return a; 73 | else 74 | return b; 75 | } 76 | 77 | static inline int min_int(int a, int b) 78 | { 79 | if (a < b) 80 | return a; 81 | else 82 | return b; 83 | } 84 | 85 | void *mallocz(size_t size); 86 | 87 | #if defined(_WIN32) 88 | static inline uint32_t bswap_32(uint32_t v) 89 | { 90 | return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) | 91 | ((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24); 92 | } 93 | #else 94 | #include 95 | #endif 96 | 97 | static inline uint16_t get_le16(const uint8_t *ptr) 98 | { 99 | return ptr[0] | (ptr[1] << 8); 100 | } 101 | 102 | static inline uint32_t get_le32(const uint8_t *ptr) 103 | { 104 | return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); 105 | } 106 | 107 | static inline uint64_t get_le64(const uint8_t *ptr) 108 | { 109 | return get_le32(ptr) | ((uint64_t)get_le32(ptr + 4) << 32); 110 | } 111 | 112 | static inline void put_le16(uint8_t *ptr, uint16_t v) 113 | { 114 | ptr[0] = v; 115 | ptr[1] = v >> 8; 116 | } 117 | 118 | static inline void put_le32(uint8_t *ptr, uint32_t v) 119 | { 120 | ptr[0] = v; 121 | ptr[1] = v >> 8; 122 | ptr[2] = v >> 16; 123 | ptr[3] = v >> 24; 124 | } 125 | 126 | static inline void put_le64(uint8_t *ptr, uint64_t v) 127 | { 128 | put_le32(ptr, v); 129 | put_le32(ptr + 4, v >> 32); 130 | } 131 | 132 | static inline uint32_t get_be32(const uint8_t *d) 133 | { 134 | return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3]; 135 | } 136 | 137 | static inline void put_be32(uint8_t *d, uint32_t v) 138 | { 139 | d[0] = v >> 24; 140 | d[1] = v >> 16; 141 | d[2] = v >> 8; 142 | d[3] = v >> 0; 143 | } 144 | 145 | static inline void put_be64(uint8_t *d, uint64_t v) 146 | { 147 | put_be32(d, v >> 32); 148 | put_be32(d + 4, v); 149 | } 150 | 151 | #ifdef WORDS_BIGENDIAN 152 | static inline uint32_t cpu_to_be32(uint32_t v) 153 | { 154 | return v; 155 | } 156 | #else 157 | static inline uint32_t cpu_to_be32(uint32_t v) 158 | { 159 | return bswap_32(v); 160 | } 161 | #endif 162 | 163 | /* XXX: optimize */ 164 | static inline int ctz32(uint32_t a) 165 | { 166 | int i; 167 | if (a == 0) 168 | return 32; 169 | for(i = 0; i < 32; i++) { 170 | if ((a >> i) & 1) 171 | return i; 172 | } 173 | return 32; 174 | } 175 | 176 | 177 | void *mallocz(size_t size); 178 | void pstrcpy(char *buf, int buf_size, const char *str); 179 | char *pstrcat(char *buf, int buf_size, const char *s); 180 | int strstart(const char *str, const char *val, const char **ptr); 181 | 182 | typedef struct { 183 | uint8_t *buf; 184 | size_t size; 185 | size_t allocated_size; 186 | } DynBuf; 187 | 188 | void dbuf_init(DynBuf *s); 189 | void dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len); 190 | void dbuf_putc(DynBuf *s, uint8_t c); 191 | void dbuf_putstr(DynBuf *s, const char *str); 192 | void dbuf_free(DynBuf *s); 193 | 194 | #endif /* CUTILS_H */ 195 | -------------------------------------------------------------------------------- /tinyemu/fbuf.h: -------------------------------------------------------------------------------- 1 | #ifndef FBUF_H 2 | #define FBUF_H 3 | 4 | typedef struct { 5 | #if defined(EMSCRIPTEN) 6 | int handle; 7 | #else 8 | uint8_t *data; 9 | #endif 10 | size_t allocated_size; 11 | } FileBuffer; 12 | 13 | void file_buffer_init(FileBuffer *bs); 14 | void file_buffer_reset(FileBuffer *bs); 15 | int file_buffer_resize(FileBuffer *bs, size_t new_size); 16 | void file_buffer_write(FileBuffer *bs, size_t offset, const uint8_t *buf, 17 | size_t size); 18 | void file_buffer_set(FileBuffer *bs, size_t offset, int val, size_t size); 19 | void file_buffer_read(FileBuffer *bs, size_t offset, uint8_t *buf, 20 | size_t size); 21 | 22 | #endif /* FBUF_H */ 23 | -------------------------------------------------------------------------------- /tinyemu/fs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filesystem utilities 3 | * 4 | * Copyright (c) 2016 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "cutils.h" 32 | #include "fs.h" 33 | 34 | FSFile *fs_dup(FSDevice *fs, FSFile *f) 35 | { 36 | FSQID qid; 37 | fs->fs_walk(fs, &f, &qid, f, 0, NULL); 38 | return f; 39 | } 40 | 41 | FSFile *fs_walk_path1(FSDevice *fs, FSFile *f, const char *path, 42 | char **pname) 43 | { 44 | const char *p; 45 | char *name; 46 | FSFile *f1; 47 | FSQID qid; 48 | int len, ret; 49 | BOOL is_last, is_first; 50 | 51 | if (path[0] == '/') 52 | path++; 53 | 54 | is_first = TRUE; 55 | for(;;) { 56 | p = strchr(path, '/'); 57 | if (!p) { 58 | name = (char *)path; 59 | if (pname) { 60 | *pname = name; 61 | if (is_first) { 62 | ret = fs->fs_walk(fs, &f, &qid, f, 0, NULL); 63 | if (ret < 0) 64 | f = NULL; 65 | } 66 | return f; 67 | } 68 | is_last = TRUE; 69 | } else { 70 | len = p - path; 71 | name = malloc(len + 1); 72 | memcpy(name, path, len); 73 | name[len] = '\0'; 74 | is_last = FALSE; 75 | } 76 | ret = fs->fs_walk(fs, &f1, &qid, f, 1, &name); 77 | if (!is_last) 78 | free(name); 79 | if (!is_first) 80 | fs->fs_delete(fs, f); 81 | f = f1; 82 | is_first = FALSE; 83 | if (ret <= 0) { 84 | fs->fs_delete(fs, f); 85 | f = NULL; 86 | break; 87 | } else if (is_last) { 88 | break; 89 | } 90 | path = p + 1; 91 | } 92 | return f; 93 | } 94 | 95 | FSFile *fs_walk_path(FSDevice *fs, FSFile *f, const char *path) 96 | { 97 | return fs_walk_path1(fs, f, path, NULL); 98 | } 99 | 100 | void fs_end(FSDevice *fs) 101 | { 102 | fs->fs_end(fs); 103 | free(fs); 104 | } 105 | -------------------------------------------------------------------------------- /tinyemu/fs_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Misc FS utilities 3 | * 4 | * Copyright (c) 2016-2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #define HEAD_FILENAME "head" 25 | #define ROOT_FILENAME "files" 26 | 27 | #define FILEID_SIZE_MAX 32 28 | 29 | #define FS_KEY_LEN 16 30 | 31 | /* default block size to determine the total filesytem size */ 32 | #define FS_BLOCK_SIZE_LOG2 12 33 | #define FS_BLOCK_SIZE (1 << FS_BLOCK_SIZE_LOG2) 34 | 35 | typedef enum { 36 | FS_ERR_OK = 0, 37 | FS_ERR_GENERIC = -1, 38 | FS_ERR_SYNTAX = -2, 39 | FS_ERR_REVISION = -3, 40 | FS_ERR_FILE_ID = -4, 41 | FS_ERR_IO = -5, 42 | FS_ERR_NOENT = -6, 43 | FS_ERR_COUNTERS = -7, 44 | FS_ERR_QUOTA = -8, 45 | FS_ERR_PROTOCOL_VERSION = -9, 46 | FS_ERR_HEAD = -10, 47 | } FSCommitErrorCode; 48 | 49 | typedef uint64_t FSFileID; 50 | 51 | static inline BOOL isspace_nolf(int c) 52 | { 53 | return (c == ' ' || c == '\t'); 54 | } 55 | 56 | static inline int from_hex(int c) 57 | { 58 | if (c >= '0' && c <= '9') 59 | return c - '0'; 60 | else if (c >= 'A' && c <= 'F') 61 | return c - 'A' + 10; 62 | else if (c >= 'a' && c <= 'f') 63 | return c - 'a' + 10; 64 | else 65 | return -1; 66 | } 67 | 68 | static inline uint64_t block_align(uint64_t val, uint64_t align) 69 | { 70 | return (val + align - 1) & ~(align - 1); 71 | } 72 | 73 | void pstrcpy(char *buf, int buf_size, const char *str); 74 | char *pstrcat(char *buf, int buf_size, const char *s); 75 | char *compose_path(const char *path, const char *name); 76 | char *compose_url(const char *base_url, const char *name); 77 | void skip_line(const char **pp); 78 | char *quoted_str(const char *str); 79 | int parse_fname(char *buf, int buf_size, const char **pp); 80 | int parse_uint32_base(uint32_t *pval, const char **pp, int base); 81 | int parse_uint64_base(uint64_t *pval, const char **pp, int base); 82 | int parse_uint64(uint64_t *pval, const char **pp); 83 | int parse_uint32(uint32_t *pval, const char **pp); 84 | int parse_time(uint32_t *psec, uint32_t *pnsec, const char **pp); 85 | int parse_file_id(FSFileID *pval, const char **pp); 86 | char *file_id_to_filename(char *buf, FSFileID file_id); 87 | void encode_hex(char *str, const uint8_t *buf, int len); 88 | int decode_hex(uint8_t *buf, const char *str, int len); 89 | BOOL is_url(const char *path); 90 | 91 | const char *skip_header(const char *p); 92 | int parse_tag(char *buf, int buf_size, const char *str, const char *tag); 93 | int parse_tag_uint64(uint64_t *pval, const char *str, const char *tag); 94 | int parse_tag_file_id(FSFileID *pval, const char *str, const char *tag); 95 | int parse_tag_version(const char *str); 96 | -------------------------------------------------------------------------------- /tinyemu/fs_wget.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HTTP file download 3 | * 4 | * Copyright (c) 2016-2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #if defined(EMSCRIPTEN) 25 | #define USE_BUILTIN_CRYPTO 26 | #endif 27 | 28 | #ifdef USE_BUILTIN_CRYPTO 29 | #include "aes.h" 30 | #include "sha256.h" 31 | #else 32 | #include 33 | #include 34 | #include 35 | #endif 36 | #ifdef _WIN32 37 | #include 38 | #endif 39 | 40 | #define LOG() printf("%s:%d\n", __func__, __LINE__) 41 | 42 | /* XHR */ 43 | 44 | /* err < 0: error (no data provided) 45 | err = 0: end of transfer (data can be provided too) 46 | err = 1: data chunk 47 | */ 48 | typedef void WGetWriteCallback(void *opaque, int err, void *data, size_t size); 49 | typedef size_t WGetReadCallback(void *opaque, void *data, size_t size); 50 | typedef struct XHRState XHRState; 51 | 52 | XHRState *fs_wget(const char *url, const char *user, const char *password, 53 | void *opaque, WGetWriteCallback *cb, BOOL single_write); 54 | void fs_wget_free(XHRState *s); 55 | 56 | void fs_wget_init(void); 57 | void fs_wget_end(void); 58 | 59 | #ifndef EMSCRIPTEN 60 | typedef BOOL FSNetEventLoopCompletionFunc(void *opaque); 61 | void fs_net_set_fdset(int *pfd_max, fd_set *rfds, fd_set *wfds, fd_set *efds, 62 | int *ptimeout); 63 | void fs_net_event_loop(FSNetEventLoopCompletionFunc *cb, void *opaque); 64 | #endif 65 | 66 | /* crypto */ 67 | 68 | extern const uint8_t encrypted_file_magic[4]; 69 | 70 | typedef int DecryptFileCB(void *opaque, const uint8_t *data, size_t len); 71 | typedef struct DecryptFileState DecryptFileState; 72 | 73 | DecryptFileState *decrypt_file_init(AES_KEY *aes_state, 74 | DecryptFileCB *write_cb, 75 | void *opaque); 76 | int decrypt_file(DecryptFileState *s, const uint8_t *data, 77 | size_t size); 78 | int decrypt_file_flush(DecryptFileState *s); 79 | void decrypt_file_end(DecryptFileState *s); 80 | 81 | void pbkdf2_hmac_sha256(const uint8_t *pwd, int pwd_len, 82 | const uint8_t *salt, int salt_len, 83 | int iter, int key_len, uint8_t *out); 84 | 85 | /* XHR file */ 86 | 87 | typedef void FSWGetFileCB(FSDevice *fs, FSFile *f, int64_t size, void *opaque); 88 | 89 | void fs_wget_file2(FSDevice *fs, FSFile *f, const char *url, 90 | const char *user, const char *password, 91 | FSFile *posted_file, uint64_t post_data_len, 92 | FSWGetFileCB *cb, void *opaque, 93 | AES_KEY *aes_state); 94 | -------------------------------------------------------------------------------- /tinyemu/ide.h: -------------------------------------------------------------------------------- 1 | /* 2 | * IDE emulation 3 | * 4 | * Copyright (c) 2003-2016 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include "virtio.h" 25 | #include "iomem.h" 26 | #include "pci.h" 27 | 28 | typedef struct IDEIFState IDEIFState; 29 | 30 | IDEIFState *ide_init(PhysMemoryMap *port_map, uint32_t addr, uint32_t addr2, 31 | IRQSignal *irq, BlockDevice **tab_bs); 32 | PCIDevice *piix3_ide_init(PCIBus *pci_bus, int devfn); 33 | -------------------------------------------------------------------------------- /tinyemu/iomem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * IO memory handling 3 | * 4 | * Copyright (c) 2016-2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef IOMEM_H 25 | #define IOMEM_H 26 | 27 | typedef void DeviceWriteFunc(void *opaque, uint32_t offset, 28 | uint32_t val, int size_log2); 29 | typedef uint32_t DeviceReadFunc(void *opaque, uint32_t offset, int size_log2); 30 | 31 | #define DEVIO_SIZE8 (1 << 0) 32 | #define DEVIO_SIZE16 (1 << 1) 33 | #define DEVIO_SIZE32 (1 << 2) 34 | /* not supported, could add specific 64 bit callbacks when needed */ 35 | //#define DEVIO_SIZE64 (1 << 3) 36 | #define DEVIO_DISABLED (1 << 4) 37 | 38 | #define DEVRAM_FLAG_ROM (1 << 0) /* not writable */ 39 | #define DEVRAM_FLAG_DIRTY_BITS (1 << 1) /* maintain dirty bits */ 40 | #define DEVRAM_FLAG_DISABLED (1 << 2) /* allocated but not mapped */ 41 | #define DEVRAM_PAGE_SIZE_LOG2 12 42 | #define DEVRAM_PAGE_SIZE (1 << DEVRAM_PAGE_SIZE_LOG2) 43 | 44 | typedef struct PhysMemoryMap PhysMemoryMap; 45 | 46 | typedef struct { 47 | PhysMemoryMap *map; 48 | uint64_t addr; 49 | uint64_t org_size; /* original size */ 50 | uint64_t size; /* =org_size or 0 if the mapping is disabled */ 51 | BOOL is_ram; 52 | /* the following is used for RAM access */ 53 | int devram_flags; 54 | uint8_t *phys_mem; 55 | int dirty_bits_size; /* in bytes */ 56 | uint32_t *dirty_bits; /* NULL if not used */ 57 | uint32_t *dirty_bits_tab[2]; 58 | int dirty_bits_index; /* 0-1 */ 59 | /* the following is used for I/O access */ 60 | void *opaque; 61 | DeviceReadFunc *read_func; 62 | DeviceWriteFunc *write_func; 63 | int devio_flags; 64 | } PhysMemoryRange; 65 | 66 | #define PHYS_MEM_RANGE_MAX 32 67 | 68 | struct PhysMemoryMap { 69 | int n_phys_mem_range; 70 | PhysMemoryRange phys_mem_range[PHYS_MEM_RANGE_MAX]; 71 | PhysMemoryRange *(*register_ram)(PhysMemoryMap *s, uint64_t addr, 72 | uint64_t size, int devram_flags); 73 | void (*free_ram)(PhysMemoryMap *s, PhysMemoryRange *pr); 74 | const uint32_t *(*get_dirty_bits)(PhysMemoryMap *s, PhysMemoryRange *pr); 75 | void (*set_ram_addr)(PhysMemoryMap *s, PhysMemoryRange *pr, uint64_t addr, 76 | BOOL enabled); 77 | void *opaque; 78 | void (*flush_tlb_write_range)(void *opaque, uint8_t *ram_addr, 79 | size_t ram_size); 80 | }; 81 | 82 | 83 | PhysMemoryMap *phys_mem_map_init(void); 84 | void phys_mem_map_end(PhysMemoryMap *s); 85 | PhysMemoryRange *register_ram_entry(PhysMemoryMap *s, uint64_t addr, 86 | uint64_t size, int devram_flags); 87 | static inline PhysMemoryRange *cpu_register_ram(PhysMemoryMap *s, uint64_t addr, 88 | uint64_t size, int devram_flags) 89 | { 90 | return s->register_ram(s, addr, size, devram_flags); 91 | } 92 | PhysMemoryRange *cpu_register_device(PhysMemoryMap *s, uint64_t addr, 93 | uint64_t size, void *opaque, 94 | DeviceReadFunc *read_func, DeviceWriteFunc *write_func, 95 | int devio_flags); 96 | PhysMemoryRange *get_phys_mem_range(PhysMemoryMap *s, uint64_t paddr); 97 | void phys_mem_set_addr(PhysMemoryRange *pr, uint64_t addr, BOOL enabled); 98 | 99 | static inline const uint32_t *phys_mem_get_dirty_bits(PhysMemoryRange *pr) 100 | { 101 | PhysMemoryMap *map = pr->map; 102 | return map->get_dirty_bits(map, pr); 103 | } 104 | 105 | static inline void phys_mem_set_dirty_bit(PhysMemoryRange *pr, size_t offset) 106 | { 107 | size_t page_index; 108 | uint32_t mask, *dirty_bits_ptr; 109 | if (pr->dirty_bits) { 110 | page_index = offset >> DEVRAM_PAGE_SIZE_LOG2; 111 | mask = 1 << (page_index & 0x1f); 112 | dirty_bits_ptr = pr->dirty_bits + (page_index >> 5); 113 | *dirty_bits_ptr |= mask; 114 | } 115 | } 116 | 117 | static inline BOOL phys_mem_is_dirty_bit(PhysMemoryRange *pr, size_t offset) 118 | { 119 | size_t page_index; 120 | uint32_t *dirty_bits_ptr; 121 | if (!pr->dirty_bits) 122 | return TRUE; 123 | page_index = offset >> DEVRAM_PAGE_SIZE_LOG2; 124 | dirty_bits_ptr = pr->dirty_bits + (page_index >> 5); 125 | return (*dirty_bits_ptr >> (page_index & 0x1f)) & 1; 126 | } 127 | 128 | void phys_mem_reset_dirty_bit(PhysMemoryRange *pr, size_t offset); 129 | uint8_t *phys_mem_get_ram_ptr(PhysMemoryMap *map, uint64_t paddr, BOOL is_rw); 130 | 131 | /* IRQ support */ 132 | 133 | typedef void SetIRQFunc(void *opaque, int irq_num, int level); 134 | 135 | typedef struct { 136 | SetIRQFunc *set_irq; 137 | void *opaque; 138 | int irq_num; 139 | } IRQSignal; 140 | 141 | void irq_init(IRQSignal *irq, SetIRQFunc *set_irq, void *opaque, int irq_num); 142 | 143 | static inline void set_irq(IRQSignal *irq, int level) 144 | { 145 | irq->set_irq(irq->opaque, irq->irq_num, level); 146 | } 147 | 148 | #endif /* IOMEM_H */ 149 | -------------------------------------------------------------------------------- /tinyemu/json.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Pseudo JSON parser 3 | * 4 | * Copyright (c) 2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef JSON_H 25 | #define JSON_H 26 | 27 | typedef enum { 28 | JSON_STR, 29 | JSON_INT, 30 | JSON_OBJ, 31 | JSON_ARRAY, 32 | JSON_BOOL, 33 | JSON_NULL, 34 | JSON_UNDEFINED, 35 | JSON_EXCEPTION, 36 | } JSONTypeEnum; 37 | 38 | typedef struct { 39 | int len; 40 | char data[0]; 41 | } JSONString; 42 | 43 | typedef struct JSONValue { 44 | JSONTypeEnum type; 45 | union { 46 | JSONString *str; 47 | int int32; 48 | BOOL b; 49 | struct JSONObject *obj; 50 | struct JSONArray *array; 51 | } u; 52 | } JSONValue; 53 | 54 | typedef struct JSONProperty { 55 | JSONValue name; 56 | JSONValue value; 57 | } JSONProperty; 58 | 59 | typedef struct JSONObject { 60 | int len; 61 | int size; 62 | JSONProperty *props; 63 | } JSONObject; 64 | 65 | typedef struct JSONArray { 66 | int len; 67 | int size; 68 | JSONValue *tab; 69 | } JSONArray; 70 | 71 | JSONValue json_string_new2(const char *str, int len); 72 | JSONValue json_string_new(const char *str); 73 | JSONValue __attribute__((format(printf, 1, 2))) json_error_new(const char *fmt, ...); 74 | void json_free(JSONValue val); 75 | 76 | JSONValue json_object_new(void); 77 | JSONValue json_object_get(JSONValue val, const char *name); 78 | int json_object_set(JSONValue val, const char *name, JSONValue prop_val); 79 | 80 | JSONValue json_array_new(void); 81 | JSONValue json_array_get(JSONValue val, unsigned int idx); 82 | int json_array_set(JSONValue val, unsigned int idx, JSONValue prop_val); 83 | 84 | static inline BOOL json_is_error(JSONValue val) 85 | { 86 | return val.type == JSON_EXCEPTION; 87 | } 88 | 89 | static inline BOOL json_is_undefined(JSONValue val) 90 | { 91 | return val.type == JSON_UNDEFINED; 92 | } 93 | 94 | static inline JSONValue json_undefined_new(void) 95 | { 96 | JSONValue val; 97 | val.type = JSON_UNDEFINED; 98 | val.u.int32 = 0; 99 | return val; 100 | } 101 | 102 | static inline JSONValue json_null_new(void) 103 | { 104 | JSONValue val; 105 | val.type = JSON_NULL; 106 | val.u.int32 = 0; 107 | return val; 108 | } 109 | 110 | static inline JSONValue json_int32_new(int v) 111 | { 112 | JSONValue val; 113 | val.type = JSON_INT; 114 | val.u.int32 = v; 115 | return val; 116 | } 117 | 118 | static inline JSONValue json_bool_new(BOOL v) 119 | { 120 | JSONValue val; 121 | val.type = JSON_BOOL; 122 | val.u.b = v; 123 | return val; 124 | } 125 | 126 | const char *json_get_str(JSONValue val); 127 | const char *json_get_error(JSONValue val); 128 | 129 | JSONValue json_parse_value(const char *p); 130 | JSONValue json_parse_value_len(const char *p, int len); 131 | 132 | #endif /* JSON_H */ 133 | -------------------------------------------------------------------------------- /tinyemu/list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Linux klist like system 3 | * 4 | * Copyright (c) 2016-2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef LIST_H 25 | #define LIST_H 26 | 27 | struct list_head { 28 | struct list_head *prev; 29 | struct list_head *next; 30 | }; 31 | 32 | /* return the pointer of type 'type *' containing 'el' as field 'member' */ 33 | #define list_entry(el, type, member) \ 34 | ((type *)((uint8_t *)(el) - offsetof(type, member))) 35 | 36 | static inline void init_list_head(struct list_head *head) 37 | { 38 | head->prev = head; 39 | head->next = head; 40 | } 41 | 42 | /* insert 'el' between 'prev' and 'next' */ 43 | static inline void __list_add(struct list_head *el, 44 | struct list_head *prev, struct list_head *next) 45 | { 46 | prev->next = el; 47 | el->prev = prev; 48 | el->next = next; 49 | next->prev = el; 50 | } 51 | 52 | /* add 'el' at the head of the list 'head' (= after element head) */ 53 | static inline void list_add(struct list_head *el, struct list_head *head) 54 | { 55 | __list_add(el, head, head->next); 56 | } 57 | 58 | /* add 'el' at the end of the list 'head' (= before element head) */ 59 | static inline void list_add_tail(struct list_head *el, struct list_head *head) 60 | { 61 | __list_add(el, head->prev, head); 62 | } 63 | 64 | static inline void list_del(struct list_head *el) 65 | { 66 | struct list_head *prev, *next; 67 | prev = el->prev; 68 | next = el->next; 69 | prev->next = next; 70 | next->prev = prev; 71 | el->prev = NULL; /* fail safe */ 72 | el->next = NULL; /* fail safe */ 73 | } 74 | 75 | static inline int list_empty(struct list_head *el) 76 | { 77 | return el->next == el; 78 | } 79 | 80 | #define list_for_each(el, head) \ 81 | for(el = (head)->next; el != (head); el = el->next) 82 | 83 | #define list_for_each_safe(el, el1, head) \ 84 | for(el = (head)->next, el1 = el->next; el != (head); \ 85 | el = el1, el1 = el->next) 86 | 87 | #define list_for_each_prev(el, head) \ 88 | for(el = (head)->prev; el != (head); el = el->prev) 89 | 90 | #define list_for_each_prev_safe(el, el1, head) \ 91 | for(el = (head)->prev, el1 = el->prev; el != (head); \ 92 | el = el1, el1 = el->prev) 93 | 94 | #endif /* LIST_H */ 95 | -------------------------------------------------------------------------------- /tinyemu/machine.h: -------------------------------------------------------------------------------- 1 | /* 2 | * VM definitions 3 | * 4 | * Copyright (c) 2016-2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include "json.h" 25 | 26 | typedef struct FBDevice FBDevice; 27 | 28 | typedef void SimpleFBDrawFunc(FBDevice *fb_dev, void *opaque, 29 | int x, int y, int w, int h); 30 | 31 | struct FBDevice { 32 | /* the following is set by the device */ 33 | int width; 34 | int height; 35 | int stride; /* current stride in bytes */ 36 | uint8_t *fb_data; /* current pointer to the pixel data */ 37 | int fb_size; /* frame buffer memory size (info only) */ 38 | void *device_opaque; 39 | void (*refresh)(struct FBDevice *fb_dev, 40 | SimpleFBDrawFunc *redraw_func, void *opaque); 41 | }; 42 | 43 | #define MAX_DRIVE_DEVICE 4 44 | #define MAX_FS_DEVICE 4 45 | #define MAX_ETH_DEVICE 1 46 | 47 | #define VM_CONFIG_VERSION 1 48 | 49 | typedef enum { 50 | VM_FILE_BIOS, 51 | VM_FILE_VGA_BIOS, 52 | VM_FILE_KERNEL, 53 | VM_FILE_INITRD, 54 | 55 | VM_FILE_COUNT, 56 | } VMFileTypeEnum; 57 | 58 | typedef struct { 59 | char *filename; 60 | uint8_t *buf; 61 | int len; 62 | } VMFileEntry; 63 | 64 | typedef struct { 65 | char *device; 66 | char *filename; 67 | BlockDevice *block_dev; 68 | } VMDriveEntry; 69 | 70 | typedef struct { 71 | char *device; 72 | char *tag; /* 9p mount tag */ 73 | char *filename; 74 | FSDevice *fs_dev; 75 | } VMFSEntry; 76 | 77 | typedef struct { 78 | char *driver; 79 | char *ifname; 80 | EthernetDevice *net; 81 | } VMEthEntry; 82 | 83 | typedef struct VirtMachineClass VirtMachineClass; 84 | 85 | typedef struct { 86 | char *cfg_filename; 87 | const VirtMachineClass *vmc; 88 | char *machine_name; 89 | uint64_t ram_size; 90 | BOOL rtc_real_time; 91 | BOOL rtc_local_time; 92 | char *display_device; /* NULL means no display */ 93 | int width, height; /* graphic width & height */ 94 | CharacterDevice *console; 95 | VMDriveEntry tab_drive[MAX_DRIVE_DEVICE]; 96 | int drive_count; 97 | VMFSEntry tab_fs[MAX_FS_DEVICE]; 98 | int fs_count; 99 | VMEthEntry tab_eth[MAX_ETH_DEVICE]; 100 | int eth_count; 101 | 102 | char *cmdline; /* bios or kernel command line */ 103 | BOOL accel_enable; /* enable acceleration (KVM) */ 104 | char *input_device; /* NULL means no input */ 105 | 106 | /* kernel, bios and other auxiliary files */ 107 | VMFileEntry files[VM_FILE_COUNT]; 108 | } VirtMachineParams; 109 | 110 | typedef struct VirtMachine { 111 | const VirtMachineClass *vmc; 112 | /* network */ 113 | EthernetDevice *net; 114 | /* console */ 115 | VIRTIODevice *console_dev; 116 | CharacterDevice *console; 117 | /* graphics */ 118 | FBDevice *fb_dev; 119 | } VirtMachine; 120 | 121 | struct VirtMachineClass { 122 | const char *machine_names; 123 | void (*virt_machine_set_defaults)(VirtMachineParams *p); 124 | VirtMachine *(*virt_machine_init)(const VirtMachineParams *p); 125 | void (*virt_machine_end)(VirtMachine *s); 126 | int (*virt_machine_get_sleep_duration)(VirtMachine *s, int delay); 127 | void (*virt_machine_interp)(VirtMachine *s, int max_exec_cycle); 128 | BOOL (*vm_mouse_is_absolute)(VirtMachine *s); 129 | void (*vm_send_mouse_event)(VirtMachine *s1, int dx, int dy, int dz, 130 | unsigned int buttons); 131 | void (*vm_send_key_event)(VirtMachine *s1, BOOL is_down, uint16_t key_code); 132 | }; 133 | 134 | extern const VirtMachineClass riscv_machine_class; 135 | extern const VirtMachineClass pc_machine_class; 136 | 137 | void __attribute__((format(printf, 1, 2))) vm_error(const char *fmt, ...); 138 | int vm_get_int(JSONValue obj, const char *name, int *pval); 139 | int vm_get_int_opt(JSONValue obj, const char *name, int *pval, int def_val); 140 | 141 | void virt_machine_set_defaults(VirtMachineParams *p); 142 | void virt_machine_load_config_file(VirtMachineParams *p, 143 | const char *filename, 144 | void (*start_cb)(void *opaque), 145 | void *opaque); 146 | void vm_add_cmdline(VirtMachineParams *p, const char *cmdline); 147 | char *get_file_path(const char *base_filename, const char *filename); 148 | void virt_machine_free_config(VirtMachineParams *p); 149 | VirtMachine *virt_machine_init(const VirtMachineParams *p); 150 | void virt_machine_end(VirtMachine *s); 151 | static inline int virt_machine_get_sleep_duration(VirtMachine *s, int delay) 152 | { 153 | return s->vmc->virt_machine_get_sleep_duration(s, delay); 154 | } 155 | static inline void virt_machine_interp(VirtMachine *s, int max_exec_cycle) 156 | { 157 | s->vmc->virt_machine_interp(s, max_exec_cycle); 158 | } 159 | static inline BOOL vm_mouse_is_absolute(VirtMachine *s) 160 | { 161 | return s->vmc->vm_mouse_is_absolute(s); 162 | } 163 | static inline void vm_send_mouse_event(VirtMachine *s1, int dx, int dy, int dz, 164 | unsigned int buttons) 165 | { 166 | s1->vmc->vm_send_mouse_event(s1, dx, dy, dz, buttons); 167 | } 168 | static inline void vm_send_key_event(VirtMachine *s1, BOOL is_down, uint16_t key_code) 169 | { 170 | s1->vmc->vm_send_key_event(s1, is_down, key_code); 171 | } 172 | 173 | /* gui */ 174 | void sdl_refresh(VirtMachine *m); 175 | void sdl_init(int width, int height); 176 | 177 | /* simplefb.c */ 178 | typedef struct SimpleFBState SimpleFBState; 179 | SimpleFBState *simplefb_init(PhysMemoryMap *map, uint64_t phys_addr, 180 | FBDevice *fb_dev, int width, int height); 181 | void simplefb_refresh(FBDevice *fb_dev, 182 | SimpleFBDrawFunc *redraw_func, void *opaque, 183 | PhysMemoryRange *mem_range, 184 | int fb_page_count); 185 | 186 | /* vga.c */ 187 | typedef struct VGAState VGAState; 188 | VGAState *pci_vga_init(PCIBus *bus, FBDevice *fb_dev, 189 | int width, int height, 190 | const uint8_t *vga_rom_buf, int vga_rom_size); 191 | 192 | /* block_net.c */ 193 | BlockDevice *block_device_init_http(const char *url, 194 | int max_cache_size_kb, 195 | void (*start_cb)(void *opaque), 196 | void *start_opaque); 197 | -------------------------------------------------------------------------------- /tinyemu/netinit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # RISCVEMU Ethernet bridge and NAT configuration (run with sudo) 4 | # 5 | # Copyright (c) 2017 Fabrice Bellard 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | # THE SOFTWARE. 24 | # 25 | 26 | # host network interface connected to Internet (change it) 27 | internet_ifname="enp0s20f0u1" 28 | 29 | # setup bridge interface 30 | ip link add br0 type bridge 31 | # create and add tap0 interface to bridge 32 | ip tuntap add dev tap0 mode tap user $USER 33 | ip link set tap0 master br0 34 | 35 | ip link set dev br0 up 36 | ip link set dev tap0 up 37 | ifconfig br0 192.168.3.1 38 | 39 | # setup NAT to access to Internet 40 | echo 1 > /proc/sys/net/ipv4/ip_forward 41 | # delete forwarding reject rule if present 42 | #iptables -D FORWARD 1 43 | iptables -t nat -A POSTROUTING -o $internet_ifname -j MASQUERADE 44 | -------------------------------------------------------------------------------- /tinyemu/pci.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple PCI bus driver 3 | * 4 | * Copyright (c) 2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef PCI_H 25 | #define PCI_H 26 | 27 | #include "iomem.h" 28 | 29 | typedef struct PCIBus PCIBus; 30 | typedef struct PCIDevice PCIDevice; 31 | 32 | /* bar type */ 33 | #define PCI_ADDRESS_SPACE_MEM 0x00 34 | #define PCI_ADDRESS_SPACE_IO 0x01 35 | #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08 36 | 37 | #define PCI_ROM_SLOT 6 38 | #define PCI_NUM_REGIONS 7 39 | 40 | /* PCI config addresses */ 41 | #define PCI_VENDOR_ID 0x00 /* 16 bits */ 42 | #define PCI_DEVICE_ID 0x02 /* 16 bits */ 43 | #define PCI_COMMAND 0x04 /* 16 bits */ 44 | #define PCI_COMMAND_IO (1 << 0) 45 | #define PCI_COMMAND_MEMORY (1 << 1) 46 | #define PCI_STATUS 0x06 /* 16 bits */ 47 | #define PCI_STATUS_CAP_LIST (1 << 4) 48 | #define PCI_CLASS_PROG 0x09 49 | #define PCI_SUBSYSTEM_VENDOR_ID 0x2c /* 16 bits */ 50 | #define PCI_SUBSYSTEM_ID 0x2e /* 16 bits */ 51 | #define PCI_CAPABILITY_LIST 0x34 /* 8 bits */ 52 | #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ 53 | #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ 54 | 55 | typedef void PCIBarSetFunc(void *opaque, int bar_num, uint32_t addr, 56 | BOOL enabled); 57 | 58 | PCIDevice *pci_register_device(PCIBus *b, const char *name, int devfn, 59 | uint16_t vendor_id, uint16_t device_id, 60 | uint8_t revision, uint16_t class_id); 61 | PhysMemoryMap *pci_device_get_mem_map(PCIDevice *d); 62 | PhysMemoryMap *pci_device_get_port_map(PCIDevice *d); 63 | void pci_register_bar(PCIDevice *d, unsigned int bar_num, 64 | uint32_t size, int type, 65 | void *opaque, PCIBarSetFunc *bar_set); 66 | IRQSignal *pci_device_get_irq(PCIDevice *d, unsigned int irq_num); 67 | uint8_t *pci_device_get_dma_ptr(PCIDevice *d, uint64_t addr, BOOL is_rw); 68 | void pci_device_set_config8(PCIDevice *d, uint8_t addr, uint8_t val); 69 | void pci_device_set_config16(PCIDevice *d, uint8_t addr, uint16_t val); 70 | int pci_device_get_devfn(PCIDevice *d); 71 | int pci_add_capability(PCIDevice *d, const uint8_t *buf, int size); 72 | 73 | typedef struct I440FXState I440FXState; 74 | 75 | I440FXState *i440fx_init(PCIBus **pbus, int *ppiix3_devfn, 76 | PhysMemoryMap *mem_map, PhysMemoryMap *port_map, 77 | IRQSignal *pic_irqs); 78 | void i440fx_map_interrupts(I440FXState *s, uint8_t *elcr, 79 | const uint8_t *pci_irqs); 80 | 81 | #endif /* PCI_H */ 82 | -------------------------------------------------------------------------------- /tinyemu/ps2.h: -------------------------------------------------------------------------------- 1 | /* ps2.c */ 2 | typedef struct PS2MouseState PS2MouseState; 3 | typedef struct PS2KbdState PS2KbdState; 4 | 5 | PS2KbdState *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg); 6 | PS2MouseState *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg); 7 | void ps2_write_mouse(void *, int val); 8 | void ps2_write_keyboard(void *, int val); 9 | uint32_t ps2_read_data(void *); 10 | void ps2_queue(void *, int b); 11 | void ps2_keyboard_set_translation(void *opaque, int mode); 12 | 13 | void ps2_put_keycode(PS2KbdState *s, BOOL is_down, int keycode); 14 | void ps2_mouse_event(PS2MouseState *s, 15 | int dx, int dy, int dz, int buttons_state); 16 | 17 | /* vmmouse.c */ 18 | typedef struct VMMouseState VMMouseState; 19 | 20 | VMMouseState *vmmouse_init(PS2MouseState *ps2_mouse); 21 | BOOL vmmouse_is_absolute(VMMouseState *s); 22 | void vmmouse_send_mouse_event(VMMouseState *s, int x, int y, int dz, 23 | int buttons); 24 | void vmmouse_handler(VMMouseState *s, uint32_t *regs); 25 | 26 | /* pckbd.c */ 27 | 28 | typedef struct KBDState KBDState; 29 | 30 | KBDState *i8042_init(PS2KbdState **pkbd, 31 | PS2MouseState **pmouse, 32 | PhysMemoryMap *port_map, 33 | IRQSignal *kbd_irq, IRQSignal *mouse_irq, 34 | uint32_t io_base); 35 | -------------------------------------------------------------------------------- /tinyemu/readme.txt: -------------------------------------------------------------------------------- 1 | TinyEMU System Emulator by Fabrice Bellard 2 | ========================================== 3 | 4 | 1) Features 5 | ----------- 6 | 7 | - RISC-V system emulator supporting the RV128IMAFDQC base ISA (user 8 | level ISA version 2.2, priviledged architecture version 1.10) 9 | including: 10 | 11 | - 32/64/128 bit integer registers 12 | - 32/64/128 bit floating point instructions 13 | - Compressed instructions 14 | - dynamic XLEN change 15 | 16 | - x86 system emulator based on KVM 17 | 18 | - VirtIO console, network, block device, input and 9P filesystem 19 | 20 | - Graphical display with SDL 21 | 22 | - JSON configuration file 23 | 24 | - Remote HTTP block device and filesystem 25 | 26 | - small code, easy to modify, no external dependancies 27 | 28 | - Javascript demo version 29 | 30 | 2) Installation 31 | --------------- 32 | 33 | - The libraries libcurl, OpenSSL and SDL should be installed. On a Fedora 34 | system you can do it with: 35 | 36 | sudo dnf install openssl-devel libcurl-devel SDL-devel 37 | 38 | It is possible to compile the programs without these libraries by 39 | commenting CONFIG_FS_NET and/or CONFIG_SDL in the Makefile. 40 | 41 | - Edit the Makefile to disable the 128 bit target if you compile on a 42 | 32 bit host (for the 128 bit RISCV target the compiler must support 43 | the __int128 C extension). 44 | 45 | - Use 'make' to compile the binaries. 46 | 47 | - You can optionally install the program to '/usr/local/bin' with: 48 | 49 | make install 50 | 51 | 3) Usage 52 | -------- 53 | 54 | 3.1 Quick examples 55 | ------------------ 56 | 57 | - Use the VM images available from https://bellard.org/jslinux (no 58 | need to download them): 59 | 60 | Terminal: 61 | 62 | ./temu https://bellard.org/jslinux/buildroot-riscv64.cfg 63 | 64 | Graphical (with SDL): 65 | 66 | ./temu https://bellard.org/jslinux/buildroot-x86-xwin.cfg 67 | 68 | ./temu https://bellard.org/jslinux/win2k.cfg 69 | 70 | - Download the example RISC-V Linux image 71 | (diskimage-linux-riscv-yyyy-mm-dd.tar.gz) and use it: 72 | 73 | ./temu root-riscv64.cfg 74 | 75 | ./temu rv128test/rv128test.cfg 76 | 77 | - Access to your local hard disk (/tmp directory) in the guest: 78 | 79 | ./temu root_9p-riscv64.cfg 80 | 81 | then type: 82 | mount -t 9p /dev/root /mnt 83 | 84 | in the guest. The content of the host '/tmp' directory is visible in '/mnt'. 85 | 86 | 3.2 Invocation 87 | -------------- 88 | 89 | usage: temu [options] config_file 90 | options are: 91 | -m ram_size set the RAM size in MB 92 | -rw allow write access to the disk image (default=snapshot) 93 | -ctrlc the C-c key stops the emulator instead of being sent to the 94 | emulated software 95 | -append cmdline append cmdline to the kernel command line 96 | -no-accel disable VM acceleration (KVM, x86 machine only) 97 | 98 | Console keys: 99 | Press C-a x to exit the emulator, C-a h to get some help. 100 | 101 | 3.3 Network usage 102 | ----------------- 103 | 104 | The easiest way is to use the "user" mode network driver. No specific 105 | configuration is necessary. 106 | 107 | TinyEMU also supports a "tap" network driver to redirect the network 108 | traffic from a VirtIO network adapter. 109 | 110 | You can look at the netinit.sh script to create the tap network 111 | interface and to redirect the virtual traffic to Internet thru a 112 | NAT. The exact configuration may depend on the Linux distribution and 113 | local firewall configuration. 114 | 115 | The VM configuration file must include: 116 | 117 | eth0: { driver: "tap", ifname: "tap0" } 118 | 119 | and configure the network in the guest system with: 120 | 121 | ifconfig eth0 192.168.3.2 122 | route add -net 0.0.0.0 gw 192.168.3.1 eth0 123 | 124 | 3.4 Network filesystem 125 | ---------------------- 126 | 127 | TinyEMU supports the VirtIO 9P filesystem to access local or remote 128 | filesystems. For remote filesystems, it does HTTP requests to download 129 | the files. The protocol is compatible with the vfsync utility. In the 130 | "mount" command, "/dev/rootN" must be used as device name where N is 131 | the index of the filesystem. When N=0 it is omitted. 132 | 133 | The build_filelist tool builds the file list from a root directory. A 134 | simple web server is enough to serve the files. 135 | 136 | The '.preload' file gives a list of files to preload when opening a 137 | given file. 138 | 139 | 3.5 Network block device 140 | ------------------------ 141 | 142 | TinyEMU supports an HTTP block device. The disk image is split into 143 | small files. Use the 'splitimg' utility to generate images. The URL of 144 | the JSON blk.txt file must be provided as disk image filename. 145 | 146 | 4) Technical notes 147 | ------------------ 148 | 149 | 4.1) 128 bit support 150 | 151 | The RISC-V specification does not define all the instruction encodings 152 | for the 128 bit integer and floating point operations. The missing 153 | ones were interpolated from the 32 and 64 ones. 154 | 155 | Unfortunately there is no RISC-V 128 bit toolchain nor OS now 156 | (volunteers for the Linux port ?), so rv128test.bin may be the first 157 | 128 bit code for RISC-V ! 158 | 159 | 4.2) Floating point emulation 160 | 161 | The floating point emulation is bit exact and supports all the 162 | specified instructions for 32, 64 and 128 bit floating point 163 | numbers. It uses the new SoftFP library. 164 | 165 | 4.3) HTIF console 166 | 167 | The standard HTIF console uses registers at variable addresses which 168 | are deduced by loading specific ELF symbols. TinyEMU does not rely on 169 | an ELF loader, so it is much simpler to use registers at fixed 170 | addresses (0x40008000). A small modification was made in the 171 | "riscv-pk" boot loader to support it. The HTIF console is only used to 172 | display boot messages and to power off the virtual system. The OS 173 | should use the VirtIO console. 174 | 175 | 4.4) Javascript version 176 | 177 | The Javascript version (JSLinux) can be compiled with Makefile.js and 178 | emscripten. A complete precompiled and preconfigured demo is available 179 | in the jslinux-yyyy-mm-dd.tar.gz archive (read the readme.txt file 180 | inside the archive). 181 | 182 | 4.5) x86 emulator 183 | 184 | A small x86 emulator is included. It is not really an emulator because 185 | it uses the Linux KVM API to run the x86 code at near native 186 | performance. The x86 emulator uses the same set of VirtIO devices as 187 | the RISCV emulator and is able to run many operating systems. 188 | 189 | The x86 emulator accepts a Linux kernel image (bzImage). No BIOS image 190 | is necessary. 191 | 192 | The x86 emulator comes from my JS/Linux project (2011) which was one 193 | of the first emulator running Linux fully implemented in 194 | Javascript. It is provided to allow easy access to the x86 images 195 | hosted at https://bellard.org/jslinux . 196 | 197 | 198 | 5) License / Credits 199 | -------------------- 200 | 201 | TinyEMU is released under the MIT license. If there is no explicit 202 | license in a file, the license from MIT-LICENSE.txt applies. 203 | 204 | The SLIRP library has its own license (two clause BSD license). 205 | -------------------------------------------------------------------------------- /tinyemu/riscv_cpu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * RISCV CPU emulator 3 | * 4 | * Copyright (c) 2016-2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef RISCV_CPU_H 25 | #define RISCV_CPU_H 26 | 27 | #include 28 | #include "cutils.h" 29 | #include "iomem.h" 30 | 31 | #define MIP_USIP (1 << 0) 32 | #define MIP_SSIP (1 << 1) 33 | #define MIP_HSIP (1 << 2) 34 | #define MIP_MSIP (1 << 3) 35 | #define MIP_UTIP (1 << 4) 36 | #define MIP_STIP (1 << 5) 37 | #define MIP_HTIP (1 << 6) 38 | #define MIP_MTIP (1 << 7) 39 | #define MIP_UEIP (1 << 8) 40 | #define MIP_SEIP (1 << 9) 41 | #define MIP_HEIP (1 << 10) 42 | #define MIP_MEIP (1 << 11) 43 | 44 | typedef struct RISCVCPUState RISCVCPUState; 45 | 46 | typedef struct { 47 | RISCVCPUState *(*riscv_cpu_init)(PhysMemoryMap *mem_map); 48 | void (*riscv_cpu_end)(RISCVCPUState *s); 49 | void (*riscv_cpu_interp)(RISCVCPUState *s, int n_cycles); 50 | uint64_t (*riscv_cpu_get_cycles)(RISCVCPUState *s); 51 | void (*riscv_cpu_set_mip)(RISCVCPUState *s, uint32_t mask); 52 | void (*riscv_cpu_reset_mip)(RISCVCPUState *s, uint32_t mask); 53 | uint32_t (*riscv_cpu_get_mip)(RISCVCPUState *s); 54 | BOOL (*riscv_cpu_get_power_down)(RISCVCPUState *s); 55 | uint32_t (*riscv_cpu_get_misa)(RISCVCPUState *s); 56 | void (*riscv_cpu_flush_tlb_write_range_ram)(RISCVCPUState *s, 57 | uint8_t *ram_ptr, size_t ram_size); 58 | } RISCVCPUClass; 59 | 60 | typedef struct { 61 | const RISCVCPUClass *class_ptr; 62 | } RISCVCPUCommonState; 63 | 64 | int riscv_cpu_get_max_xlen(void); 65 | 66 | extern const RISCVCPUClass riscv_cpu_class32; 67 | extern const RISCVCPUClass riscv_cpu_class64; 68 | extern const RISCVCPUClass riscv_cpu_class128; 69 | 70 | RISCVCPUState *riscv_cpu_init(PhysMemoryMap *mem_map, int max_xlen); 71 | static inline void riscv_cpu_end(RISCVCPUState *s) 72 | { 73 | const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr; 74 | c->riscv_cpu_end(s); 75 | } 76 | static inline void riscv_cpu_interp(RISCVCPUState *s, int n_cycles) 77 | { 78 | const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr; 79 | c->riscv_cpu_interp(s, n_cycles); 80 | } 81 | static inline uint64_t riscv_cpu_get_cycles(RISCVCPUState *s) 82 | { 83 | const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr; 84 | return c->riscv_cpu_get_cycles(s); 85 | } 86 | static inline void riscv_cpu_set_mip(RISCVCPUState *s, uint32_t mask) 87 | { 88 | const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr; 89 | c->riscv_cpu_set_mip(s, mask); 90 | } 91 | static inline void riscv_cpu_reset_mip(RISCVCPUState *s, uint32_t mask) 92 | { 93 | const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr; 94 | c->riscv_cpu_reset_mip(s, mask); 95 | } 96 | static inline uint32_t riscv_cpu_get_mip(RISCVCPUState *s) 97 | { 98 | const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr; 99 | return c->riscv_cpu_get_mip(s); 100 | } 101 | static inline BOOL riscv_cpu_get_power_down(RISCVCPUState *s) 102 | { 103 | const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr; 104 | return c->riscv_cpu_get_power_down(s); 105 | } 106 | static inline uint32_t riscv_cpu_get_misa(RISCVCPUState *s) 107 | { 108 | const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr; 109 | return c->riscv_cpu_get_misa(s); 110 | } 111 | static inline void riscv_cpu_flush_tlb_write_range_ram(RISCVCPUState *s, 112 | uint8_t *ram_ptr, size_t ram_size) 113 | { 114 | const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr; 115 | c->riscv_cpu_flush_tlb_write_range_ram(s, ram_ptr, ram_size); 116 | } 117 | 118 | #endif /* RISCV_CPU_H */ 119 | -------------------------------------------------------------------------------- /tinyemu/sha256.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenSSL compatible SHA256 header 3 | * 4 | * Copyright (c) 2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef SHA256_H 25 | #define SHA256_H 26 | 27 | #define SHA256_DIGEST_LENGTH 32 28 | 29 | typedef struct { 30 | uint64_t length; 31 | uint32_t state[8], curlen; 32 | uint8_t buf[64]; 33 | } SHA256_CTX; 34 | 35 | void SHA256_Init(SHA256_CTX *s); 36 | void SHA256_Update(SHA256_CTX *s, const uint8_t *in, unsigned long inlen); 37 | void SHA256_Final(uint8_t *out, SHA256_CTX *s); 38 | void SHA256(const uint8_t *buf, int buf_len, uint8_t *out); 39 | 40 | #endif /* SHA256_H */ 41 | -------------------------------------------------------------------------------- /tinyemu/simplefb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple frame buffer 3 | * 4 | * Copyright (c) 2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "cutils.h" 32 | #include "iomem.h" 33 | #include "virtio.h" 34 | #include "machine.h" 35 | 36 | //#define DEBUG_VBE 37 | 38 | #define FB_ALLOC_ALIGN 65536 39 | 40 | struct SimpleFBState { 41 | FBDevice *fb_dev; 42 | int fb_page_count; 43 | PhysMemoryRange *mem_range; 44 | }; 45 | 46 | #define MAX_MERGE_DISTANCE 3 47 | 48 | void simplefb_refresh(FBDevice *fb_dev, 49 | SimpleFBDrawFunc *redraw_func, void *opaque, 50 | PhysMemoryRange *mem_range, 51 | int fb_page_count) 52 | { 53 | const uint32_t *dirty_bits; 54 | uint32_t dirty_val; 55 | int y0, y1, page_y0, page_y1, byte_pos, page_index, bit_pos; 56 | 57 | dirty_bits = phys_mem_get_dirty_bits(mem_range); 58 | 59 | page_index = 0; 60 | y0 = y1 = 0; 61 | while (page_index < fb_page_count) { 62 | dirty_val = dirty_bits[page_index >> 5]; 63 | if (dirty_val != 0) { 64 | bit_pos = 0; 65 | while (dirty_val != 0) { 66 | while (((dirty_val >> bit_pos) & 1) == 0) 67 | bit_pos++; 68 | dirty_val &= ~(1 << bit_pos); 69 | 70 | byte_pos = (page_index + bit_pos) * DEVRAM_PAGE_SIZE; 71 | page_y0 = byte_pos / fb_dev->stride; 72 | page_y1 = ((byte_pos + DEVRAM_PAGE_SIZE - 1) / fb_dev->stride) + 1; 73 | page_y1 = min_int(page_y1, fb_dev->height); 74 | if (y0 == y1) { 75 | y0 = page_y0; 76 | y1 = page_y1; 77 | } else if (page_y0 <= (y1 + MAX_MERGE_DISTANCE)) { 78 | /* union with current region */ 79 | y1 = page_y1; 80 | } else { 81 | /* flush */ 82 | redraw_func(fb_dev, opaque, 83 | 0, y0, fb_dev->width, y1 - y0); 84 | y0 = page_y0; 85 | y1 = page_y1; 86 | } 87 | } 88 | } 89 | page_index += 32; 90 | } 91 | 92 | if (y0 != y1) { 93 | redraw_func(fb_dev, opaque, 94 | 0, y0, fb_dev->width, y1 - y0); 95 | } 96 | } 97 | 98 | static void simplefb_refresh1(FBDevice *fb_dev, 99 | SimpleFBDrawFunc *redraw_func, void *opaque) 100 | { 101 | SimpleFBState *s = fb_dev->device_opaque; 102 | simplefb_refresh(fb_dev, redraw_func, opaque, s->mem_range, 103 | s->fb_page_count); 104 | } 105 | 106 | SimpleFBState *simplefb_init(PhysMemoryMap *map, uint64_t phys_addr, 107 | FBDevice *fb_dev, int width, int height) 108 | { 109 | SimpleFBState *s; 110 | 111 | s = mallocz(sizeof(*s)); 112 | s->fb_dev = fb_dev; 113 | 114 | fb_dev->width = width; 115 | fb_dev->height = height; 116 | fb_dev->stride = width * 4; 117 | fb_dev->fb_size = (height * fb_dev->stride + FB_ALLOC_ALIGN - 1) & ~(FB_ALLOC_ALIGN - 1); 118 | s->fb_page_count = fb_dev->fb_size >> DEVRAM_PAGE_SIZE_LOG2; 119 | 120 | s->mem_range = cpu_register_ram(map, phys_addr, fb_dev->fb_size, 121 | DEVRAM_FLAG_DIRTY_BITS); 122 | 123 | fb_dev->fb_data = s->mem_range->phys_mem; 124 | fb_dev->device_opaque = s; 125 | fb_dev->refresh = simplefb_refresh1; 126 | return s; 127 | } 128 | -------------------------------------------------------------------------------- /tinyemu/slirp/bootp.h: -------------------------------------------------------------------------------- 1 | /* bootp/dhcp defines */ 2 | 3 | #define BOOTP_SERVER 67 4 | #define BOOTP_CLIENT 68 5 | 6 | #define BOOTP_REQUEST 1 7 | #define BOOTP_REPLY 2 8 | 9 | #define RFC1533_COOKIE 99, 130, 83, 99 10 | #define RFC1533_PAD 0 11 | #define RFC1533_NETMASK 1 12 | #define RFC1533_TIMEOFFSET 2 13 | #define RFC1533_GATEWAY 3 14 | #define RFC1533_TIMESERVER 4 15 | #define RFC1533_IEN116NS 5 16 | #define RFC1533_DNS 6 17 | #define RFC1533_LOGSERVER 7 18 | #define RFC1533_COOKIESERVER 8 19 | #define RFC1533_LPRSERVER 9 20 | #define RFC1533_IMPRESSSERVER 10 21 | #define RFC1533_RESOURCESERVER 11 22 | #define RFC1533_HOSTNAME 12 23 | #define RFC1533_BOOTFILESIZE 13 24 | #define RFC1533_MERITDUMPFILE 14 25 | #define RFC1533_DOMAINNAME 15 26 | #define RFC1533_SWAPSERVER 16 27 | #define RFC1533_ROOTPATH 17 28 | #define RFC1533_EXTENSIONPATH 18 29 | #define RFC1533_IPFORWARDING 19 30 | #define RFC1533_IPSOURCEROUTING 20 31 | #define RFC1533_IPPOLICYFILTER 21 32 | #define RFC1533_IPMAXREASSEMBLY 22 33 | #define RFC1533_IPTTL 23 34 | #define RFC1533_IPMTU 24 35 | #define RFC1533_IPMTUPLATEAU 25 36 | #define RFC1533_INTMTU 26 37 | #define RFC1533_INTLOCALSUBNETS 27 38 | #define RFC1533_INTBROADCAST 28 39 | #define RFC1533_INTICMPDISCOVER 29 40 | #define RFC1533_INTICMPRESPOND 30 41 | #define RFC1533_INTROUTEDISCOVER 31 42 | #define RFC1533_INTROUTESOLICIT 32 43 | #define RFC1533_INTSTATICROUTES 33 44 | #define RFC1533_LLTRAILERENCAP 34 45 | #define RFC1533_LLARPCACHETMO 35 46 | #define RFC1533_LLETHERNETENCAP 36 47 | #define RFC1533_TCPTTL 37 48 | #define RFC1533_TCPKEEPALIVETMO 38 49 | #define RFC1533_TCPKEEPALIVEGB 39 50 | #define RFC1533_NISDOMAIN 40 51 | #define RFC1533_NISSERVER 41 52 | #define RFC1533_NTPSERVER 42 53 | #define RFC1533_VENDOR 43 54 | #define RFC1533_NBNS 44 55 | #define RFC1533_NBDD 45 56 | #define RFC1533_NBNT 46 57 | #define RFC1533_NBSCOPE 47 58 | #define RFC1533_XFS 48 59 | #define RFC1533_XDM 49 60 | 61 | #define RFC2132_REQ_ADDR 50 62 | #define RFC2132_LEASE_TIME 51 63 | #define RFC2132_MSG_TYPE 53 64 | #define RFC2132_SRV_ID 54 65 | #define RFC2132_PARAM_LIST 55 66 | #define RFC2132_MESSAGE 56 67 | #define RFC2132_MAX_SIZE 57 68 | #define RFC2132_RENEWAL_TIME 58 69 | #define RFC2132_REBIND_TIME 59 70 | 71 | #define DHCPDISCOVER 1 72 | #define DHCPOFFER 2 73 | #define DHCPREQUEST 3 74 | #define DHCPACK 5 75 | #define DHCPNAK 6 76 | 77 | #define RFC1533_VENDOR_MAJOR 0 78 | #define RFC1533_VENDOR_MINOR 0 79 | 80 | #define RFC1533_VENDOR_MAGIC 128 81 | #define RFC1533_VENDOR_ADDPARM 129 82 | #define RFC1533_VENDOR_ETHDEV 130 83 | #define RFC1533_VENDOR_HOWTO 132 84 | #define RFC1533_VENDOR_MNUOPTS 160 85 | #define RFC1533_VENDOR_SELECTION 176 86 | #define RFC1533_VENDOR_MOTD 184 87 | #define RFC1533_VENDOR_NUMOFMOTD 8 88 | #define RFC1533_VENDOR_IMG 192 89 | #define RFC1533_VENDOR_NUMOFIMG 16 90 | 91 | #define RFC1533_END 255 92 | #define BOOTP_VENDOR_LEN 64 93 | #define DHCP_OPT_LEN 312 94 | 95 | struct bootp_t { 96 | struct ip ip; 97 | struct udphdr udp; 98 | uint8_t bp_op; 99 | uint8_t bp_htype; 100 | uint8_t bp_hlen; 101 | uint8_t bp_hops; 102 | uint32_t bp_xid; 103 | uint16_t bp_secs; 104 | uint16_t unused; 105 | struct in_addr bp_ciaddr; 106 | struct in_addr bp_yiaddr; 107 | struct in_addr bp_siaddr; 108 | struct in_addr bp_giaddr; 109 | uint8_t bp_hwaddr[16]; 110 | uint8_t bp_sname[64]; 111 | uint8_t bp_file[128]; 112 | uint8_t bp_vend[DHCP_OPT_LEN]; 113 | }; 114 | 115 | typedef struct { 116 | uint16_t allocated; 117 | uint8_t macaddr[6]; 118 | } BOOTPClient; 119 | 120 | #define NB_BOOTP_CLIENTS 16 121 | 122 | void bootp_input(struct mbuf *m); 123 | -------------------------------------------------------------------------------- /tinyemu/slirp/cksum.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1988, 1992, 1993 3 | * The Regents of the University of California. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the University nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 30 | * in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp 31 | */ 32 | 33 | #include "slirp.h" 34 | 35 | /* 36 | * Checksum routine for Internet Protocol family headers (Portable Version). 37 | * 38 | * This routine is very heavily used in the network 39 | * code and should be modified for each CPU to be as fast as possible. 40 | * 41 | * XXX Since we will never span more than 1 mbuf, we can optimise this 42 | */ 43 | 44 | #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) 45 | #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; \ 46 | (void)ADDCARRY(sum);} 47 | 48 | int cksum(struct mbuf *m, int len) 49 | { 50 | register uint16_t *w; 51 | register int sum = 0; 52 | register int mlen = 0; 53 | int byte_swapped = 0; 54 | 55 | union { 56 | uint8_t c[2]; 57 | uint16_t s; 58 | } s_util; 59 | union { 60 | uint16_t s[2]; 61 | uint32_t l; 62 | } l_util; 63 | 64 | if (m->m_len == 0) 65 | goto cont; 66 | w = mtod(m, uint16_t *); 67 | 68 | mlen = m->m_len; 69 | 70 | if (len < mlen) 71 | mlen = len; 72 | #ifdef DEBUG 73 | len -= mlen; 74 | #endif 75 | /* 76 | * Force to even boundary. 77 | */ 78 | if ((1 & (long) w) && (mlen > 0)) { 79 | REDUCE; 80 | sum <<= 8; 81 | s_util.c[0] = *(uint8_t *)w; 82 | w = (uint16_t *)((int8_t *)w + 1); 83 | mlen--; 84 | byte_swapped = 1; 85 | } 86 | /* 87 | * Unroll the loop to make overhead from 88 | * branches &c small. 89 | */ 90 | while ((mlen -= 32) >= 0) { 91 | sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 92 | sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; 93 | sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; 94 | sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; 95 | w += 16; 96 | } 97 | mlen += 32; 98 | while ((mlen -= 8) >= 0) { 99 | sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 100 | w += 4; 101 | } 102 | mlen += 8; 103 | if (mlen == 0 && byte_swapped == 0) 104 | goto cont; 105 | REDUCE; 106 | while ((mlen -= 2) >= 0) { 107 | sum += *w++; 108 | } 109 | 110 | if (byte_swapped) { 111 | REDUCE; 112 | sum <<= 8; 113 | if (mlen == -1) { 114 | s_util.c[1] = *(uint8_t *)w; 115 | sum += s_util.s; 116 | mlen = 0; 117 | } else 118 | 119 | mlen = -1; 120 | } else if (mlen == -1) 121 | s_util.c[0] = *(uint8_t *)w; 122 | 123 | cont: 124 | #ifdef DEBUG 125 | if (len) { 126 | DEBUG_ERROR((dfd, "cksum: out of data\n")); 127 | DEBUG_ERROR((dfd, " len = %d\n", len)); 128 | } 129 | #endif 130 | if (mlen == -1) { 131 | /* The last mbuf has odd # of bytes. Follow the 132 | standard (the odd byte may be shifted left by 8 bits 133 | or not as determined by endian-ness of the machine) */ 134 | s_util.c[1] = 0; 135 | sum += s_util.s; 136 | } 137 | REDUCE; 138 | return (~sum & 0xffff); 139 | } 140 | -------------------------------------------------------------------------------- /tinyemu/slirp/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1995 Danny Gasparovski. 3 | * 4 | * Please read the file COPYRIGHT for the 5 | * terms and conditions of the copyright. 6 | */ 7 | 8 | //#define DEBUG 1 9 | 10 | #ifdef DEBUG 11 | 12 | #define DBG_CALL 0x1 13 | #define DBG_MISC 0x2 14 | #define DBG_ERROR 0x4 15 | 16 | #define dfd stderr 17 | 18 | extern int slirp_debug; 19 | 20 | #define DEBUG_CALL(x) if (slirp_debug & DBG_CALL) { fprintf(dfd, "%s...\n", x); fflush(dfd); } 21 | #define DEBUG_ARG(x, y) if (slirp_debug & DBG_CALL) { fputc(' ', dfd); fprintf(dfd, x, y); fputc('\n', dfd); fflush(dfd); } 22 | #define DEBUG_ARGS(x) if (slirp_debug & DBG_CALL) { fprintf x ; fflush(dfd); } 23 | #define DEBUG_MISC(x) if (slirp_debug & DBG_MISC) { fprintf x ; fflush(dfd); } 24 | #define DEBUG_ERROR(x) if (slirp_debug & DBG_ERROR) {fprintf x ; fflush(dfd); } 25 | 26 | #else 27 | 28 | #define DEBUG_CALL(x) 29 | #define DEBUG_ARG(x, y) 30 | #define DEBUG_ARGS(x) 31 | #define DEBUG_MISC(x) 32 | #define DEBUG_ERROR(x) 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /tinyemu/slirp/if.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1995 Danny Gasparovski. 3 | * 4 | * Please read the file COPYRIGHT for the 5 | * terms and conditions of the copyright. 6 | */ 7 | 8 | #include "slirp.h" 9 | 10 | #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm)) 11 | 12 | static void 13 | ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead) 14 | { 15 | ifm->ifs_next = ifmhead->ifs_next; 16 | ifmhead->ifs_next = ifm; 17 | ifm->ifs_prev = ifmhead; 18 | ifm->ifs_next->ifs_prev = ifm; 19 | } 20 | 21 | static void 22 | ifs_remque(struct mbuf *ifm) 23 | { 24 | ifm->ifs_prev->ifs_next = ifm->ifs_next; 25 | ifm->ifs_next->ifs_prev = ifm->ifs_prev; 26 | } 27 | 28 | void 29 | if_init(Slirp *slirp) 30 | { 31 | slirp->if_fastq.ifq_next = slirp->if_fastq.ifq_prev = &slirp->if_fastq; 32 | slirp->if_batchq.ifq_next = slirp->if_batchq.ifq_prev = &slirp->if_batchq; 33 | slirp->next_m = &slirp->if_batchq; 34 | } 35 | 36 | /* 37 | * if_output: Queue packet into an output queue. 38 | * There are 2 output queue's, if_fastq and if_batchq. 39 | * Each output queue is a doubly linked list of double linked lists 40 | * of mbufs, each list belonging to one "session" (socket). This 41 | * way, we can output packets fairly by sending one packet from each 42 | * session, instead of all the packets from one session, then all packets 43 | * from the next session, etc. Packets on the if_fastq get absolute 44 | * priority, but if one session hogs the link, it gets "downgraded" 45 | * to the batchq until it runs out of packets, then it'll return 46 | * to the fastq (eg. if the user does an ls -alR in a telnet session, 47 | * it'll temporarily get downgraded to the batchq) 48 | */ 49 | void 50 | if_output(struct socket *so, struct mbuf *ifm) 51 | { 52 | Slirp *slirp = ifm->slirp; 53 | struct mbuf *ifq; 54 | int on_fastq = 1; 55 | 56 | DEBUG_CALL("if_output"); 57 | DEBUG_ARG("so = %lx", (long)so); 58 | DEBUG_ARG("ifm = %lx", (long)ifm); 59 | 60 | /* 61 | * First remove the mbuf from m_usedlist, 62 | * since we're gonna use m_next and m_prev ourselves 63 | * XXX Shouldn't need this, gotta change dtom() etc. 64 | */ 65 | if (ifm->m_flags & M_USEDLIST) { 66 | remque(ifm); 67 | ifm->m_flags &= ~M_USEDLIST; 68 | } 69 | 70 | /* 71 | * See if there's already a batchq list for this session. 72 | * This can include an interactive session, which should go on fastq, 73 | * but gets too greedy... hence it'll be downgraded from fastq to batchq. 74 | * We mustn't put this packet back on the fastq (or we'll send it out of order) 75 | * XXX add cache here? 76 | */ 77 | for (ifq = slirp->if_batchq.ifq_prev; ifq != &slirp->if_batchq; 78 | ifq = ifq->ifq_prev) { 79 | if (so == ifq->ifq_so) { 80 | /* A match! */ 81 | ifm->ifq_so = so; 82 | ifs_insque(ifm, ifq->ifs_prev); 83 | goto diddit; 84 | } 85 | } 86 | 87 | /* No match, check which queue to put it on */ 88 | if (so && (so->so_iptos & IPTOS_LOWDELAY)) { 89 | ifq = slirp->if_fastq.ifq_prev; 90 | on_fastq = 1; 91 | /* 92 | * Check if this packet is a part of the last 93 | * packet's session 94 | */ 95 | if (ifq->ifq_so == so) { 96 | ifm->ifq_so = so; 97 | ifs_insque(ifm, ifq->ifs_prev); 98 | goto diddit; 99 | } 100 | } else 101 | ifq = slirp->if_batchq.ifq_prev; 102 | 103 | /* Create a new doubly linked list for this session */ 104 | ifm->ifq_so = so; 105 | ifs_init(ifm); 106 | insque(ifm, ifq); 107 | 108 | diddit: 109 | slirp->if_queued++; 110 | 111 | if (so) { 112 | /* Update *_queued */ 113 | so->so_queued++; 114 | so->so_nqueued++; 115 | /* 116 | * Check if the interactive session should be downgraded to 117 | * the batchq. A session is downgraded if it has queued 6 118 | * packets without pausing, and at least 3 of those packets 119 | * have been sent over the link 120 | * (XXX These are arbitrary numbers, probably not optimal..) 121 | */ 122 | if (on_fastq && ((so->so_nqueued >= 6) && 123 | (so->so_nqueued - so->so_queued) >= 3)) { 124 | 125 | /* Remove from current queue... */ 126 | remque(ifm->ifs_next); 127 | 128 | /* ...And insert in the new. That'll teach ya! */ 129 | insque(ifm->ifs_next, &slirp->if_batchq); 130 | } 131 | } 132 | 133 | #ifndef FULL_BOLT 134 | /* 135 | * This prevents us from malloc()ing too many mbufs 136 | */ 137 | if_start(ifm->slirp); 138 | #endif 139 | } 140 | 141 | /* 142 | * Send a packet 143 | * We choose a packet based on it's position in the output queues; 144 | * If there are packets on the fastq, they are sent FIFO, before 145 | * everything else. Otherwise we choose the first packet from the 146 | * batchq and send it. the next packet chosen will be from the session 147 | * after this one, then the session after that one, and so on.. So, 148 | * for example, if there are 3 ftp session's fighting for bandwidth, 149 | * one packet will be sent from the first session, then one packet 150 | * from the second session, then one packet from the third, then back 151 | * to the first, etc. etc. 152 | */ 153 | void 154 | if_start(Slirp *slirp) 155 | { 156 | struct mbuf *ifm, *ifqt; 157 | 158 | DEBUG_CALL("if_start"); 159 | 160 | if (slirp->if_queued == 0) 161 | return; /* Nothing to do */ 162 | 163 | again: 164 | /* check if we can really output */ 165 | if (!slirp_can_output(slirp->opaque)) 166 | return; 167 | 168 | /* 169 | * See which queue to get next packet from 170 | * If there's something in the fastq, select it immediately 171 | */ 172 | if (slirp->if_fastq.ifq_next != &slirp->if_fastq) { 173 | ifm = slirp->if_fastq.ifq_next; 174 | } else { 175 | /* Nothing on fastq, see if next_m is valid */ 176 | if (slirp->next_m != &slirp->if_batchq) 177 | ifm = slirp->next_m; 178 | else 179 | ifm = slirp->if_batchq.ifq_next; 180 | 181 | /* Set which packet to send on next iteration */ 182 | slirp->next_m = ifm->ifq_next; 183 | } 184 | /* Remove it from the queue */ 185 | ifqt = ifm->ifq_prev; 186 | remque(ifm); 187 | slirp->if_queued--; 188 | 189 | /* If there are more packets for this session, re-queue them */ 190 | if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) { 191 | insque(ifm->ifs_next, ifqt); 192 | ifs_remque(ifm); 193 | } 194 | 195 | /* Update so_queued */ 196 | if (ifm->ifq_so) { 197 | if (--ifm->ifq_so->so_queued == 0) 198 | /* If there's no more queued, reset nqueued */ 199 | ifm->ifq_so->so_nqueued = 0; 200 | } 201 | 202 | /* Encapsulate the packet for sending */ 203 | if_encap(slirp, (uint8_t *)ifm->m_data, ifm->m_len); 204 | 205 | m_free(ifm); 206 | 207 | if (slirp->if_queued) 208 | goto again; 209 | } 210 | -------------------------------------------------------------------------------- /tinyemu/slirp/if.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1995 Danny Gasparovski. 3 | * 4 | * Please read the file COPYRIGHT for the 5 | * terms and conditions of the copyright. 6 | */ 7 | 8 | #ifndef _IF_H_ 9 | #define _IF_H_ 10 | 11 | #define IF_COMPRESS 0x01 /* We want compression */ 12 | #define IF_NOCOMPRESS 0x02 /* Do not do compression */ 13 | #define IF_AUTOCOMP 0x04 /* Autodetect (default) */ 14 | #define IF_NOCIDCOMP 0x08 /* CID compression */ 15 | 16 | #define IF_MTU 1500 17 | #define IF_MRU 1500 18 | #define IF_COMP IF_AUTOCOMP /* Flags for compression */ 19 | 20 | /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */ 21 | #define IF_MAXLINKHDR (2 + 14 + 40) 22 | 23 | #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm)) 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /tinyemu/slirp/ip_icmp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1982, 1986, 1993 3 | * The Regents of the University of California. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the University nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 30 | * ip_icmp.h,v 1.4 1995/05/30 08:09:43 rgrimes Exp 31 | */ 32 | 33 | #ifndef _NETINET_IP_ICMP_H_ 34 | #define _NETINET_IP_ICMP_H_ 35 | 36 | /* 37 | * Interface Control Message Protocol Definitions. 38 | * Per RFC 792, September 1981. 39 | */ 40 | 41 | typedef uint32_t n_time; 42 | 43 | /* 44 | * Structure of an icmp header. 45 | */ 46 | struct icmp { 47 | u_char icmp_type; /* type of message, see below */ 48 | u_char icmp_code; /* type sub code */ 49 | u_short icmp_cksum; /* ones complement cksum of struct */ 50 | union { 51 | u_char ih_pptr; /* ICMP_PARAMPROB */ 52 | struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ 53 | struct ih_idseq { 54 | u_short icd_id; 55 | u_short icd_seq; 56 | } ih_idseq; 57 | int ih_void; 58 | 59 | /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ 60 | struct ih_pmtu { 61 | u_short ipm_void; 62 | u_short ipm_nextmtu; 63 | } ih_pmtu; 64 | } icmp_hun; 65 | #define icmp_pptr icmp_hun.ih_pptr 66 | #define icmp_gwaddr icmp_hun.ih_gwaddr 67 | #define icmp_id icmp_hun.ih_idseq.icd_id 68 | #define icmp_seq icmp_hun.ih_idseq.icd_seq 69 | #define icmp_void icmp_hun.ih_void 70 | #define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void 71 | #define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu 72 | union { 73 | struct id_ts { 74 | n_time its_otime; 75 | n_time its_rtime; 76 | n_time its_ttime; 77 | } id_ts; 78 | struct id_ip { 79 | struct ip idi_ip; 80 | /* options and then 64 bits of data */ 81 | } id_ip; 82 | uint32_t id_mask; 83 | char id_data[1]; 84 | } icmp_dun; 85 | #define icmp_otime icmp_dun.id_ts.its_otime 86 | #define icmp_rtime icmp_dun.id_ts.its_rtime 87 | #define icmp_ttime icmp_dun.id_ts.its_ttime 88 | #define icmp_ip icmp_dun.id_ip.idi_ip 89 | #define icmp_mask icmp_dun.id_mask 90 | #define icmp_data icmp_dun.id_data 91 | }; 92 | 93 | /* 94 | * Lower bounds on packet lengths for various types. 95 | * For the error advice packets must first insure that the 96 | * packet is large enought to contain the returned ip header. 97 | * Only then can we do the check to see if 64 bits of packet 98 | * data have been returned, since we need to check the returned 99 | * ip header length. 100 | */ 101 | #define ICMP_MINLEN 8 /* abs minimum */ 102 | #define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */ 103 | #define ICMP_MASKLEN 12 /* address mask */ 104 | #define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ 105 | #define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) 106 | /* N.B.: must separately check that ip_hl >= 5 */ 107 | 108 | /* 109 | * Definition of type and code field values. 110 | */ 111 | #define ICMP_ECHOREPLY 0 /* echo reply */ 112 | #define ICMP_UNREACH 3 /* dest unreachable, codes: */ 113 | #define ICMP_UNREACH_NET 0 /* bad net */ 114 | #define ICMP_UNREACH_HOST 1 /* bad host */ 115 | #define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ 116 | #define ICMP_UNREACH_PORT 3 /* bad port */ 117 | #define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ 118 | #define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ 119 | #define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ 120 | #define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ 121 | #define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ 122 | #define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */ 123 | #define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ 124 | #define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ 125 | #define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ 126 | #define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ 127 | #define ICMP_REDIRECT 5 /* shorter route, codes: */ 128 | #define ICMP_REDIRECT_NET 0 /* for network */ 129 | #define ICMP_REDIRECT_HOST 1 /* for host */ 130 | #define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ 131 | #define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ 132 | #define ICMP_ECHO 8 /* echo service */ 133 | #define ICMP_ROUTERADVERT 9 /* router advertisement */ 134 | #define ICMP_ROUTERSOLICIT 10 /* router solicitation */ 135 | #define ICMP_TIMXCEED 11 /* time exceeded, code: */ 136 | #define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ 137 | #define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ 138 | #define ICMP_PARAMPROB 12 /* ip header bad */ 139 | #define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ 140 | #define ICMP_TSTAMP 13 /* timestamp request */ 141 | #define ICMP_TSTAMPREPLY 14 /* timestamp reply */ 142 | #define ICMP_IREQ 15 /* information request */ 143 | #define ICMP_IREQREPLY 16 /* information reply */ 144 | #define ICMP_MASKREQ 17 /* address mask request */ 145 | #define ICMP_MASKREPLY 18 /* address mask reply */ 146 | 147 | #define ICMP_MAXTYPE 18 148 | 149 | #define ICMP_INFOTYPE(type) \ 150 | ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ 151 | (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ 152 | (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ 153 | (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ 154 | (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) 155 | 156 | void icmp_input(struct mbuf *, int); 157 | void icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize, 158 | const char *message); 159 | void icmp_reflect(struct mbuf *); 160 | 161 | #endif 162 | -------------------------------------------------------------------------------- /tinyemu/slirp/ip_output.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1982, 1986, 1988, 1990, 1993 3 | * The Regents of the University of California. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the University nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 30 | * ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp 31 | */ 32 | 33 | /* 34 | * Changes and additions relating to SLiRP are 35 | * Copyright (c) 1995 Danny Gasparovski. 36 | * 37 | * Please read the file COPYRIGHT for the 38 | * terms and conditions of the copyright. 39 | */ 40 | 41 | #include "slirp.h" 42 | 43 | /* Number of packets queued before we start sending 44 | * (to prevent allocing too many mbufs) */ 45 | #define IF_THRESH 10 46 | 47 | /* 48 | * IP output. The packet in mbuf chain m contains a skeletal IP 49 | * header (with len, off, ttl, proto, tos, src, dst). 50 | * The mbuf chain containing the packet will be freed. 51 | * The mbuf opt, if present, will not be freed. 52 | */ 53 | int 54 | ip_output(struct socket *so, struct mbuf *m0) 55 | { 56 | Slirp *slirp = m0->slirp; 57 | register struct ip *ip; 58 | register struct mbuf *m = m0; 59 | register int hlen = sizeof(struct ip ); 60 | int len, off, error = 0; 61 | 62 | DEBUG_CALL("ip_output"); 63 | DEBUG_ARG("so = %lx", (long)so); 64 | DEBUG_ARG("m0 = %lx", (long)m0); 65 | 66 | ip = mtod(m, struct ip *); 67 | /* 68 | * Fill in IP header. 69 | */ 70 | ip->ip_v = IPVERSION; 71 | ip->ip_off &= IP_DF; 72 | ip->ip_id = htons(slirp->ip_id++); 73 | ip->ip_hl = hlen >> 2; 74 | 75 | /* 76 | * If small enough for interface, can just send directly. 77 | */ 78 | if ((uint16_t)ip->ip_len <= IF_MTU) { 79 | ip->ip_len = htons((uint16_t)ip->ip_len); 80 | ip->ip_off = htons((uint16_t)ip->ip_off); 81 | ip->ip_sum = 0; 82 | ip->ip_sum = cksum(m, hlen); 83 | 84 | if_output(so, m); 85 | goto done; 86 | } 87 | 88 | /* 89 | * Too large for interface; fragment if possible. 90 | * Must be able to put at least 8 bytes per fragment. 91 | */ 92 | if (ip->ip_off & IP_DF) { 93 | error = -1; 94 | goto bad; 95 | } 96 | 97 | len = (IF_MTU - hlen) &~ 7; /* ip databytes per packet */ 98 | if (len < 8) { 99 | error = -1; 100 | goto bad; 101 | } 102 | 103 | { 104 | int mhlen, firstlen = len; 105 | struct mbuf **mnext = &m->m_nextpkt; 106 | 107 | /* 108 | * Loop through length of segment after first fragment, 109 | * make new header and copy data of each part and link onto chain. 110 | */ 111 | m0 = m; 112 | mhlen = sizeof (struct ip); 113 | for (off = hlen + len; off < (uint16_t)ip->ip_len; off += len) { 114 | register struct ip *mhip; 115 | m = m_get(slirp); 116 | if (m == NULL) { 117 | error = -1; 118 | goto sendorfree; 119 | } 120 | m->m_data += IF_MAXLINKHDR; 121 | mhip = mtod(m, struct ip *); 122 | *mhip = *ip; 123 | 124 | m->m_len = mhlen; 125 | mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); 126 | if (ip->ip_off & IP_MF) 127 | mhip->ip_off |= IP_MF; 128 | if (off + len >= (uint16_t)ip->ip_len) 129 | len = (uint16_t)ip->ip_len - off; 130 | else 131 | mhip->ip_off |= IP_MF; 132 | mhip->ip_len = htons((uint16_t)(len + mhlen)); 133 | 134 | if (m_copy(m, m0, off, len) < 0) { 135 | error = -1; 136 | goto sendorfree; 137 | } 138 | 139 | mhip->ip_off = htons((uint16_t)mhip->ip_off); 140 | mhip->ip_sum = 0; 141 | mhip->ip_sum = cksum(m, mhlen); 142 | *mnext = m; 143 | mnext = &m->m_nextpkt; 144 | } 145 | /* 146 | * Update first fragment by trimming what's been copied out 147 | * and updating header, then send each fragment (in order). 148 | */ 149 | m = m0; 150 | m_adj(m, hlen + firstlen - (uint16_t)ip->ip_len); 151 | ip->ip_len = htons((uint16_t)m->m_len); 152 | ip->ip_off = htons((uint16_t)(ip->ip_off | IP_MF)); 153 | ip->ip_sum = 0; 154 | ip->ip_sum = cksum(m, hlen); 155 | sendorfree: 156 | for (m = m0; m; m = m0) { 157 | m0 = m->m_nextpkt; 158 | m->m_nextpkt = NULL; 159 | if (error == 0) 160 | if_output(so, m); 161 | else 162 | m_freem(m); 163 | } 164 | } 165 | 166 | done: 167 | return (error); 168 | 169 | bad: 170 | m_freem(m0); 171 | goto done; 172 | } 173 | -------------------------------------------------------------------------------- /tinyemu/slirp/libslirp.h: -------------------------------------------------------------------------------- 1 | #ifndef _LIBSLIRP_H 2 | #define _LIBSLIRP_H 3 | 4 | #ifdef CONFIG_SLIRP 5 | 6 | #include 7 | 8 | struct Slirp; 9 | typedef struct Slirp Slirp; 10 | 11 | int get_dns_addr(struct in_addr *pdns_addr); 12 | 13 | Slirp *slirp_init(int restricted, struct in_addr vnetwork, 14 | struct in_addr vnetmask, struct in_addr vhost, 15 | const char *vhostname, const char *tftp_path, 16 | const char *bootfile, struct in_addr vdhcp_start, 17 | struct in_addr vnameserver, void *opaque); 18 | void slirp_cleanup(Slirp *slirp); 19 | 20 | void slirp_select_fill(Slirp *slirp, int *pnfds, 21 | fd_set *readfds, fd_set *writefds, fd_set *xfds); 22 | 23 | void slirp_select_poll(Slirp *slirp, 24 | fd_set *readfds, fd_set *writefds, fd_set *xfds, 25 | int select_error); 26 | 27 | void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len); 28 | 29 | /* you must provide the following functions: */ 30 | int slirp_can_output(void *opaque); 31 | void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len); 32 | 33 | int slirp_add_hostfwd(Slirp *slirp, int is_udp, 34 | struct in_addr host_addr, int host_port, 35 | struct in_addr guest_addr, int guest_port); 36 | int slirp_remove_hostfwd(Slirp *slirp, int is_udp, 37 | struct in_addr host_addr, int host_port); 38 | int slirp_add_exec(Slirp *slirp, int do_pty, const void *args, 39 | struct in_addr *guest_addr, int guest_port); 40 | 41 | void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, 42 | int guest_port, const uint8_t *buf, int size); 43 | size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr, 44 | int guest_port); 45 | int slirp_get_time_ms(void); 46 | 47 | #else /* !CONFIG_SLIRP */ 48 | 49 | static inline void slirp_select_fill(int *pnfds, fd_set *readfds, 50 | fd_set *writefds, fd_set *xfds) { } 51 | 52 | static inline void slirp_select_poll(fd_set *readfds, fd_set *writefds, 53 | fd_set *xfds, int select_error) { } 54 | #endif /* !CONFIG_SLIRP */ 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /tinyemu/slirp/main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1995 Danny Gasparovski. 3 | * 4 | * Please read the file COPYRIGHT for the 5 | * terms and conditions of the copyright. 6 | */ 7 | 8 | #ifdef HAVE_SYS_SELECT_H 9 | #include 10 | #endif 11 | 12 | #define TOWRITEMAX 512 13 | 14 | extern int slirp_socket; 15 | extern int slirp_socket_unit; 16 | extern int slirp_socket_port; 17 | extern uint32_t slirp_socket_addr; 18 | extern char *slirp_socket_passwd; 19 | extern int ctty_closed; 20 | 21 | /* 22 | * Get the difference in 2 times from updtim() 23 | * Allow for wraparound times, "just in case" 24 | * x is the greater of the 2 (current time) and y is 25 | * what it's being compared against. 26 | */ 27 | #define TIME_DIFF(x,y) (x)-(y) < 0 ? ~0-(y)+(x) : (x)-(y) 28 | 29 | extern char *slirp_tty; 30 | extern char *exec_shell; 31 | extern u_int curtime; 32 | extern fd_set *global_readfds, *global_writefds, *global_xfds; 33 | extern struct in_addr loopback_addr; 34 | extern char *username; 35 | extern char *socket_path; 36 | extern int towrite_max; 37 | extern int ppp_exit; 38 | extern int tcp_keepintvl; 39 | 40 | #define PROTO_SLIP 0x1 41 | #ifdef USE_PPP 42 | #define PROTO_PPP 0x2 43 | #endif 44 | 45 | void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len); 46 | ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags); 47 | -------------------------------------------------------------------------------- /tinyemu/slirp/mbuf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1995 Danny Gasparovski 3 | * 4 | * Please read the file COPYRIGHT for the 5 | * terms and conditions of the copyright. 6 | */ 7 | 8 | /* 9 | * mbuf's in SLiRP are much simpler than the real mbufs in 10 | * FreeBSD. They are fixed size, determined by the MTU, 11 | * so that one whole packet can fit. Mbuf's cannot be 12 | * chained together. If there's more data than the mbuf 13 | * could hold, an external malloced buffer is pointed to 14 | * by m_ext (and the data pointers) and M_EXT is set in 15 | * the flags 16 | */ 17 | 18 | #include "slirp.h" 19 | 20 | #define MBUF_THRESH 30 21 | 22 | /* 23 | * Find a nice value for msize 24 | * XXX if_maxlinkhdr already in mtu 25 | */ 26 | #define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + offsetof(struct mbuf, m_dat) + 6) 27 | 28 | void 29 | m_init(Slirp *slirp) 30 | { 31 | slirp->m_freelist.m_next = slirp->m_freelist.m_prev = &slirp->m_freelist; 32 | slirp->m_usedlist.m_next = slirp->m_usedlist.m_prev = &slirp->m_usedlist; 33 | } 34 | 35 | /* 36 | * Get an mbuf from the free list, if there are none 37 | * malloc one 38 | * 39 | * Because fragmentation can occur if we alloc new mbufs and 40 | * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE, 41 | * which tells m_free to actually free() it 42 | */ 43 | struct mbuf * 44 | m_get(Slirp *slirp) 45 | { 46 | register struct mbuf *m; 47 | int flags = 0; 48 | 49 | DEBUG_CALL("m_get"); 50 | 51 | if (slirp->m_freelist.m_next == &slirp->m_freelist) { 52 | m = (struct mbuf *)malloc(SLIRP_MSIZE); 53 | if (m == NULL) goto end_error; 54 | slirp->mbuf_alloced++; 55 | if (slirp->mbuf_alloced > MBUF_THRESH) 56 | flags = M_DOFREE; 57 | m->slirp = slirp; 58 | } else { 59 | m = slirp->m_freelist.m_next; 60 | remque(m); 61 | } 62 | 63 | /* Insert it in the used list */ 64 | insque(m,&slirp->m_usedlist); 65 | m->m_flags = (flags | M_USEDLIST); 66 | 67 | /* Initialise it */ 68 | m->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat); 69 | m->m_data = m->m_dat; 70 | m->m_len = 0; 71 | m->m_nextpkt = NULL; 72 | m->m_prevpkt = NULL; 73 | end_error: 74 | DEBUG_ARG("m = %lx", (long )m); 75 | return m; 76 | } 77 | 78 | void 79 | m_free(struct mbuf *m) 80 | { 81 | 82 | DEBUG_CALL("m_free"); 83 | DEBUG_ARG("m = %lx", (long )m); 84 | 85 | if(m) { 86 | /* Remove from m_usedlist */ 87 | if (m->m_flags & M_USEDLIST) 88 | remque(m); 89 | 90 | /* If it's M_EXT, free() it */ 91 | if (m->m_flags & M_EXT) 92 | free(m->m_ext); 93 | 94 | /* 95 | * Either free() it or put it on the free list 96 | */ 97 | if (m->m_flags & M_DOFREE) { 98 | m->slirp->mbuf_alloced--; 99 | free(m); 100 | } else if ((m->m_flags & M_FREELIST) == 0) { 101 | insque(m,&m->slirp->m_freelist); 102 | m->m_flags = M_FREELIST; /* Clobber other flags */ 103 | } 104 | } /* if(m) */ 105 | } 106 | 107 | /* 108 | * Copy data from one mbuf to the end of 109 | * the other.. if result is too big for one mbuf, malloc() 110 | * an M_EXT data segment 111 | */ 112 | void 113 | m_cat(struct mbuf *m, struct mbuf *n) 114 | { 115 | /* 116 | * If there's no room, realloc 117 | */ 118 | if (M_FREEROOM(m) < n->m_len) 119 | m_inc(m,m->m_size+MINCSIZE); 120 | 121 | memcpy(m->m_data+m->m_len, n->m_data, n->m_len); 122 | m->m_len += n->m_len; 123 | 124 | m_free(n); 125 | } 126 | 127 | 128 | /* make m size bytes large */ 129 | void 130 | m_inc(struct mbuf *m, int size) 131 | { 132 | int datasize; 133 | 134 | /* some compiles throw up on gotos. This one we can fake. */ 135 | if(m->m_size>size) return; 136 | 137 | if (m->m_flags & M_EXT) { 138 | datasize = m->m_data - m->m_ext; 139 | m->m_ext = (char *)realloc(m->m_ext,size); 140 | m->m_data = m->m_ext + datasize; 141 | } else { 142 | char *dat; 143 | datasize = m->m_data - m->m_dat; 144 | dat = (char *)malloc(size); 145 | memcpy(dat, m->m_dat, m->m_size); 146 | 147 | m->m_ext = dat; 148 | m->m_data = m->m_ext + datasize; 149 | m->m_flags |= M_EXT; 150 | } 151 | 152 | m->m_size = size; 153 | 154 | } 155 | 156 | 157 | 158 | void 159 | m_adj(struct mbuf *m, int len) 160 | { 161 | if (m == NULL) 162 | return; 163 | if (len >= 0) { 164 | /* Trim from head */ 165 | m->m_data += len; 166 | m->m_len -= len; 167 | } else { 168 | /* Trim from tail */ 169 | len = -len; 170 | m->m_len -= len; 171 | } 172 | } 173 | 174 | 175 | /* 176 | * Copy len bytes from m, starting off bytes into n 177 | */ 178 | int 179 | m_copy(struct mbuf *n, struct mbuf *m, int off, int len) 180 | { 181 | if (len > M_FREEROOM(n)) 182 | return -1; 183 | 184 | memcpy((n->m_data + n->m_len), (m->m_data + off), len); 185 | n->m_len += len; 186 | return 0; 187 | } 188 | 189 | 190 | /* 191 | * Given a pointer into an mbuf, return the mbuf 192 | * XXX This is a kludge, I should eliminate the need for it 193 | * Fortunately, it's not used often 194 | */ 195 | struct mbuf * 196 | dtom(Slirp *slirp, void *dat) 197 | { 198 | struct mbuf *m; 199 | 200 | DEBUG_CALL("dtom"); 201 | DEBUG_ARG("dat = %lx", (long )dat); 202 | 203 | /* bug corrected for M_EXT buffers */ 204 | for (m = slirp->m_usedlist.m_next; m != &slirp->m_usedlist; 205 | m = m->m_next) { 206 | if (m->m_flags & M_EXT) { 207 | if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) ) 208 | return m; 209 | } else { 210 | if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) ) 211 | return m; 212 | } 213 | } 214 | 215 | DEBUG_ERROR((dfd, "dtom failed")); 216 | 217 | return (struct mbuf *)0; 218 | } 219 | -------------------------------------------------------------------------------- /tinyemu/slirp/mbuf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1982, 1986, 1988, 1993 3 | * The Regents of the University of California. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the University nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * @(#)mbuf.h 8.3 (Berkeley) 1/21/94 30 | * mbuf.h,v 1.9 1994/11/14 13:54:20 bde Exp 31 | */ 32 | 33 | #ifndef _MBUF_H_ 34 | #define _MBUF_H_ 35 | 36 | #define m_freem m_free 37 | 38 | 39 | #define MINCSIZE 4096 /* Amount to increase mbuf if too small */ 40 | 41 | /* 42 | * Macros for type conversion 43 | * mtod(m,t) - convert mbuf pointer to data pointer of correct type 44 | */ 45 | #define mtod(m,t) ((t)(m)->m_data) 46 | 47 | /* XXX About mbufs for slirp: 48 | * Only one mbuf is ever used in a chain, for each "cell" of data. 49 | * m_nextpkt points to the next packet, if fragmented. 50 | * If the data is too large, the M_EXT is used, and a larger block 51 | * is alloced. Therefore, m_free[m] must check for M_EXT and if set 52 | * free the m_ext. This is inefficient memory-wise, but who cares. 53 | */ 54 | 55 | /* XXX should union some of these! */ 56 | /* header at beginning of each mbuf: */ 57 | struct m_hdr { 58 | struct mbuf *mh_next; /* Linked list of mbufs */ 59 | struct mbuf *mh_prev; 60 | struct mbuf *mh_nextpkt; /* Next packet in queue/record */ 61 | struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */ 62 | int mh_flags; /* Misc flags */ 63 | 64 | int mh_size; /* Size of data */ 65 | struct socket *mh_so; 66 | 67 | caddr_t mh_data; /* Location of data */ 68 | int mh_len; /* Amount of data in this mbuf */ 69 | }; 70 | 71 | /* 72 | * How much room is in the mbuf, from m_data to the end of the mbuf 73 | */ 74 | #define M_ROOM(m) ((m->m_flags & M_EXT)? \ 75 | (((m)->m_ext + (m)->m_size) - (m)->m_data) \ 76 | : \ 77 | (((m)->m_dat + (m)->m_size) - (m)->m_data)) 78 | 79 | /* 80 | * How much free room there is 81 | */ 82 | #define M_FREEROOM(m) (M_ROOM(m) - (m)->m_len) 83 | #define M_TRAILINGSPACE M_FREEROOM 84 | 85 | struct mbuf { 86 | struct m_hdr m_hdr; 87 | Slirp *slirp; 88 | union M_dat { 89 | char m_dat_[1]; /* ANSI don't like 0 sized arrays */ 90 | char *m_ext_; 91 | } M_dat; 92 | }; 93 | 94 | #define m_next m_hdr.mh_next 95 | #define m_prev m_hdr.mh_prev 96 | #define m_nextpkt m_hdr.mh_nextpkt 97 | #define m_prevpkt m_hdr.mh_prevpkt 98 | #define m_flags m_hdr.mh_flags 99 | #define m_len m_hdr.mh_len 100 | #define m_data m_hdr.mh_data 101 | #define m_size m_hdr.mh_size 102 | #define m_dat M_dat.m_dat_ 103 | #define m_ext M_dat.m_ext_ 104 | #define m_so m_hdr.mh_so 105 | 106 | #define ifq_prev m_prev 107 | #define ifq_next m_next 108 | #define ifs_prev m_prevpkt 109 | #define ifs_next m_nextpkt 110 | #define ifq_so m_so 111 | 112 | #define M_EXT 0x01 /* m_ext points to more (malloced) data */ 113 | #define M_FREELIST 0x02 /* mbuf is on free list */ 114 | #define M_USEDLIST 0x04 /* XXX mbuf is on used list (for dtom()) */ 115 | #define M_DOFREE 0x08 /* when m_free is called on the mbuf, free() 116 | * it rather than putting it on the free list */ 117 | 118 | void m_init(Slirp *); 119 | struct mbuf * m_get(Slirp *); 120 | void m_free(struct mbuf *); 121 | void m_cat(register struct mbuf *, register struct mbuf *); 122 | void m_inc(struct mbuf *, int); 123 | void m_adj(struct mbuf *, int); 124 | int m_copy(struct mbuf *, struct mbuf *, int, int); 125 | struct mbuf * dtom(Slirp *, void *); 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /tinyemu/slirp/misc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1995 Danny Gasparovski. 3 | * 4 | * Please read the file COPYRIGHT for the 5 | * terms and conditions of the copyright. 6 | */ 7 | 8 | #ifndef _MISC_H_ 9 | #define _MISC_H_ 10 | 11 | struct ex_list { 12 | int ex_pty; /* Do we want a pty? */ 13 | struct in_addr ex_addr; /* Server address */ 14 | int ex_fport; /* Port to telnet to */ 15 | const char *ex_exec; /* Command line of what to exec */ 16 | struct ex_list *ex_next; 17 | }; 18 | 19 | #ifndef HAVE_STRDUP 20 | char *strdup(const char *); 21 | #endif 22 | 23 | void do_wait(int); 24 | 25 | #define EMU_NONE 0x0 26 | 27 | /* TCP emulations */ 28 | #define EMU_CTL 0x1 29 | #define EMU_FTP 0x2 30 | #define EMU_KSH 0x3 31 | #define EMU_IRC 0x4 32 | #define EMU_REALAUDIO 0x5 33 | #define EMU_RLOGIN 0x6 34 | #define EMU_IDENT 0x7 35 | #define EMU_RSH 0x8 36 | 37 | #define EMU_NOCONNECT 0x10 /* Don't connect */ 38 | 39 | struct tos_t { 40 | uint16_t lport; 41 | uint16_t fport; 42 | uint8_t tos; 43 | uint8_t emu; 44 | }; 45 | 46 | struct emu_t { 47 | uint16_t lport; 48 | uint16_t fport; 49 | uint8_t tos; 50 | uint8_t emu; 51 | struct emu_t *next; 52 | }; 53 | 54 | extern int x_port, x_server, x_display; 55 | 56 | int show_x(char *, struct socket *); 57 | void redir_x(uint32_t, int, int, int); 58 | void slirp_insque(void *, void *); 59 | void slirp_remque(void *); 60 | int add_exec(struct ex_list **, int, char *, struct in_addr, int); 61 | int slirp_openpty(int *, int *); 62 | int fork_exec(struct socket *so, const char *ex, int do_pty); 63 | void snooze_hup(int); 64 | void snooze(void); 65 | void relay(int); 66 | void add_emu(char *); 67 | void fd_nonblock(int); 68 | void fd_block(int); 69 | int rsh_exec(struct socket *, struct socket *, char *, char *, char *); 70 | int os_socket(int domain, int type, int protocol); 71 | uint32_t os_get_time_ms(void); 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /tinyemu/slirp/sbuf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1995 Danny Gasparovski. 3 | * 4 | * Please read the file COPYRIGHT for the 5 | * terms and conditions of the copyright. 6 | */ 7 | 8 | #include "slirp.h" 9 | 10 | static void sbappendsb(struct sbuf *sb, struct mbuf *m); 11 | 12 | void 13 | sbfree(struct sbuf *sb) 14 | { 15 | free(sb->sb_data); 16 | } 17 | 18 | void 19 | sbdrop(struct sbuf *sb, int num) 20 | { 21 | /* 22 | * We can only drop how much we have 23 | * This should never succeed 24 | */ 25 | if(num > sb->sb_cc) 26 | num = sb->sb_cc; 27 | sb->sb_cc -= num; 28 | sb->sb_rptr += num; 29 | if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen) 30 | sb->sb_rptr -= sb->sb_datalen; 31 | 32 | } 33 | 34 | void 35 | sbreserve(struct sbuf *sb, int size) 36 | { 37 | if (sb->sb_data) { 38 | /* Already alloced, realloc if necessary */ 39 | if (sb->sb_datalen != size) { 40 | sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size); 41 | sb->sb_cc = 0; 42 | if (sb->sb_wptr) 43 | sb->sb_datalen = size; 44 | else 45 | sb->sb_datalen = 0; 46 | } 47 | } else { 48 | sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size); 49 | sb->sb_cc = 0; 50 | if (sb->sb_wptr) 51 | sb->sb_datalen = size; 52 | else 53 | sb->sb_datalen = 0; 54 | } 55 | } 56 | 57 | /* 58 | * Try and write() to the socket, whatever doesn't get written 59 | * append to the buffer... for a host with a fast net connection, 60 | * this prevents an unnecessary copy of the data 61 | * (the socket is non-blocking, so we won't hang) 62 | */ 63 | void 64 | sbappend(struct socket *so, struct mbuf *m) 65 | { 66 | int ret = 0; 67 | 68 | DEBUG_CALL("sbappend"); 69 | DEBUG_ARG("so = %lx", (long)so); 70 | DEBUG_ARG("m = %lx", (long)m); 71 | DEBUG_ARG("m->m_len = %d", m->m_len); 72 | 73 | /* Shouldn't happen, but... e.g. foreign host closes connection */ 74 | if (m->m_len <= 0) { 75 | m_free(m); 76 | return; 77 | } 78 | 79 | /* 80 | * If there is urgent data, call sosendoob 81 | * if not all was sent, sowrite will take care of the rest 82 | * (The rest of this function is just an optimisation) 83 | */ 84 | if (so->so_urgc) { 85 | sbappendsb(&so->so_rcv, m); 86 | m_free(m); 87 | sosendoob(so); 88 | return; 89 | } 90 | 91 | /* 92 | * We only write if there's nothing in the buffer, 93 | * ottherwise it'll arrive out of order, and hence corrupt 94 | */ 95 | if (!so->so_rcv.sb_cc) 96 | ret = slirp_send(so, m->m_data, m->m_len, 0); 97 | 98 | if (ret <= 0) { 99 | /* 100 | * Nothing was written 101 | * It's possible that the socket has closed, but 102 | * we don't need to check because if it has closed, 103 | * it will be detected in the normal way by soread() 104 | */ 105 | sbappendsb(&so->so_rcv, m); 106 | } else if (ret != m->m_len) { 107 | /* 108 | * Something was written, but not everything.. 109 | * sbappendsb the rest 110 | */ 111 | m->m_len -= ret; 112 | m->m_data += ret; 113 | sbappendsb(&so->so_rcv, m); 114 | } /* else */ 115 | /* Whatever happened, we free the mbuf */ 116 | m_free(m); 117 | } 118 | 119 | /* 120 | * Copy the data from m into sb 121 | * The caller is responsible to make sure there's enough room 122 | */ 123 | static void 124 | sbappendsb(struct sbuf *sb, struct mbuf *m) 125 | { 126 | int len, n, nn; 127 | 128 | len = m->m_len; 129 | 130 | if (sb->sb_wptr < sb->sb_rptr) { 131 | n = sb->sb_rptr - sb->sb_wptr; 132 | if (n > len) n = len; 133 | memcpy(sb->sb_wptr, m->m_data, n); 134 | } else { 135 | /* Do the right edge first */ 136 | n = sb->sb_data + sb->sb_datalen - sb->sb_wptr; 137 | if (n > len) n = len; 138 | memcpy(sb->sb_wptr, m->m_data, n); 139 | len -= n; 140 | if (len) { 141 | /* Now the left edge */ 142 | nn = sb->sb_rptr - sb->sb_data; 143 | if (nn > len) nn = len; 144 | memcpy(sb->sb_data,m->m_data+n,nn); 145 | n += nn; 146 | } 147 | } 148 | 149 | sb->sb_cc += n; 150 | sb->sb_wptr += n; 151 | if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen) 152 | sb->sb_wptr -= sb->sb_datalen; 153 | } 154 | 155 | /* 156 | * Copy data from sbuf to a normal, straight buffer 157 | * Don't update the sbuf rptr, this will be 158 | * done in sbdrop when the data is acked 159 | */ 160 | void 161 | sbcopy(struct sbuf *sb, int off, int len, char *to) 162 | { 163 | char *from; 164 | 165 | from = sb->sb_rptr + off; 166 | if (from >= sb->sb_data + sb->sb_datalen) 167 | from -= sb->sb_datalen; 168 | 169 | if (from < sb->sb_wptr) { 170 | if (len > sb->sb_cc) len = sb->sb_cc; 171 | memcpy(to,from,len); 172 | } else { 173 | /* re-use off */ 174 | off = (sb->sb_data + sb->sb_datalen) - from; 175 | if (off > len) off = len; 176 | memcpy(to,from,off); 177 | len -= off; 178 | if (len) 179 | memcpy(to+off,sb->sb_data,len); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /tinyemu/slirp/sbuf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1995 Danny Gasparovski. 3 | * 4 | * Please read the file COPYRIGHT for the 5 | * terms and conditions of the copyright. 6 | */ 7 | 8 | #ifndef _SBUF_H_ 9 | #define _SBUF_H_ 10 | 11 | #define sbflush(sb) sbdrop((sb),(sb)->sb_cc) 12 | #define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc) 13 | 14 | struct sbuf { 15 | u_int sb_cc; /* actual chars in buffer */ 16 | u_int sb_datalen; /* Length of data */ 17 | char *sb_wptr; /* write pointer. points to where the next 18 | * bytes should be written in the sbuf */ 19 | char *sb_rptr; /* read pointer. points to where the next 20 | * byte should be read from the sbuf */ 21 | char *sb_data; /* Actual data */ 22 | }; 23 | 24 | void sbfree(struct sbuf *); 25 | void sbdrop(struct sbuf *, int); 26 | void sbreserve(struct sbuf *, int); 27 | void sbappend(struct socket *, struct mbuf *); 28 | void sbcopy(struct sbuf *, int, int, char *); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /tinyemu/slirp/slirp_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * User definable configuration options 3 | */ 4 | 5 | /* Define if you want the connection to be probed */ 6 | /* XXX Not working yet, so ignore this for now */ 7 | #undef PROBE_CONN 8 | 9 | /* Define to 1 if you want KEEPALIVE timers */ 10 | #define DO_KEEPALIVE 0 11 | 12 | /* Define to MAX interfaces you expect to use at once */ 13 | /* MAX_INTERFACES determines the max. TOTAL number of interfaces (SLIP and PPP) */ 14 | /* MAX_PPP_INTERFACES determines max. number of PPP interfaces */ 15 | #define MAX_INTERFACES 1 16 | #define MAX_PPP_INTERFACES 1 17 | 18 | /* Define if you want slirp's socket in /tmp */ 19 | /* XXXXXX Do this in ./configure */ 20 | #undef USE_TMPSOCKET 21 | 22 | /* Define if you want slirp to use cfsetXspeed() on the terminal */ 23 | #undef DO_CFSETSPEED 24 | 25 | /* Define this if you want slirp to write to the tty as fast as it can */ 26 | /* This should only be set if you are using load-balancing, slirp does a */ 27 | /* pretty good job on single modems already, and seting this will make */ 28 | /* interactive sessions less responsive */ 29 | /* XXXXX Talk about having fast modem as unit 0 */ 30 | #undef FULL_BOLT 31 | 32 | /* 33 | * Define if you want slirp to use less CPU 34 | * You will notice a small lag in interactive sessions, but it's not that bad 35 | * Things like Netscape/ftp/etc. are completely unaffected 36 | * This is mainly for sysadmins who have many slirp users 37 | */ 38 | #undef USE_LOWCPU 39 | 40 | /* Define this if your compiler doesn't like prototypes */ 41 | #ifndef __STDC__ 42 | #define NO_PROTOTYPES 43 | #endif 44 | 45 | /*********************************************************/ 46 | /* 47 | * Autoconf defined configuration options 48 | * You shouldn't need to touch any of these 49 | */ 50 | 51 | /* Ignore this */ 52 | #undef DUMMY_PPP 53 | 54 | /* Define if you have unistd.h */ 55 | #define HAVE_UNISTD_H 56 | 57 | /* Define if you have stdlib.h */ 58 | #define HAVE_STDLIB_H 59 | 60 | /* Define if you have sys/ioctl.h */ 61 | #undef HAVE_SYS_IOCTL_H 62 | #ifndef _WIN32 63 | #define HAVE_SYS_IOCTL_H 64 | #endif 65 | 66 | /* Define if you have sys/filio.h */ 67 | #undef HAVE_SYS_FILIO_H 68 | #ifdef __APPLE__ 69 | #define HAVE_SYS_FILIO_H 70 | #endif 71 | 72 | /* Define if you have strerror */ 73 | #define HAVE_STRERROR 74 | 75 | /* Define if you have strdup() */ 76 | #define HAVE_STRDUP 77 | 78 | /* Define according to how time.h should be included */ 79 | #define TIME_WITH_SYS_TIME 0 80 | #undef HAVE_SYS_TIME_H 81 | 82 | /* Define if you have sys/bitypes.h */ 83 | #undef HAVE_SYS_BITYPES_H 84 | 85 | /* Define if the machine is big endian */ 86 | //#undef HOST_WORDS_BIGENDIAN 87 | 88 | /* Define if you have readv */ 89 | #undef HAVE_READV 90 | 91 | /* Define if iovec needs to be declared */ 92 | #undef DECLARE_IOVEC 93 | #ifdef _WIN32 94 | #define DECLARE_IOVEC 95 | #endif 96 | 97 | /* Define if you have a POSIX.1 sys/wait.h */ 98 | #undef HAVE_SYS_WAIT_H 99 | 100 | /* Define if you have sys/select.h */ 101 | #undef HAVE_SYS_SELECT_H 102 | #ifndef _WIN32 103 | #define HAVE_SYS_SELECT_H 104 | #endif 105 | 106 | /* Define if you have strings.h */ 107 | #define HAVE_STRING_H 108 | 109 | /* Define if you have arpa/inet.h */ 110 | #undef HAVE_ARPA_INET_H 111 | #ifndef _WIN32 112 | #define HAVE_ARPA_INET_H 113 | #endif 114 | 115 | /* Define if you have sys/signal.h */ 116 | #undef HAVE_SYS_SIGNAL_H 117 | 118 | /* Define if you have sys/stropts.h */ 119 | #undef HAVE_SYS_STROPTS_H 120 | 121 | /* Define to whatever your compiler thinks inline should be */ 122 | //#define inline inline 123 | 124 | /* Define to whatever your compiler thinks const should be */ 125 | //#define const const 126 | 127 | /* Define if your compiler doesn't like prototypes */ 128 | #undef NO_PROTOTYPES 129 | 130 | /* Define to sizeof(char) */ 131 | #define SIZEOF_CHAR 1 132 | 133 | /* Define to sizeof(short) */ 134 | #define SIZEOF_SHORT 2 135 | 136 | /* Define to sizeof(int) */ 137 | #define SIZEOF_INT 4 138 | 139 | /* Define to sizeof(char *) */ 140 | #define SIZEOF_CHAR_P (HOST_LONG_BITS / 8) 141 | 142 | /* Define if you have random() */ 143 | #undef HAVE_RANDOM 144 | 145 | /* Define if you have srandom() */ 146 | #undef HAVE_SRANDOM 147 | 148 | /* Define if you have inet_aton */ 149 | #undef HAVE_INET_ATON 150 | #ifndef _WIN32 151 | #define HAVE_INET_ATON 152 | #endif 153 | 154 | /* Define if you have setenv */ 155 | #undef HAVE_SETENV 156 | 157 | /* Define if you have index() */ 158 | #define HAVE_INDEX 159 | 160 | /* Define if you have bcmp() */ 161 | #undef HAVE_BCMP 162 | 163 | /* Define if you have drand48 */ 164 | #undef HAVE_DRAND48 165 | 166 | /* Define if you have memmove */ 167 | #define HAVE_MEMMOVE 168 | 169 | /* Define if you have gethostid */ 170 | #define HAVE_GETHOSTID 171 | 172 | /* Define if you DON'T have unix-domain sockets */ 173 | #undef NO_UNIX_SOCKETS 174 | #ifdef _WIN32 175 | #define NO_UNIX_SOCKETS 176 | #endif 177 | 178 | /* Define if you have revoke() */ 179 | #undef HAVE_REVOKE 180 | 181 | /* Define if you have the sysv method of opening pty's (/dev/ptmx, etc.) */ 182 | #undef HAVE_GRANTPT 183 | 184 | /* Define if you have fchmod */ 185 | #undef HAVE_FCHMOD 186 | 187 | /* Define if you have */ 188 | #undef HAVE_SYS_TYPES32_H 189 | -------------------------------------------------------------------------------- /tinyemu/slirp/socket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1995 Danny Gasparovski. 3 | * 4 | * Please read the file COPYRIGHT for the 5 | * terms and conditions of the copyright. 6 | */ 7 | 8 | #ifndef _SLIRP_SOCKET_H_ 9 | #define _SLIRP_SOCKET_H_ 10 | 11 | #define SO_EXPIRE 240000 12 | #define SO_EXPIREFAST 10000 13 | 14 | /* 15 | * Our socket structure 16 | */ 17 | 18 | struct socket { 19 | struct socket *so_next,*so_prev; /* For a linked list of sockets */ 20 | 21 | int s; /* The actual socket */ 22 | 23 | Slirp *slirp; /* managing slirp instance */ 24 | 25 | /* XXX union these with not-yet-used sbuf params */ 26 | struct mbuf *so_m; /* Pointer to the original SYN packet, 27 | * for non-blocking connect()'s, and 28 | * PING reply's */ 29 | struct tcpiphdr *so_ti; /* Pointer to the original ti within 30 | * so_mconn, for non-blocking connections */ 31 | int so_urgc; 32 | struct in_addr so_faddr; /* foreign host table entry */ 33 | struct in_addr so_laddr; /* local host table entry */ 34 | uint16_t so_fport; /* foreign port */ 35 | uint16_t so_lport; /* local port */ 36 | 37 | uint8_t so_iptos; /* Type of service */ 38 | uint8_t so_emu; /* Is the socket emulated? */ 39 | 40 | u_char so_type; /* Type of socket, UDP or TCP */ 41 | int so_state; /* internal state flags SS_*, below */ 42 | 43 | struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */ 44 | u_int so_expire; /* When the socket will expire */ 45 | 46 | int so_queued; /* Number of packets queued from this socket */ 47 | int so_nqueued; /* Number of packets queued in a row 48 | * Used to determine when to "downgrade" a session 49 | * from fastq to batchq */ 50 | 51 | struct sbuf so_rcv; /* Receive buffer */ 52 | struct sbuf so_snd; /* Send buffer */ 53 | void * extra; /* Extra pointer */ 54 | }; 55 | 56 | 57 | /* 58 | * Socket state bits. (peer means the host on the Internet, 59 | * local host means the host on the other end of the modem) 60 | */ 61 | #define SS_NOFDREF 0x001 /* No fd reference */ 62 | 63 | #define SS_ISFCONNECTING 0x002 /* Socket is connecting to peer (non-blocking connect()'s) */ 64 | #define SS_ISFCONNECTED 0x004 /* Socket is connected to peer */ 65 | #define SS_FCANTRCVMORE 0x008 /* Socket can't receive more from peer (for half-closes) */ 66 | #define SS_FCANTSENDMORE 0x010 /* Socket can't send more to peer (for half-closes) */ 67 | #define SS_FWDRAIN 0x040 /* We received a FIN, drain data and set SS_FCANTSENDMORE */ 68 | 69 | #define SS_CTL 0x080 70 | #define SS_FACCEPTCONN 0x100 /* Socket is accepting connections from a host on the internet */ 71 | #define SS_FACCEPTONCE 0x200 /* If set, the SS_FACCEPTCONN socket will die after one accept */ 72 | 73 | #define SS_PERSISTENT_MASK 0xf000 /* Unremovable state bits */ 74 | #define SS_HOSTFWD 0x1000 /* Socket describes host->guest forwarding */ 75 | #define SS_INCOMING 0x2000 /* Connection was initiated by a host on the internet */ 76 | 77 | struct socket * solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int); 78 | struct socket * socreate(Slirp *); 79 | void sofree(struct socket *); 80 | int soread(struct socket *); 81 | void sorecvoob(struct socket *); 82 | int sosendoob(struct socket *); 83 | int sowrite(struct socket *); 84 | void sorecvfrom(struct socket *); 85 | int sosendto(struct socket *, struct mbuf *); 86 | struct socket * tcp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int, 87 | int); 88 | void soisfconnecting(register struct socket *); 89 | void soisfconnected(register struct socket *); 90 | void sofwdrain(struct socket *); 91 | struct iovec; /* For win32 */ 92 | size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np); 93 | int soreadbuf(struct socket *so, const char *buf, int size); 94 | 95 | #endif /* _SOCKET_H_ */ 96 | -------------------------------------------------------------------------------- /tinyemu/slirp/tcp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1982, 1986, 1993 3 | * The Regents of the University of California. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the University nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * @(#)tcp.h 8.1 (Berkeley) 6/10/93 30 | * tcp.h,v 1.3 1994/08/21 05:27:34 paul Exp 31 | */ 32 | 33 | #ifndef _TCP_H_ 34 | #define _TCP_H_ 35 | 36 | typedef uint32_t tcp_seq; 37 | 38 | #define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */ 39 | #define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */ 40 | 41 | #define TCP_SNDSPACE 8192 42 | #define TCP_RCVSPACE 8192 43 | 44 | /* 45 | * TCP header. 46 | * Per RFC 793, September, 1981. 47 | */ 48 | struct tcphdr { 49 | uint16_t th_sport; /* source port */ 50 | uint16_t th_dport; /* destination port */ 51 | tcp_seq th_seq; /* sequence number */ 52 | tcp_seq th_ack; /* acknowledgement number */ 53 | #ifdef HOST_WORDS_BIGENDIAN 54 | u_int th_off:4, /* data offset */ 55 | th_x2:4; /* (unused) */ 56 | #else 57 | u_int th_x2:4, /* (unused) */ 58 | th_off:4; /* data offset */ 59 | #endif 60 | uint8_t th_flags; 61 | #define TH_FIN 0x01 62 | #define TH_SYN 0x02 63 | #define TH_RST 0x04 64 | #define TH_PUSH 0x08 65 | #define TH_ACK 0x10 66 | #define TH_URG 0x20 67 | uint16_t th_win; /* window */ 68 | uint16_t th_sum; /* checksum */ 69 | uint16_t th_urp; /* urgent pointer */ 70 | }; 71 | 72 | #include "tcp_var.h" 73 | 74 | #define TCPOPT_EOL 0 75 | #define TCPOPT_NOP 1 76 | #define TCPOPT_MAXSEG 2 77 | #define TCPOLEN_MAXSEG 4 78 | #define TCPOPT_WINDOW 3 79 | #define TCPOLEN_WINDOW 3 80 | #define TCPOPT_SACK_PERMITTED 4 /* Experimental */ 81 | #define TCPOLEN_SACK_PERMITTED 2 82 | #define TCPOPT_SACK 5 /* Experimental */ 83 | #define TCPOPT_TIMESTAMP 8 84 | #define TCPOLEN_TIMESTAMP 10 85 | #define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */ 86 | 87 | #define TCPOPT_TSTAMP_HDR \ 88 | (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP) 89 | 90 | /* 91 | * Default maximum segment size for TCP. 92 | * With an IP MSS of 576, this is 536, 93 | * but 512 is probably more convenient. 94 | * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)). 95 | * 96 | * We make this 1460 because we only care about Ethernet in the qemu context. 97 | */ 98 | #define TCP_MSS 1460 99 | 100 | #define TCP_MAXWIN 65535 /* largest value for (unscaled) window */ 101 | 102 | #define TCP_MAX_WINSHIFT 14 /* maximum window shift */ 103 | 104 | /* 105 | * User-settable options (used with setsockopt). 106 | * 107 | * We don't use the system headers on unix because we have conflicting 108 | * local structures. We can't avoid the system definitions on Windows, 109 | * so we undefine them. 110 | */ 111 | #undef TCP_NODELAY 112 | #define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ 113 | #undef TCP_MAXSEG 114 | 115 | /* 116 | * TCP FSM state definitions. 117 | * Per RFC793, September, 1981. 118 | */ 119 | 120 | #define TCP_NSTATES 11 121 | 122 | #define TCPS_CLOSED 0 /* closed */ 123 | #define TCPS_LISTEN 1 /* listening for connection */ 124 | #define TCPS_SYN_SENT 2 /* active, have sent syn */ 125 | #define TCPS_SYN_RECEIVED 3 /* have send and received syn */ 126 | /* states < TCPS_ESTABLISHED are those where connections not established */ 127 | #define TCPS_ESTABLISHED 4 /* established */ 128 | #define TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */ 129 | /* states > TCPS_CLOSE_WAIT are those where user has closed */ 130 | #define TCPS_FIN_WAIT_1 6 /* have closed, sent fin */ 131 | #define TCPS_CLOSING 7 /* closed xchd FIN; await FIN ACK */ 132 | #define TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */ 133 | /* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */ 134 | #define TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */ 135 | #define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */ 136 | 137 | #define TCPS_HAVERCVDSYN(s) ((s) >= TCPS_SYN_RECEIVED) 138 | #define TCPS_HAVEESTABLISHED(s) ((s) >= TCPS_ESTABLISHED) 139 | #define TCPS_HAVERCVDFIN(s) ((s) >= TCPS_TIME_WAIT) 140 | 141 | /* 142 | * TCP sequence numbers are 32 bit integers operated 143 | * on with modular arithmetic. These macros can be 144 | * used to compare such integers. 145 | */ 146 | #define SEQ_LT(a,b) ((int)((a)-(b)) < 0) 147 | #define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0) 148 | #define SEQ_GT(a,b) ((int)((a)-(b)) > 0) 149 | #define SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0) 150 | 151 | /* 152 | * Macros to initialize tcp sequence numbers for 153 | * send and receive from initial send and receive 154 | * sequence numbers. 155 | */ 156 | #define tcp_rcvseqinit(tp) \ 157 | (tp)->rcv_adv = (tp)->rcv_nxt = (tp)->irs + 1 158 | 159 | #define tcp_sendseqinit(tp) \ 160 | (tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = (tp)->iss 161 | 162 | #define TCP_ISSINCR (125*1024) /* increment for tcp_iss each second */ 163 | 164 | #endif 165 | -------------------------------------------------------------------------------- /tinyemu/slirp/tcp_timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1982, 1986, 1993 3 | * The Regents of the University of California. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the University nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * @(#)tcp_timer.h 8.1 (Berkeley) 6/10/93 30 | * tcp_timer.h,v 1.4 1994/08/21 05:27:38 paul Exp 31 | */ 32 | 33 | #ifndef _TCP_TIMER_H_ 34 | #define _TCP_TIMER_H_ 35 | 36 | /* 37 | * Definitions of the TCP timers. These timers are counted 38 | * down PR_SLOWHZ times a second. 39 | */ 40 | #define TCPT_NTIMERS 4 41 | 42 | #define TCPT_REXMT 0 /* retransmit */ 43 | #define TCPT_PERSIST 1 /* retransmit persistence */ 44 | #define TCPT_KEEP 2 /* keep alive */ 45 | #define TCPT_2MSL 3 /* 2*msl quiet time timer */ 46 | 47 | /* 48 | * The TCPT_REXMT timer is used to force retransmissions. 49 | * The TCP has the TCPT_REXMT timer set whenever segments 50 | * have been sent for which ACKs are expected but not yet 51 | * received. If an ACK is received which advances tp->snd_una, 52 | * then the retransmit timer is cleared (if there are no more 53 | * outstanding segments) or reset to the base value (if there 54 | * are more ACKs expected). Whenever the retransmit timer goes off, 55 | * we retransmit one unacknowledged segment, and do a backoff 56 | * on the retransmit timer. 57 | * 58 | * The TCPT_PERSIST timer is used to keep window size information 59 | * flowing even if the window goes shut. If all previous transmissions 60 | * have been acknowledged (so that there are no retransmissions in progress), 61 | * and the window is too small to bother sending anything, then we start 62 | * the TCPT_PERSIST timer. When it expires, if the window is nonzero, 63 | * we go to transmit state. Otherwise, at intervals send a single byte 64 | * into the peer's window to force him to update our window information. 65 | * We do this at most as often as TCPT_PERSMIN time intervals, 66 | * but no more frequently than the current estimate of round-trip 67 | * packet time. The TCPT_PERSIST timer is cleared whenever we receive 68 | * a window update from the peer. 69 | * 70 | * The TCPT_KEEP timer is used to keep connections alive. If an 71 | * connection is idle (no segments received) for TCPTV_KEEP_INIT amount of time, 72 | * but not yet established, then we drop the connection. Once the connection 73 | * is established, if the connection is idle for TCPTV_KEEP_IDLE time 74 | * (and keepalives have been enabled on the socket), we begin to probe 75 | * the connection. We force the peer to send us a segment by sending: 76 | * 77 | * This segment is (deliberately) outside the window, and should elicit 78 | * an ack segment in response from the peer. If, despite the TCPT_KEEP 79 | * initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE 80 | * amount of time probing, then we drop the connection. 81 | */ 82 | 83 | /* 84 | * Time constants. 85 | */ 86 | #define TCPTV_MSL ( 5*PR_SLOWHZ) /* max seg lifetime (hah!) */ 87 | 88 | #define TCPTV_SRTTBASE 0 /* base roundtrip time; 89 | if 0, no idea yet */ 90 | #define TCPTV_SRTTDFLT ( 3*PR_SLOWHZ) /* assumed RTT if no info */ 91 | 92 | #define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistence */ 93 | #define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */ 94 | 95 | #define TCPTV_KEEP_INIT ( 75*PR_SLOWHZ) /* initial connect keep alive */ 96 | #define TCPTV_KEEP_IDLE (120*60*PR_SLOWHZ) /* dflt time before probing */ 97 | #define TCPTV_KEEPINTVL ( 75*PR_SLOWHZ) /* default probe interval */ 98 | #define TCPTV_KEEPCNT 8 /* max probes before drop */ 99 | 100 | #define TCPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */ 101 | #define TCPTV_REXMTMAX ( 12*PR_SLOWHZ) /* max allowable REXMT value */ 102 | 103 | #define TCP_LINGERTIME 120 /* linger at most 2 minutes */ 104 | 105 | #define TCP_MAXRXTSHIFT 12 /* maximum retransmits */ 106 | 107 | 108 | /* 109 | * Force a time value to be in a certain range. 110 | */ 111 | #define TCPT_RANGESET(tv, value, tvmin, tvmax) { \ 112 | (tv) = (value); \ 113 | if ((tv) < (tvmin)) \ 114 | (tv) = (tvmin); \ 115 | else if ((tv) > (tvmax)) \ 116 | (tv) = (tvmax); \ 117 | } 118 | 119 | extern const int tcp_backoff[]; 120 | 121 | struct tcpcb; 122 | 123 | void tcp_fasttimo(Slirp *); 124 | void tcp_slowtimo(Slirp *); 125 | void tcp_canceltimers(struct tcpcb *); 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /tinyemu/slirp/tcp_var.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1982, 1986, 1993, 1994 3 | * The Regents of the University of California. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the University nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * @(#)tcp_var.h 8.3 (Berkeley) 4/10/94 30 | * tcp_var.h,v 1.3 1994/08/21 05:27:39 paul Exp 31 | */ 32 | 33 | #ifndef _TCP_VAR_H_ 34 | #define _TCP_VAR_H_ 35 | 36 | #include "tcpip.h" 37 | #include "tcp_timer.h" 38 | 39 | /* 40 | * Tcp control block, one per tcp; fields: 41 | */ 42 | struct tcpcb { 43 | struct tcpiphdr *seg_next; /* sequencing queue */ 44 | struct tcpiphdr *seg_prev; 45 | short t_state; /* state of this connection */ 46 | short t_timer[TCPT_NTIMERS]; /* tcp timers */ 47 | short t_rxtshift; /* log(2) of rexmt exp. backoff */ 48 | short t_rxtcur; /* current retransmit value */ 49 | short t_dupacks; /* consecutive dup acks recd */ 50 | u_short t_maxseg; /* maximum segment size */ 51 | char t_force; /* 1 if forcing out a byte */ 52 | u_short t_flags; 53 | #define TF_ACKNOW 0x0001 /* ack peer immediately */ 54 | #define TF_DELACK 0x0002 /* ack, but try to delay it */ 55 | #define TF_NODELAY 0x0004 /* don't delay packets to coalesce */ 56 | #define TF_NOOPT 0x0008 /* don't use tcp options */ 57 | #define TF_SENTFIN 0x0010 /* have sent FIN */ 58 | #define TF_REQ_SCALE 0x0020 /* have/will request window scaling */ 59 | #define TF_RCVD_SCALE 0x0040 /* other side has requested scaling */ 60 | #define TF_REQ_TSTMP 0x0080 /* have/will request timestamps */ 61 | #define TF_RCVD_TSTMP 0x0100 /* a timestamp was received in SYN */ 62 | #define TF_SACK_PERMIT 0x0200 /* other side said I could SACK */ 63 | 64 | struct tcpiphdr t_template; /* static skeletal packet for xmit */ 65 | 66 | struct socket *t_socket; /* back pointer to socket */ 67 | /* 68 | * The following fields are used as in the protocol specification. 69 | * See RFC783, Dec. 1981, page 21. 70 | */ 71 | /* send sequence variables */ 72 | tcp_seq snd_una; /* send unacknowledged */ 73 | tcp_seq snd_nxt; /* send next */ 74 | tcp_seq snd_up; /* send urgent pointer */ 75 | tcp_seq snd_wl1; /* window update seg seq number */ 76 | tcp_seq snd_wl2; /* window update seg ack number */ 77 | tcp_seq iss; /* initial send sequence number */ 78 | uint32_t snd_wnd; /* send window */ 79 | /* receive sequence variables */ 80 | uint32_t rcv_wnd; /* receive window */ 81 | tcp_seq rcv_nxt; /* receive next */ 82 | tcp_seq rcv_up; /* receive urgent pointer */ 83 | tcp_seq irs; /* initial receive sequence number */ 84 | /* 85 | * Additional variables for this implementation. 86 | */ 87 | /* receive variables */ 88 | tcp_seq rcv_adv; /* advertised window */ 89 | /* retransmit variables */ 90 | tcp_seq snd_max; /* highest sequence number sent; 91 | * used to recognize retransmits 92 | */ 93 | /* congestion control (for slow start, source quench, retransmit after loss) */ 94 | uint32_t snd_cwnd; /* congestion-controlled window */ 95 | uint32_t snd_ssthresh; /* snd_cwnd size threshold for 96 | * for slow start exponential to 97 | * linear switch 98 | */ 99 | /* 100 | * transmit timing stuff. See below for scale of srtt and rttvar. 101 | * "Variance" is actually smoothed difference. 102 | */ 103 | short t_idle; /* inactivity time */ 104 | short t_rtt; /* round trip time */ 105 | tcp_seq t_rtseq; /* sequence number being timed */ 106 | short t_srtt; /* smoothed round-trip time */ 107 | short t_rttvar; /* variance in round-trip time */ 108 | u_short t_rttmin; /* minimum rtt allowed */ 109 | uint32_t max_sndwnd; /* largest window peer has offered */ 110 | 111 | /* out-of-band data */ 112 | char t_oobflags; /* have some */ 113 | char t_iobc; /* input character */ 114 | #define TCPOOB_HAVEDATA 0x01 115 | #define TCPOOB_HADDATA 0x02 116 | short t_softerror; /* possible error not yet reported */ 117 | 118 | /* RFC 1323 variables */ 119 | u_char snd_scale; /* window scaling for send window */ 120 | u_char rcv_scale; /* window scaling for recv window */ 121 | u_char request_r_scale; /* pending window scaling */ 122 | u_char requested_s_scale; 123 | uint32_t ts_recent; /* timestamp echo data */ 124 | uint32_t ts_recent_age; /* when last updated */ 125 | tcp_seq last_ack_sent; 126 | 127 | }; 128 | 129 | #define sototcpcb(so) ((so)->so_tcpcb) 130 | 131 | /* 132 | * The smoothed round-trip time and estimated variance 133 | * are stored as fixed point numbers scaled by the values below. 134 | * For convenience, these scales are also used in smoothing the average 135 | * (smoothed = (1/scale)sample + ((scale-1)/scale)smoothed). 136 | * With these scales, srtt has 3 bits to the right of the binary point, 137 | * and thus an "ALPHA" of 0.875. rttvar has 2 bits to the right of the 138 | * binary point, and is smoothed with an ALPHA of 0.75. 139 | */ 140 | #define TCP_RTT_SCALE 8 /* multiplier for srtt; 3 bits frac. */ 141 | #define TCP_RTT_SHIFT 3 /* shift for srtt; 3 bits frac. */ 142 | #define TCP_RTTVAR_SCALE 4 /* multiplier for rttvar; 2 bits */ 143 | #define TCP_RTTVAR_SHIFT 2 /* multiplier for rttvar; 2 bits */ 144 | 145 | /* 146 | * The initial retransmission should happen at rtt + 4 * rttvar. 147 | * Because of the way we do the smoothing, srtt and rttvar 148 | * will each average +1/2 tick of bias. When we compute 149 | * the retransmit timer, we want 1/2 tick of rounding and 150 | * 1 extra tick because of +-1/2 tick uncertainty in the 151 | * firing of the timer. The bias will give us exactly the 152 | * 1.5 tick we need. But, because the bias is 153 | * statistical, we have to test that we don't drop below 154 | * the minimum feasible timer (which is 2 ticks). 155 | * This macro assumes that the value of TCP_RTTVAR_SCALE 156 | * is the same as the multiplier for rttvar. 157 | */ 158 | #define TCP_REXMTVAL(tp) \ 159 | (((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar) 160 | 161 | #endif 162 | -------------------------------------------------------------------------------- /tinyemu/slirp/tcpip.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1982, 1986, 1993 3 | * The Regents of the University of California. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the University nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * @(#)tcpip.h 8.1 (Berkeley) 6/10/93 30 | * tcpip.h,v 1.3 1994/08/21 05:27:40 paul Exp 31 | */ 32 | 33 | #ifndef _TCPIP_H_ 34 | #define _TCPIP_H_ 35 | 36 | /* 37 | * Tcp+ip header, after ip options removed. 38 | */ 39 | struct tcpiphdr { 40 | struct ipovly ti_i; /* overlaid ip structure */ 41 | struct tcphdr ti_t; /* tcp header */ 42 | }; 43 | #define ti_mbuf ti_i.ih_mbuf.mptr 44 | #define ti_x1 ti_i.ih_x1 45 | #define ti_pr ti_i.ih_pr 46 | #define ti_len ti_i.ih_len 47 | #define ti_src ti_i.ih_src 48 | #define ti_dst ti_i.ih_dst 49 | #define ti_sport ti_t.th_sport 50 | #define ti_dport ti_t.th_dport 51 | #define ti_seq ti_t.th_seq 52 | #define ti_ack ti_t.th_ack 53 | #define ti_x2 ti_t.th_x2 54 | #define ti_off ti_t.th_off 55 | #define ti_flags ti_t.th_flags 56 | #define ti_win ti_t.th_win 57 | #define ti_sum ti_t.th_sum 58 | #define ti_urp ti_t.th_urp 59 | 60 | #define tcpiphdr2qlink(T) ((struct qlink*)(((char*)(T)) - sizeof(struct qlink))) 61 | #define qlink2tcpiphdr(Q) ((struct tcpiphdr*)(((char*)(Q)) + sizeof(struct qlink))) 62 | #define tcpiphdr_next(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->next) 63 | #define tcpiphdr_prev(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->prev) 64 | #define tcpfrag_list_first(T) qlink2tcpiphdr((T)->seg_next) 65 | #define tcpfrag_list_end(F, T) (tcpiphdr2qlink(F) == (struct qlink*)(T)) 66 | #define tcpfrag_list_empty(T) ((T)->seg_next == (struct tcpiphdr*)(T)) 67 | 68 | /* 69 | * Just a clean way to get to the first byte 70 | * of the packet 71 | */ 72 | struct tcpiphdr_2 { 73 | struct tcpiphdr dummy; 74 | char first_char; 75 | }; 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /tinyemu/slirp/tftp.h: -------------------------------------------------------------------------------- 1 | /* tftp defines */ 2 | 3 | #define TFTP_SESSIONS_MAX 3 4 | 5 | #define TFTP_SERVER 69 6 | 7 | #define TFTP_RRQ 1 8 | #define TFTP_WRQ 2 9 | #define TFTP_DATA 3 10 | #define TFTP_ACK 4 11 | #define TFTP_ERROR 5 12 | #define TFTP_OACK 6 13 | 14 | #define TFTP_FILENAME_MAX 512 15 | 16 | struct tftp_t { 17 | struct ip ip; 18 | struct udphdr udp; 19 | uint16_t tp_op; 20 | union { 21 | struct { 22 | uint16_t tp_block_nr; 23 | uint8_t tp_buf[512]; 24 | } tp_data; 25 | struct { 26 | uint16_t tp_error_code; 27 | uint8_t tp_msg[512]; 28 | } tp_error; 29 | uint8_t tp_buf[512 + 2]; 30 | } x; 31 | }; 32 | 33 | struct tftp_session { 34 | Slirp *slirp; 35 | char *filename; 36 | 37 | struct in_addr client_ip; 38 | uint16_t client_port; 39 | 40 | int timestamp; 41 | }; 42 | 43 | void tftp_input(struct mbuf *m); 44 | -------------------------------------------------------------------------------- /tinyemu/slirp/udp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1982, 1986, 1993 3 | * The Regents of the University of California. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the University nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * @(#)udp.h 8.1 (Berkeley) 6/10/93 30 | * udp.h,v 1.3 1994/08/21 05:27:41 paul Exp 31 | */ 32 | 33 | #ifndef _UDP_H_ 34 | #define _UDP_H_ 35 | 36 | #define UDP_TTL 0x60 37 | #define UDP_UDPDATALEN 16192 38 | 39 | /* 40 | * Udp protocol header. 41 | * Per RFC 768, September, 1981. 42 | */ 43 | struct udphdr { 44 | uint16_t uh_sport; /* source port */ 45 | uint16_t uh_dport; /* destination port */ 46 | int16_t uh_ulen; /* udp length */ 47 | uint16_t uh_sum; /* udp checksum */ 48 | }; 49 | 50 | /* 51 | * UDP kernel structures and variables. 52 | */ 53 | struct udpiphdr { 54 | struct ipovly ui_i; /* overlaid ip structure */ 55 | struct udphdr ui_u; /* udp header */ 56 | }; 57 | #define ui_mbuf ui_i.ih_mbuf.mptr 58 | #define ui_x1 ui_i.ih_x1 59 | #define ui_pr ui_i.ih_pr 60 | #define ui_len ui_i.ih_len 61 | #define ui_src ui_i.ih_src 62 | #define ui_dst ui_i.ih_dst 63 | #define ui_sport ui_u.uh_sport 64 | #define ui_dport ui_u.uh_dport 65 | #define ui_ulen ui_u.uh_ulen 66 | #define ui_sum ui_u.uh_sum 67 | 68 | /* 69 | * Names for UDP sysctl objects 70 | */ 71 | #define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ 72 | #define UDPCTL_MAXID 2 73 | 74 | struct mbuf; 75 | 76 | void udp_init(Slirp *); 77 | void udp_input(register struct mbuf *, int); 78 | int udp_output(struct socket *, struct mbuf *, struct sockaddr_in *); 79 | int udp_attach(struct socket *); 80 | void udp_detach(struct socket *); 81 | struct socket * udp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int, 82 | int); 83 | int udp_output2(struct socket *so, struct mbuf *m, 84 | struct sockaddr_in *saddr, struct sockaddr_in *daddr, 85 | int iptos); 86 | #endif 87 | -------------------------------------------------------------------------------- /tinyemu/softfp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SoftFP Library 3 | * 4 | * Copyright (c) 2016 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "cutils.h" 30 | #include "softfp.h" 31 | 32 | static inline int clz32(uint32_t a) 33 | { 34 | int r; 35 | if (a == 0) { 36 | r = 32; 37 | } else { 38 | r = __builtin_clz(a); 39 | } 40 | return r; 41 | } 42 | 43 | static inline int clz64(uint64_t a) 44 | { 45 | int r; 46 | if (a == 0) { 47 | r = 64; 48 | } else 49 | { 50 | r = __builtin_clzll(a); 51 | } 52 | return r; 53 | } 54 | 55 | #ifdef HAVE_INT128 56 | static inline int clz128(uint128_t a) 57 | { 58 | int r; 59 | if (a == 0) { 60 | r = 128; 61 | } else 62 | { 63 | uint64_t ah, al; 64 | ah = a >> 64; 65 | al = a; 66 | if (ah != 0) 67 | r = __builtin_clzll(ah); 68 | else 69 | r = __builtin_clzll(al) + 64; 70 | } 71 | return r; 72 | } 73 | #endif 74 | 75 | #define F_SIZE 32 76 | #include "softfp_template.h" 77 | 78 | #define F_SIZE 64 79 | #include "softfp_template.h" 80 | 81 | #ifdef HAVE_INT128 82 | 83 | #define F_SIZE 128 84 | #include "softfp_template.h" 85 | 86 | #endif 87 | 88 | -------------------------------------------------------------------------------- /tinyemu/softfp_template_icvt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SoftFP Library 3 | * 4 | * Copyright (c) 2016 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #if ICVT_SIZE == 32 25 | #define ICVT_UINT uint32_t 26 | #define ICVT_INT int32_t 27 | #elif ICVT_SIZE == 64 28 | #define ICVT_UINT uint64_t 29 | #define ICVT_INT int64_t 30 | #elif ICVT_SIZE == 128 31 | #define ICVT_UINT uint128_t 32 | #define ICVT_INT int128_t 33 | #else 34 | #error unsupported icvt 35 | #endif 36 | 37 | /* conversions between float and integers */ 38 | static ICVT_INT glue(glue(glue(internal_cvt_sf, F_SIZE), _i), ICVT_SIZE)(F_UINT a, RoundingModeEnum rm, 39 | uint32_t *pfflags, BOOL is_unsigned) 40 | { 41 | uint32_t a_sign, addend, rnd_bits; 42 | int32_t a_exp; 43 | F_UINT a_mant; 44 | ICVT_UINT r, r_max; 45 | 46 | a_sign = a >> (F_SIZE - 1); 47 | a_exp = (a >> MANT_SIZE) & EXP_MASK; 48 | a_mant = a & MANT_MASK; 49 | if (a_exp == EXP_MASK && a_mant != 0) 50 | a_sign = 0; /* NaN is like +infinity */ 51 | if (a_exp == 0) { 52 | a_exp = 1; 53 | } else { 54 | a_mant |= (F_UINT)1 << MANT_SIZE; 55 | } 56 | a_mant <<= RND_SIZE; 57 | a_exp = a_exp - (EXP_MASK / 2) - MANT_SIZE; 58 | 59 | if (is_unsigned) 60 | r_max = (ICVT_UINT)a_sign - 1; 61 | else 62 | r_max = ((ICVT_UINT)1 << (ICVT_SIZE - 1)) - (ICVT_UINT)(a_sign ^ 1); 63 | if (a_exp >= 0) { 64 | if (a_exp <= (ICVT_SIZE - 1 - MANT_SIZE)) { 65 | r = (ICVT_UINT)(a_mant >> RND_SIZE) << a_exp; 66 | if (r > r_max) 67 | goto overflow; 68 | } else { 69 | overflow: 70 | *pfflags |= FFLAG_INVALID_OP; 71 | return r_max; 72 | } 73 | } else { 74 | a_mant = rshift_rnd(a_mant, -a_exp); 75 | 76 | switch(rm) { 77 | case RM_RNE: 78 | case RM_RMM: 79 | addend = (1 << (RND_SIZE - 1)); 80 | break; 81 | case RM_RTZ: 82 | addend = 0; 83 | break; 84 | default: 85 | case RM_RDN: 86 | case RM_RUP: 87 | if (a_sign ^ (rm & 1)) 88 | addend = (1 << RND_SIZE) - 1; 89 | else 90 | addend = 0; 91 | break; 92 | } 93 | 94 | rnd_bits = a_mant & ((1 << RND_SIZE ) - 1); 95 | a_mant = (a_mant + addend) >> RND_SIZE; 96 | /* half way: select even result */ 97 | if (rm == RM_RNE && rnd_bits == (1 << (RND_SIZE - 1))) 98 | a_mant &= ~1; 99 | if (a_mant > r_max) 100 | goto overflow; 101 | r = a_mant; 102 | if (rnd_bits != 0) 103 | *pfflags |= FFLAG_INEXACT; 104 | } 105 | if (a_sign) 106 | r = -r; 107 | return r; 108 | } 109 | 110 | ICVT_INT glue(glue(glue(cvt_sf, F_SIZE), _i), ICVT_SIZE)(F_UINT a, RoundingModeEnum rm, 111 | uint32_t *pfflags) 112 | { 113 | return glue(glue(glue(internal_cvt_sf, F_SIZE), _i), ICVT_SIZE)(a, rm, 114 | pfflags, FALSE); 115 | } 116 | 117 | ICVT_UINT glue(glue(glue(cvt_sf, F_SIZE), _u), ICVT_SIZE)(F_UINT a, RoundingModeEnum rm, 118 | uint32_t *pfflags) 119 | { 120 | return glue(glue(glue(internal_cvt_sf, F_SIZE), _i), ICVT_SIZE) (a, rm, 121 | pfflags, TRUE); 122 | } 123 | 124 | /* conversions between float and integers */ 125 | static F_UINT glue(glue(glue(internal_cvt_i, ICVT_SIZE), _sf), F_SIZE)(ICVT_INT a, 126 | RoundingModeEnum rm, 127 | uint32_t *pfflags, 128 | BOOL is_unsigned) 129 | { 130 | uint32_t a_sign; 131 | int32_t a_exp; 132 | F_UINT a_mant; 133 | ICVT_UINT r, mask; 134 | int l; 135 | 136 | if (!is_unsigned && a < 0) { 137 | a_sign = 1; 138 | r = -(ICVT_UINT)a; 139 | } else { 140 | a_sign = 0; 141 | r = a; 142 | } 143 | a_exp = (EXP_MASK / 2) + F_SIZE - 2; 144 | /* need to reduce range before generic float normalization */ 145 | l = ICVT_SIZE - glue(clz, ICVT_SIZE)(r) - (F_SIZE - 1); 146 | if (l > 0) { 147 | mask = r & (((ICVT_UINT)1 << l) - 1); 148 | r = (r >> l) | ((r & mask) != 0); 149 | a_exp += l; 150 | } 151 | a_mant = r; 152 | return normalize_sf(a_sign, a_exp, a_mant, rm, pfflags); 153 | } 154 | 155 | F_UINT glue(glue(glue(cvt_i, ICVT_SIZE), _sf), F_SIZE)(ICVT_INT a, 156 | RoundingModeEnum rm, 157 | uint32_t *pfflags) 158 | { 159 | return glue(glue(glue(internal_cvt_i, ICVT_SIZE), _sf), F_SIZE)(a, rm, pfflags, FALSE); 160 | } 161 | 162 | F_UINT glue(glue(glue(cvt_u, ICVT_SIZE), _sf), F_SIZE)(ICVT_UINT a, 163 | RoundingModeEnum rm, 164 | uint32_t *pfflags) 165 | { 166 | return glue(glue(glue(internal_cvt_i, ICVT_SIZE), _sf), F_SIZE)(a, rm, pfflags, TRUE); 167 | } 168 | 169 | #undef ICVT_SIZE 170 | #undef ICVT_INT 171 | #undef ICVT_UINT 172 | -------------------------------------------------------------------------------- /tinyemu/splitimg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Disk image splitter 3 | * 4 | * Copyright (c) 2016 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | int main(int argc, char **argv) 32 | { 33 | int blocksize, ret, i; 34 | const char *infilename, *outpath; 35 | FILE *f, *fo; 36 | char buf1[1024]; 37 | uint8_t *buf; 38 | 39 | if ((optind + 1) >= argc) { 40 | printf("splitimg version " CONFIG_VERSION ", Copyright (c) 2011-2016 Fabrice Bellard\n" 41 | "usage: splitimg infile outpath [blocksize]\n" 42 | "Create a multi-file disk image for the RISCVEMU HTTP block device\n" 43 | "\n" 44 | "outpath must be a directory\n" 45 | "blocksize is the block size in KB\n"); 46 | exit(1); 47 | } 48 | 49 | infilename = argv[optind++]; 50 | outpath = argv[optind++]; 51 | blocksize = 256; 52 | if (optind < argc) 53 | blocksize = strtol(argv[optind++], NULL, 0); 54 | 55 | blocksize *= 1024; 56 | 57 | buf = malloc(blocksize); 58 | 59 | f = fopen(infilename, "rb"); 60 | if (!f) { 61 | perror(infilename); 62 | exit(1); 63 | } 64 | i = 0; 65 | for(;;) { 66 | ret = fread(buf, 1, blocksize, f); 67 | if (ret < 0) { 68 | perror("fread"); 69 | exit(1); 70 | } 71 | if (ret == 0) 72 | break; 73 | if (ret < blocksize) { 74 | printf("warning: last block is not full\n"); 75 | memset(buf + ret, 0, blocksize - ret); 76 | } 77 | snprintf(buf1, sizeof(buf1), "%s/blk%09u.bin", outpath, i); 78 | fo = fopen(buf1, "wb"); 79 | if (!fo) { 80 | perror(buf1); 81 | exit(1); 82 | } 83 | fwrite(buf, 1, blocksize, fo); 84 | fclose(fo); 85 | i++; 86 | } 87 | fclose(f); 88 | printf("%d blocks\n", i); 89 | 90 | snprintf(buf1, sizeof(buf1), "%s/blk.txt", outpath); 91 | fo = fopen(buf1, "wb"); 92 | if (!fo) { 93 | perror(buf1); 94 | exit(1); 95 | } 96 | fprintf(fo, "{\n"); 97 | fprintf(fo, " block_size: %d,\n", blocksize / 1024); 98 | fprintf(fo, " n_block: %d,\n", i); 99 | fprintf(fo, "}\n"); 100 | fclose(fo); 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /tinyemu/virtio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * VIRTIO driver 3 | * 4 | * Copyright (c) 2016 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef VIRTIO_H 25 | #define VIRTIO_H 26 | 27 | #include 28 | 29 | #include "iomem.h" 30 | #include "pci.h" 31 | 32 | #define VIRTIO_PAGE_SIZE 4096 33 | 34 | #if defined(EMSCRIPTEN) 35 | #define VIRTIO_ADDR_BITS 32 36 | #else 37 | #define VIRTIO_ADDR_BITS 64 38 | #endif 39 | 40 | #if VIRTIO_ADDR_BITS == 64 41 | typedef uint64_t virtio_phys_addr_t; 42 | #else 43 | typedef uint32_t virtio_phys_addr_t; 44 | #endif 45 | 46 | typedef struct { 47 | /* PCI only: */ 48 | PCIBus *pci_bus; 49 | /* MMIO only: */ 50 | PhysMemoryMap *mem_map; 51 | uint64_t addr; 52 | IRQSignal *irq; 53 | } VIRTIOBusDef; 54 | 55 | typedef struct VIRTIODevice VIRTIODevice; 56 | 57 | #define VIRTIO_DEBUG_IO (1 << 0) 58 | #define VIRTIO_DEBUG_9P (1 << 1) 59 | 60 | void virtio_set_debug(VIRTIODevice *s, int debug_flags); 61 | 62 | /* block device */ 63 | 64 | typedef void BlockDeviceCompletionFunc(void *opaque, int ret); 65 | 66 | typedef struct BlockDevice BlockDevice; 67 | 68 | struct BlockDevice { 69 | int64_t (*get_sector_count)(BlockDevice *bs); 70 | int (*read_async)(BlockDevice *bs, 71 | uint64_t sector_num, uint8_t *buf, int n, 72 | BlockDeviceCompletionFunc *cb, void *opaque); 73 | int (*write_async)(BlockDevice *bs, 74 | uint64_t sector_num, const uint8_t *buf, int n, 75 | BlockDeviceCompletionFunc *cb, void *opaque); 76 | void *opaque; 77 | }; 78 | 79 | VIRTIODevice *virtio_block_init(VIRTIOBusDef *bus, BlockDevice *bs); 80 | 81 | /* network device */ 82 | 83 | typedef struct EthernetDevice EthernetDevice; 84 | 85 | struct EthernetDevice { 86 | uint8_t mac_addr[6]; /* mac address of the interface */ 87 | void (*write_packet)(EthernetDevice *net, 88 | const uint8_t *buf, int len); 89 | void *opaque; 90 | #if !defined(EMSCRIPTEN) 91 | void (*select_fill)(EthernetDevice *net, int *pfd_max, 92 | fd_set *rfds, fd_set *wfds, fd_set *efds, 93 | int *pdelay); 94 | void (*select_poll)(EthernetDevice *net, 95 | fd_set *rfds, fd_set *wfds, fd_set *efds, 96 | int select_ret); 97 | #endif 98 | /* the following is set by the device */ 99 | void *device_opaque; 100 | BOOL (*device_can_write_packet)(EthernetDevice *net); 101 | void (*device_write_packet)(EthernetDevice *net, 102 | const uint8_t *buf, int len); 103 | void (*device_set_carrier)(EthernetDevice *net, BOOL carrier_state); 104 | }; 105 | 106 | VIRTIODevice *virtio_net_init(VIRTIOBusDef *bus, EthernetDevice *es); 107 | 108 | /* console device */ 109 | 110 | typedef struct { 111 | void *opaque; 112 | void (*write_data)(void *opaque, const uint8_t *buf, int len); 113 | int (*read_data)(void *opaque, uint8_t *buf, int len); 114 | } CharacterDevice; 115 | 116 | VIRTIODevice *virtio_console_init(VIRTIOBusDef *bus, CharacterDevice *cs); 117 | BOOL virtio_console_can_write_data(VIRTIODevice *s); 118 | int virtio_console_get_write_len(VIRTIODevice *s); 119 | int virtio_console_write_data(VIRTIODevice *s, const uint8_t *buf, int buf_len); 120 | void virtio_console_resize_event(VIRTIODevice *s, int width, int height); 121 | 122 | /* input device */ 123 | 124 | typedef enum { 125 | VIRTIO_INPUT_TYPE_KEYBOARD, 126 | VIRTIO_INPUT_TYPE_MOUSE, 127 | VIRTIO_INPUT_TYPE_TABLET, 128 | } VirtioInputTypeEnum; 129 | 130 | #define VIRTIO_INPUT_ABS_SCALE 32768 131 | 132 | int virtio_input_send_key_event(VIRTIODevice *s, BOOL is_down, 133 | uint16_t key_code); 134 | int virtio_input_send_mouse_event(VIRTIODevice *s, int dx, int dy, int dz, 135 | unsigned int buttons); 136 | 137 | VIRTIODevice *virtio_input_init(VIRTIOBusDef *bus, VirtioInputTypeEnum type); 138 | 139 | /* 9p filesystem device */ 140 | 141 | #include "fs.h" 142 | 143 | VIRTIODevice *virtio_9p_init(VIRTIOBusDef *bus, FSDevice *fs, 144 | const char *mount_tag); 145 | 146 | #endif /* VIRTIO_H */ 147 | -------------------------------------------------------------------------------- /tinyemu/vmmouse.c: -------------------------------------------------------------------------------- 1 | /* 2 | * VM mouse emulation 3 | * 4 | * Copyright (c) 2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "cutils.h" 31 | #include "iomem.h" 32 | #include "ps2.h" 33 | 34 | #define VMPORT_MAGIC 0x564D5868 35 | 36 | #define REG_EAX 0 37 | #define REG_EBX 1 38 | #define REG_ECX 2 39 | #define REG_EDX 3 40 | #define REG_ESI 4 41 | #define REG_EDI 5 42 | 43 | #define FIFO_SIZE (4 * 16) 44 | 45 | struct VMMouseState { 46 | PS2MouseState *ps2_mouse; 47 | int fifo_count, fifo_rindex, fifo_windex; 48 | BOOL enabled; 49 | BOOL absolute; 50 | uint32_t fifo_buf[FIFO_SIZE]; 51 | }; 52 | 53 | static void put_queue(VMMouseState *s, uint32_t val) 54 | { 55 | if (s->fifo_count >= FIFO_SIZE) 56 | return; 57 | s->fifo_buf[s->fifo_windex] = val; 58 | if (++s->fifo_windex == FIFO_SIZE) 59 | s->fifo_windex = 0; 60 | s->fifo_count++; 61 | } 62 | 63 | static void read_data(VMMouseState *s, uint32_t *regs, int size) 64 | { 65 | int i; 66 | if (size > 6 || size > s->fifo_count) { 67 | // printf("vmmouse: read error req=%d count=%d\n", size, s->fifo_count); 68 | s->enabled = FALSE; 69 | return; 70 | } 71 | for(i = 0; i < size; i++) { 72 | regs[i] = s->fifo_buf[s->fifo_rindex]; 73 | if (++s->fifo_rindex == FIFO_SIZE) 74 | s->fifo_rindex = 0; 75 | } 76 | s->fifo_count -= size; 77 | } 78 | 79 | void vmmouse_send_mouse_event(VMMouseState *s, int x, int y, int dz, 80 | int buttons) 81 | { 82 | int state; 83 | 84 | if (!s->enabled) { 85 | ps2_mouse_event(s->ps2_mouse, x, y, dz, buttons); 86 | return; 87 | } 88 | 89 | if ((s->fifo_count + 4) > FIFO_SIZE) 90 | return; 91 | 92 | state = 0; 93 | if (buttons & 1) 94 | state |= 0x20; 95 | if (buttons & 2) 96 | state |= 0x10; 97 | if (buttons & 4) 98 | state |= 0x08; 99 | if (s->absolute) { 100 | /* range = 0 ... 65535 */ 101 | x *= 2; 102 | y *= 2; 103 | } 104 | 105 | put_queue(s, state); 106 | put_queue(s, x); 107 | put_queue(s, y); 108 | put_queue(s, -dz); 109 | 110 | /* send PS/2 mouse event */ 111 | ps2_mouse_event(s->ps2_mouse, 1, 0, 0, 0); 112 | } 113 | 114 | void vmmouse_handler(VMMouseState *s, uint32_t *regs) 115 | { 116 | uint32_t cmd; 117 | 118 | cmd = regs[REG_ECX] & 0xff; 119 | switch(cmd) { 120 | case 10: /* get version */ 121 | regs[REG_EBX] = VMPORT_MAGIC; 122 | break; 123 | case 39: /* VMMOUSE_DATA */ 124 | read_data(s, regs, regs[REG_EBX]); 125 | break; 126 | case 40: /* VMMOUSE_STATUS */ 127 | regs[REG_EAX] = ((s->enabled ? 0 : 0xffff) << 16) | s->fifo_count; 128 | break; 129 | case 41: /* VMMOUSE_COMMAND */ 130 | switch(regs[REG_EBX]) { 131 | case 0x45414552: /* read id */ 132 | if (s->fifo_count < FIFO_SIZE) { 133 | put_queue(s, 0x3442554a); 134 | s->enabled = TRUE; 135 | } 136 | break; 137 | case 0x000000f5: /* disable */ 138 | s->enabled = FALSE; 139 | break; 140 | case 0x4c455252: /* set relative */ 141 | s->absolute = 0; 142 | break; 143 | case 0x53424152: /* set absolute */ 144 | s->absolute = 1; 145 | break; 146 | } 147 | break; 148 | } 149 | } 150 | 151 | BOOL vmmouse_is_absolute(VMMouseState *s) 152 | { 153 | return s->absolute; 154 | } 155 | 156 | VMMouseState *vmmouse_init(PS2MouseState *ps2_mouse) 157 | { 158 | VMMouseState *s; 159 | s = mallocz(sizeof(*s)); 160 | s->ps2_mouse = ps2_mouse; 161 | return s; 162 | } 163 | -------------------------------------------------------------------------------- /tinyemu/x86_cpu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * x86 CPU emulator stub 3 | * 4 | * Copyright (c) 2011-2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "cutils.h" 32 | #include "x86_cpu.h" 33 | 34 | X86CPUState *x86_cpu_init(PhysMemoryMap *mem_map) 35 | { 36 | fprintf(stderr, "x86 emulator is not supported\n"); 37 | exit(1); 38 | } 39 | 40 | void x86_cpu_end(X86CPUState *s) 41 | { 42 | } 43 | 44 | void x86_cpu_interp(X86CPUState *s, int max_cycles1) 45 | { 46 | } 47 | 48 | void x86_cpu_set_irq(X86CPUState *s, BOOL set) 49 | { 50 | } 51 | 52 | void x86_cpu_set_reg(X86CPUState *s, int reg, uint32_t val) 53 | { 54 | } 55 | 56 | uint32_t x86_cpu_get_reg(X86CPUState *s, int reg) 57 | { 58 | return 0; 59 | } 60 | 61 | void x86_cpu_set_seg(X86CPUState *s, int seg, const X86CPUSeg *sd) 62 | { 63 | } 64 | 65 | void x86_cpu_set_get_hard_intno(X86CPUState *s, 66 | int (*get_hard_intno)(void *opaque), 67 | void *opaque) 68 | { 69 | } 70 | 71 | void x86_cpu_set_get_tsc(X86CPUState *s, 72 | uint64_t (*get_tsc)(void *opaque), 73 | void *opaque) 74 | { 75 | } 76 | 77 | void x86_cpu_set_port_io(X86CPUState *s, 78 | DeviceReadFunc *port_read, DeviceWriteFunc *port_write, 79 | void *opaque) 80 | { 81 | } 82 | 83 | int64_t x86_cpu_get_cycles(X86CPUState *s) 84 | { 85 | return 0; 86 | } 87 | 88 | BOOL x86_cpu_get_power_down(X86CPUState *s) 89 | { 90 | return FALSE; 91 | } 92 | 93 | void x86_cpu_flush_tlb_write_range_ram(X86CPUState *s, 94 | uint8_t *ram_ptr, size_t ram_size) 95 | { 96 | } 97 | -------------------------------------------------------------------------------- /tinyemu/x86_cpu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * x86 CPU emulator 3 | * 4 | * Copyright (c) 2011-2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include "iomem.h" 25 | 26 | typedef struct X86CPUState X86CPUState; 27 | 28 | /* get_reg/set_reg additional constants */ 29 | #define X86_CPU_REG_EIP 8 30 | #define X86_CPU_REG_CR0 9 31 | #define X86_CPU_REG_CR2 10 32 | 33 | #define X86_CPU_SEG_ES 0 34 | #define X86_CPU_SEG_CS 1 35 | #define X86_CPU_SEG_SS 2 36 | #define X86_CPU_SEG_DS 3 37 | #define X86_CPU_SEG_FS 4 38 | #define X86_CPU_SEG_GS 5 39 | #define X86_CPU_SEG_LDT 6 40 | #define X86_CPU_SEG_TR 7 41 | #define X86_CPU_SEG_GDT 8 42 | #define X86_CPU_SEG_IDT 9 43 | 44 | typedef struct { 45 | uint16_t sel; 46 | uint16_t flags; 47 | uint32_t base; 48 | uint32_t limit; 49 | } X86CPUSeg; 50 | 51 | X86CPUState *x86_cpu_init(PhysMemoryMap *mem_map); 52 | void x86_cpu_end(X86CPUState *s); 53 | void x86_cpu_interp(X86CPUState *s, int max_cycles1); 54 | void x86_cpu_set_irq(X86CPUState *s, BOOL set); 55 | void x86_cpu_set_reg(X86CPUState *s, int reg, uint32_t val); 56 | uint32_t x86_cpu_get_reg(X86CPUState *s, int reg); 57 | void x86_cpu_set_seg(X86CPUState *s, int seg, const X86CPUSeg *sd); 58 | void x86_cpu_set_get_hard_intno(X86CPUState *s, 59 | int (*get_hard_intno)(void *opaque), 60 | void *opaque); 61 | void x86_cpu_set_get_tsc(X86CPUState *s, 62 | uint64_t (*get_tsc)(void *opaque), 63 | void *opaque); 64 | void x86_cpu_set_port_io(X86CPUState *s, 65 | DeviceReadFunc *port_read, DeviceWriteFunc *port_write, 66 | void *opaque); 67 | int64_t x86_cpu_get_cycles(X86CPUState *s); 68 | BOOL x86_cpu_get_power_down(X86CPUState *s); 69 | void x86_cpu_flush_tlb_write_range_ram(X86CPUState *s, 70 | uint8_t *ram_ptr, size_t ram_size); 71 | -------------------------------------------------------------------------------- /vm_32.cfg: -------------------------------------------------------------------------------- 1 | { 2 | version: 1, 3 | machine: "riscv32", 4 | memory_size: 128, 5 | bios: "file:///bbl32.bin", 6 | kernel: "file:///kernel-riscv32.bin", 7 | cmdline: "loglevel=6 swiotlb=1 console=tty0 root=root rootfstype=9p rootflags=trans=virtio rw", 8 | fs0: { file: "file:///root" }, 9 | display0: { 10 | device: "simplefb", 11 | width: 320, 12 | height: 200, 13 | }, 14 | input_device: "virtio", 15 | } 16 | -------------------------------------------------------------------------------- /vm_64.cfg: -------------------------------------------------------------------------------- 1 | { 2 | version: 1, 3 | machine: "riscv64", 4 | memory_size: 128, 5 | bios: "file:///bbl64.bin", 6 | kernel: "file:///kernel-riscv64.bin", 7 | cmdline: "loglevel=6 swiotlb=1 console=tty0 root=root rootfstype=9p rootflags=trans=virtio rw", 8 | fs0: { file: "file:///root" }, 9 | display0: { 10 | device: "simplefb", 11 | width: 320, 12 | height: 200, 13 | }, 14 | input_device: "virtio", 15 | } 16 | -------------------------------------------------------------------------------- /web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ading2210/linuxpdf/9d6ff291a3c1f157b22ae6d196c9a3841a3de289/web/favicon.ico -------------------------------------------------------------------------------- /web/favicon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ading2210/linuxpdf/9d6ff291a3c1f157b22ae6d196c9a3841a3de289/web/favicon_128.png -------------------------------------------------------------------------------- /web/index.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: Arial, Helvetica, sans-serif; 3 | box-sizing: border-box; 4 | } 5 | html, body { 6 | width: 100%; 7 | height: 100%; 8 | } 9 | body { 10 | padding: 8px; 11 | margin: 0px; 12 | background-color: #222222; 13 | display: flex; 14 | flex-direction: column; 15 | align-items: center; 16 | } 17 | 18 | .spacer { 19 | flex-grow: 1; 20 | } 21 | 22 | #article { 23 | background-color: whitesmoke; 24 | padding: 12px; 25 | border-radius: 4px; 26 | 27 | width: min(100%, 550px); 28 | height: 300px; 29 | } 30 | #header_box { 31 | display: flex; 32 | align-items: center; 33 | gap: 8px; 34 | } 35 | #header_box > h1 { 36 | margin: 0px; 37 | } 38 | #controls_box { 39 | display: flex; 40 | align-items: center; 41 | } 42 | #controls_box > * { 43 | font-size: 14px; 44 | } 45 | #play_button { 46 | text-decoration: none; 47 | color: black; 48 | background-color: lightgray; 49 | padding: 8px; 50 | border-radius: 3px; 51 | } -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | LinuxPDF 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 | 21 |

LinuxPDF

22 |
23 | 24 |

This is Linux running inside a PDF file via a RISC-V emulator, which is based on TinyEMU.

25 |

Source code: https://github.com/ading2210/linuxpdf

26 | 27 |

28 | 29 |
30 | Start Emulator 31 |
32 |
33 |

Note: the PDF only works inside Chromium-based browsers.

34 |
35 |
36 | 37 | --------------------------------------------------------------------------------