diff options
| author | Loic Guegan <manzerbredes@mailbox.org> | 2021-04-19 19:06:28 +0200 |
|---|---|---|
| committer | Loic Guegan <manzerbredes@mailbox.org> | 2021-04-19 19:06:28 +0200 |
| commit | ca1e725b0dc9b10997897dd2ac6d44028601d9bb (patch) | |
| tree | 0eb7bd087a2382d1d1a660ceda1eae01d1b8b3ca | |
| parent | f5146ca9c987ed5e6ea69a0c67b7ed03444be30c (diff) | |
Init sources
| -rw-r--r-- | README.md | 5 | ||||
| -rw-r--r-- | src/Makefile | 29 | ||||
| -rw-r--r-- | src/boot/boot.S | 128 | ||||
| -rw-r--r-- | src/boucane.c | 9 | ||||
| -rw-r--r-- | src/core/types.h | 9 | ||||
| -rw-r--r-- | src/drivers/framebuffer.c | 58 | ||||
| -rw-r--r-- | src/drivers/framebuffer.h | 35 | ||||
| -rw-r--r-- | src/libc/math.c | 32 | ||||
| -rw-r--r-- | src/libc/math.h | 9 | ||||
| -rw-r--r-- | src/libc/stdio.c | 25 | ||||
| -rw-r--r-- | src/libc/stdio.h | 21 | ||||
| -rw-r--r-- | src/libc/string.c | 29 | ||||
| -rw-r--r-- | src/libc/string.h | 9 | ||||
| -rw-r--r-- | src/linker.ld | 29 | ||||
| -rw-r--r-- | tools/bochsrc | 2 | ||||
| -rwxr-xr-x | tools/gen_grub_cdrom.sh | 31 | ||||
| -rw-r--r-- | tools/ram.svg | 218 |
17 files changed, 678 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..a420cf9 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Boucane +**What is Boucane** +Boucane is a *64 bits* multi-tasking kernel for *x86* architecture written in pure *C* and *GNU Assembly*. It was developed for popularization purpose and propagating Operating System developement knowledge. + + diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..7c2ee5f --- /dev/null +++ b/src/Makefile @@ -0,0 +1,29 @@ +EXEC := boucane +CC := gcc -c -fno-pie -fno-builtin -fno-stack-protector -I ./ +LD_SCRIPT := linker.ld + +# Note that BOOT_OBJ do not match boot.S +# Indeed boot.o generated by boot.S should appear +# first in the kernel binary (thus it must be linked first, cf the $(EXEC) rule) +BOOT_OBJ := $(addsuffix .o,$(basename $(shell find ./boot -name "*.[c|S]" ! -name "boot.S"))) +DRIVERS_OBJ := $(addsuffix .o,$(basename $(shell find ./drivers -name "*.[c|S]"))) +LIBC_OBJ := $(addsuffix .o,$(basename $(shell find ./libc -name "*.[c|S]"))) + +all: $(EXEC) + +$(EXEC): boot/boot.o $(BOOT_OBJ) $(DRIVERS_OBJ) $(LIBC_OBJ) boucane.o + ld -n -T $(LD_SCRIPT) -nostdlib -o $@ $^ + +%.o: %.S + as -o $@ $^ + +%.o: %.c + $(CC) -o $@ $< + +clean: + rm -f $(EXEC) + find ./ -name "*.o" -delete + +.PHONY: clean cdrom + + diff --git a/src/boot/boot.S b/src/boot/boot.S new file mode 100644 index 0000000..676ace7 --- /dev/null +++ b/src/boot/boot.S @@ -0,0 +1,128 @@ +.globl _start +.globl MB_INFO +.extern boucane +.extern _bss_start +.extern _bss_end +.extern boucane + +.set STACK_LOCATION, 0x1FFFFF + +.section .multiboot + +.set MB_MAGIC, 0xE85250D6 +.set MB_ARCH, 0x00000000 +.set MB_HEADER_LENGTH, (mb_header_end-mb_header_start) +.set MB_CHECKSUM, -(MB_MAGIC+MB_ARCH+MB_HEADER_LENGTH) + +mb_header_start: +.align 8 +.int MB_MAGIC +.int MB_ARCH +.int MB_HEADER_LENGTH +.int MB_CHECKSUM +# ----------- Address tag +.align 8 +.short 2 +.short 0 # Not optional +.int 24 # Size +.int mb_header_start # header_addr +.int mb_header_start # load_addr +.int 0x0 # load_end_addr +.int 0x0 # bss_end_addr +# ----------- Addr tag +.align 8 +.short 0x3 +.short 0 +.int 12 +.int _start +# ----------- End tag +.align 8 +.int 0x0 +.int 0x8 +mb_header_end: + +.section .text +.code32 # Require since grub do not enable long mode + +MB_INFO: + .int 0xABCDEF # Will contains the Multiboot2 information data structure address + +_start: +mov %ebx,(MB_INFO) + +# ----- Setup PAE Paging (identity on the first 10MB) +mov $8192, %ecx # 8*4096/4 (8 tables of 4096 byte each divide by 4 because of movl) +mov $0, %eax +zeroing_paging: +movl $0, (%eax) +add $4, %eax +loop zeroing_paging +# Setup PML4 Table (Address 0x0) +mov $0x0, %edi +mov %edi, %cr3 # Setup PML4 location +movl $0x1003, (%edi) # Setup PDPT location +# Setup PDPT +mov $0x1000, %edi +movl $0x2003, (%edi) # Setup PDPT location +# Setup PDT (5 PT = 10MB) +mov $0x2000, %edi +mov $0x3003, %eax +mov $5, %ecx +pdt_fill: +movl %eax, (%edi) # Setup PDPT location +add $8, %edi # Goto next entry +add $0x1000, %eax # Next PT +loop pdt_fill +# Setup the 5 PT +mov $0x3000, %edi +mov $0x3, %ebx # First map to 0 +mov $2560, %ecx # 512*5 +pt_fill: +mov %ebx, (%edi) +add $8, %edi # Next entry +add $0x1000, %ebx # Next Page +loop pt_fill + +# ----- Switch to compatibility mode +# Set CR4.PAE +mov %cr4, %eax +bts $5, %eax +mov %eax, %cr4 +# Set EFER.LME +mov $0xC0000080, %ecx +rdmsr +bts $8, %eax +wrmsr +# Set CR0.PG +mov %cr0, %eax +bts $31, %eax +mov %eax, %cr0 + +# Now we are in Compatibility mode +# Now we need to set CS.L=1 (setting up a 64 bit GDT) +lgdt (gdtr) +jmp $0x08, $new_cs +new_cs: + +# Run boucane +jmp boucane + +# GDT +gdt64: + gdt64_null: + .long 0 + .long 0 + gdt64_cs: + .long 0 + .byte 0 + .byte 0b10011100 + .byte 0b00100000 + .byte 0 + gdt64_ds: + .long 0 + .byte 0 + .byte 0b10000000 + .word 0 +gdtr: + .word . - gdt64 - 1 + .quad gdt64
\ No newline at end of file diff --git a/src/boucane.c b/src/boucane.c new file mode 100644 index 0000000..1b80891 --- /dev/null +++ b/src/boucane.c @@ -0,0 +1,9 @@ +#include "libc/stdio.h" + + + +void boucane(){ + clear(); + print("Boucane is booting..."); + while(1); +}
\ No newline at end of file diff --git a/src/core/types.h b/src/core/types.h new file mode 100644 index 0000000..071d8d6 --- /dev/null +++ b/src/core/types.h @@ -0,0 +1,9 @@ +#ifndef TYPES_H +#define TYPES_H + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#endif diff --git a/src/drivers/framebuffer.c b/src/drivers/framebuffer.c new file mode 100644 index 0000000..110dc73 --- /dev/null +++ b/src/drivers/framebuffer.c @@ -0,0 +1,58 @@ +#include "framebuffer.h" + +#define MAX_COL 80 +#define MAX_LINE 25 + +VIDEO_STATE VS={ + (u8 *)0xB8000, + 0, + 0, + BLACK, + GRAY, +}; + +void putchar(char c){ + // Handle newline here + if(c=='\n'){ + VS.col=0; + VS.line+=1; + if(VS.line>=MAX_LINE){ + VS.line=MAX_LINE-1; + scrollup(); + } + return; + } + + // Print char + VS.mem[VS.col*2+MAX_COL*VS.line*2]=c; + VS.mem[VS.col*2+MAX_COL*VS.line*2+1]=VS.fg|VS.bg<<4; + + // Refresh location + VS.col+=1; + if(VS.col>= MAX_COL){ + VS.col=0; + VS.line+=1; + if(VS.line>=MAX_LINE){ + VS.line=MAX_LINE-1; + scrollup(); + } + } +} + +void clear(){ + for(char i=0;i<MAX_LINE;i++){ + scrollup(); + } +} + +void scrollup(){ + // Move VS.line up + for(char i=1;i<=MAX_LINE;i++){ + for(char j=0;j<=MAX_COL;j++) + VS.mem[j*2+MAX_COL*(i-1)*2]=VS.mem[j*2+MAX_COL*i*2]; + } + // Clear last VS.line + for(char i=0;i<=MAX_COL;i++){ + VS.mem[i*2+MAX_COL*(MAX_LINE-1)*2]='\0'; + } +} diff --git a/src/drivers/framebuffer.h b/src/drivers/framebuffer.h new file mode 100644 index 0000000..d265015 --- /dev/null +++ b/src/drivers/framebuffer.h @@ -0,0 +1,35 @@ +#ifndef FRAMEBUFFER_H +#define FRAMEBUFFER_H + +#include "core/types.h" + +typedef enum VIDEO_COLORS { + BLACK=0, BLUE=1, GREEN=2,CYAN=3, RED=4,PURPLE=5,BROWN=6,GRAY=7, + DARK_GRAY=8,LIGHT_BLUE=9,LIGHT_GREEN=10,LIGHT_CYAN=11,LIGHT_RED=12,LIGHT_PURPLE=13,YELLOW=14,WHITE=15 + +} VIDEO_COLORS; + +typedef struct VIDEO_STATE { + u8 *mem; + u8 col; + u8 line; + u8 bg; + u8 fg; +} VIDEO_STATE; + +/** + * Print char + */ +void putchar(char); + +/** + * Scroll the framebuffer from one line + */ +void scrollup(); + +/** + * Clear all char from the framebuffer + */ +void clear(); + +#endif diff --git a/src/libc/math.c b/src/libc/math.c new file mode 100644 index 0000000..80b1d3a --- /dev/null +++ b/src/libc/math.c @@ -0,0 +1,32 @@ +#include "math.h" + +int pow(int x,int n){ + if(n<0) + return -1; + else if(n==0) + return 1; + else if(n==1) + return x; + int ret=x; + for(int i=0;i<(n-1);i++) + ret*=x; + return ret; +} + +int max(int x,int y){ + if(x>y) + return x; + return y; +} + +int min(int x,int y){ + if(x<y) + return x; + return y; +} + +int abs(int x){ + if(x<0) + return -x; + return x; +}
\ No newline at end of file diff --git a/src/libc/math.h b/src/libc/math.h new file mode 100644 index 0000000..4cc37a9 --- /dev/null +++ b/src/libc/math.h @@ -0,0 +1,9 @@ +#ifndef MATH_H +#define MATH_H + +int pow(int x,int n); +int max(int x,int y); +int min(int x,int y); +int abs(int x); + +#endif
\ No newline at end of file diff --git a/src/libc/stdio.c b/src/libc/stdio.c new file mode 100644 index 0000000..6e0063b --- /dev/null +++ b/src/libc/stdio.c @@ -0,0 +1,25 @@ +#include "stdio.h" +#include "string.h" + +extern VIDEO_STATE VS; + +void print(char *str){ + int i=0; + while(str[i]!='\0'){ + putchar(str[i]); + i++; + } +} + +void printc(char* str,VIDEO_COLORS c){ + VIDEO_COLORS backup=VS.fg; + VS.fg=c; + print(str); + VS.fg=backup; +} + +void printi(int i){ + char str[12]; + itoa(i,str); + print(str); +}
\ No newline at end of file diff --git a/src/libc/stdio.h b/src/libc/stdio.h new file mode 100644 index 0000000..d4bd6b6 --- /dev/null +++ b/src/libc/stdio.h @@ -0,0 +1,21 @@ +#ifndef STDIO_H +#define STDIO_H + +#include "drivers/framebuffer.h" + +/** + * Print a char* in the framebuffer + */ +void print(char*); + +/** + * Print a char in the framebuffer + */ +void printc(char*,VIDEO_COLORS c); + +/** + * Print an integer using itoa() + */ +void printi(int i); + +#endif
\ No newline at end of file diff --git a/src/libc/string.c b/src/libc/string.c new file mode 100644 index 0000000..93a9e63 --- /dev/null +++ b/src/libc/string.c @@ -0,0 +1,29 @@ +#include "string.h" +#include "math.h" + +void itoa(int i, char *a){ + // Check if lower than 0 + char neg=0; + if(i<0){ + neg=1; + i=-i; + a[0]='-'; + } + + // Count number of digits + int len=1; + while(i/pow(10,len)>=1) + { + len++; + } + + // Build string + int max_pow=len-1; + for(int j=0;j<=max_pow;j++){ + int cur_pow=pow(10,max_pow-j); + char digit=i/cur_pow; + a[j+neg]='0'+digit; + i=i-digit*cur_pow; // Remove first digits (most significant) + } + a[len+neg]='\0'; +}
\ No newline at end of file diff --git a/src/libc/string.h b/src/libc/string.h new file mode 100644 index 0000000..c3d3614 --- /dev/null +++ b/src/libc/string.h @@ -0,0 +1,9 @@ +#ifndef STRING_H +#define STRING_H + +/** + * Convert int to char + */ +void itoa(int i, char *a); + +#endif
\ No newline at end of file diff --git a/src/linker.ld b/src/linker.ld new file mode 100644 index 0000000..ed8fc5d --- /dev/null +++ b/src/linker.ld @@ -0,0 +1,29 @@ +ENTRY(_start) +OUTPUT_FORMAT(elf64-x86-64) + +SECTIONS { + + . = 1M; + + .text : ALIGN(4) + { + *(.multiboot) + *(.text) + } + .rodata : ALIGN(4) + { + *(.rodata) + } + .data : ALIGN(4) + { + *(.data) + } + .bss : ALIGN(4) + { + _bss_start = .; + *(.bss); + _bss_end = .; + *(COMMON); + } + +}
\ No newline at end of file diff --git a/tools/bochsrc b/tools/bochsrc new file mode 100644 index 0000000..fd9fe69 --- /dev/null +++ b/tools/bochsrc @@ -0,0 +1,2 @@ +romimage: file=$BXSHARE/BIOS-bochs-latest, options=fastboot +vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest diff --git a/tools/gen_grub_cdrom.sh b/tools/gen_grub_cdrom.sh new file mode 100755 index 0000000..a1f1a1c --- /dev/null +++ b/tools/gen_grub_cdrom.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +# Ensure to abort on error +set -e + +wai=$(dirname $(readlink -f "$0")) # Current script directory +outdir="${wai}/../" +cdrom="${outdir}/cdrom.img" +isodir="$(mktemp -d)" # Mount point (where the floppy will be mounted temporally +kernel="$outdir/src/boucane" + +[ ! -e "$kernel" ] && { echo "Boucane not found!"; exit 1; } + +check_for () { + command -v "$1" &>/dev/null || { echo "Command $1 not found!"; exit 1; } +} + +check_for grub-mkconfig + +mkdir -p $isodir/boot/grub +cat <<EOT >> $isodir/boot/grub/grub.cfg +set timeout=0 +menuentry "kernel" { + multiboot2 /boot/boucane + boot +} +EOT +cp $kernel "$isodir/boot/" +grub-mkrescue -o "$cdrom" $isodir + +rm -rf "$isodir" diff --git a/tools/ram.svg b/tools/ram.svg new file mode 100644 index 0000000..a66a4b5 --- /dev/null +++ b/tools/ram.svg @@ -0,0 +1,218 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="210mm" + height="297mm" + viewBox="0 0 210 297" + version="1.1" + id="svg8" + inkscape:version="1.0.2 (e86c870879, 2021-01-15, custom)" + sodipodi:docname="ram.svg"> + <defs + id="defs2" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="2.3090931" + inkscape:cx="401.30631" + inkscape:cy="290.44939" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + showgrid="false" + inkscape:window-width="1892" + inkscape:window-height="1014" + inkscape:window-x="10" + inkscape:window-y="48" + inkscape:window-maximized="0" /> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <rect + style="fill:#ffffff;fill-rule:evenodd;stroke-width:2;stroke:#333333;stroke-miterlimit:4;stroke-dasharray:none" + id="rect10" + width="67.534943" + height="112.65762" + x="43.210255" + y="34.834328" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.46667px;line-height:1.25;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583" + x="115.61518" + y="150.39668" + id="text855"><tspan + sodipodi:role="line" + id="tspan853" + x="115.61518" + y="150.39668" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.46667px;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';stroke-width:0.264583">0x0</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.46666667px;line-height:1.25;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;" + x="115.61518" + y="140.70641" + id="text843"><tspan + sodipodi:role="line" + id="tspan841" + x="115.61518" + y="140.70641" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';stroke-width:0.264583;font-size:8.46666667px;">0x640</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.46666667px;line-height:1.25;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;" + x="115.61518" + y="130.68584" + id="text847"><tspan + sodipodi:role="line" + id="tspan845" + x="115.61518" + y="130.68584" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';stroke-width:0.264583;font-size:8.46666667px;">0x800</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.46666667px;line-height:1.25;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;" + x="115.61518" + y="120.51859" + id="text851"><tspan + sodipodi:role="line" + id="tspan849" + x="115.61518" + y="120.51859" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';stroke-width:0.264583;font-size:8.46666667px;">0x850</tspan></text> + <rect + style="fill:none;stroke:#333333;stroke-width:2" + id="rect853" + width="67.534943" + height="11.90126" + x="43.210255" + y="135.59068" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:10.5833px;line-height:1.25;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583" + x="67.960762" + y="145.20314" + id="text859"><tspan + sodipodi:role="line" + id="tspan857" + x="67.960762" + y="145.20314" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';stroke-width:0.264583">IDT</tspan></text> + <rect + style="fill:none;stroke:#333333;stroke-width:2" + id="rect861" + width="67.534943" + height="11.90126" + x="43.210255" + y="117.08315" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:10.5833px;line-height:1.25;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583" + x="66.076935" + y="126.71677" + id="text865"><tspan + sodipodi:role="line" + id="tspan863" + x="66.076935" + y="126.71677" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';stroke-width:0.264583">GDT</tspan></text> + <rect + style="fill:none;stroke:#333333;stroke-width:2" + id="rect867" + width="67.534943" + height="11.90126" + x="43.210255" + y="80.192589" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:10.5833px;line-height:1.25;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583" + x="60.023312" + y="90.175453" + id="text871"><tspan + sodipodi:role="line" + id="tspan869" + x="60.023312" + y="90.175453" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';stroke-width:0.264583">Kernel</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.46667px;line-height:1.25;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583" + x="115.61518" + y="94.123299" + id="text875"><tspan + sodipodi:role="line" + id="tspan873" + x="115.61518" + y="94.123299" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.46667px;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';stroke-width:0.264583">0x100000</tspan></text> + <rect + style="fill:none;stroke:#333333;stroke-width:2" + id="rect877" + width="67.534943" + height="11.90126" + x="43.210255" + y="100.01691" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.46667px;line-height:1.25;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583" + x="115.61518" + y="103.22851" + id="text881"><tspan + sodipodi:role="line" + id="tspan879" + x="115.61518" + y="103.22851" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.46667px;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';stroke-width:0.264583">0x50000</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:10.5833px;line-height:1.25;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583" + x="62.875507" + y="109.58773" + id="text885"><tspan + sodipodi:role="line" + id="tspan883" + x="62.875507" + y="109.58773" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';stroke-width:0.264583">Stack</tspan></text> + <rect + style="fill:none;stroke:#333333;stroke-width:2" + id="rect887" + width="67.142853" + height="40.376717" + x="43.210255" + y="34.834328" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.46667px;line-height:1.25;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583" + x="115.61518" + y="78.103249" + id="text891"><tspan + sodipodi:role="line" + id="tspan889" + x="115.61518" + y="78.103249" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.46667px;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu Bold';stroke-width:0.264583">0x200000</tspan></text> + </g> +</svg> |
