initial commit

This commit is contained in:
Anselm Levskaya 2011-12-16 20:16:10 -08:00
commit dc64ec3594
4 changed files with 11269 additions and 0 deletions

153
jslinux.html Normal file

File diff suppressed because one or more lines are too long

10497
jslinux_files/cpux86-ta.js Normal file

File diff suppressed because it is too large Load Diff

97
jslinux_files/jslinux.js Normal file
View File

@ -0,0 +1,97 @@
/*
Linux launcher
Copyright (c) 2011 Fabrice Bellard
Redistribution or commercial use is prohibited without the author's
permission.
*/
"use strict";
var term, pc, boot_start_time;
function term_start()
{
term = new Term(80, 30, term_handler);
term.open();
}
/* send chars to the serial port */
function term_handler(str)
{
pc.serial.send_chars(str);
}
function clipboard_set(val)
{
var el;
el = document.getElementById("text_clipboard");
el.value = val;
}
function clipboard_get()
{
var el;
el = document.getElementById("text_clipboard");
return el.value;
}
function clear_clipboard()
{
var el;
el = document.getElementById("text_clipboard");
el.value = "";
}
/* just used to display the boot time in the VM */
function get_boot_time()
{
return (+new Date()) - boot_start_time;
}
function start()
{
var start_addr, initrd_size, params, cmdline_addr;
params = new Object();
/* serial output chars */
params.serial_write = term.write.bind(term);
/* memory size (in bytes) */
params.mem_size = 16 * 1024 * 1024;
/* clipboard I/O */
params.clipboard_get = clipboard_get;
params.clipboard_set = clipboard_set;
params.get_boot_time = get_boot_time;
pc = new PCEmulator(params);
pc.load_binary("vmlinux-2.6.20.bin", 0x00100000);
initrd_size = pc.load_binary("root.bin", 0x00400000);
start_addr = 0x10000;
pc.load_binary("linuxstart.bin", start_addr);
/* set the Linux kernel command line */
/* Note: we don't use initramfs because it is not possible to
disable gzip decompression in this case, which would be too
slow. */
cmdline_addr = 0xf800;
pc.cpu.write_string(cmdline_addr, "console=ttyS0 root=/dev/ram0 rw init=/sbin/init notsc=1");
pc.cpu.eip = start_addr;
pc.cpu.regs[0] = params.mem_size; /* eax */
pc.cpu.regs[3] = initrd_size; /* ebx */
pc.cpu.regs[1] = cmdline_addr; /* ecx */
boot_start_time = (+new Date());
pc.start();
}
term_start();

522
jslinux_files/term.js Normal file
View File

@ -0,0 +1,522 @@
/*
Javascript Terminal
Copyright (c) 2011 Fabrice Bellard
Redistribution or commercial use is prohibited without the author's
permission.
*/
"use strict";
if (!Function.prototype.bind) {
Function.prototype.bind = function(aa) {
var ba = [].slice, ca = ba.call(arguments, 1), self = this, da = function() {
}, ea = function() {
return self.apply(this instanceof da ? this : (aa || {}), ca.concat(ba.call(arguments)));
};
da.prototype = self.prototype;
ea.prototype = new da();
return ea;
};
}
function Term(fa, ga, ha) {
this.w = fa;
this.h = ga;
this.cur_h = ga;
this.tot_h = 1000;
this.y_base = 0;
this.y_disp = 0;
this.x = 0;
this.y = 0;
this.cursorstate = 0;
this.handler = ha;
this.convert_lf_to_crlf = false;
this.state = 0;
this.output_queue = "";
this.bg_colors = ["#000000", "#ff0000", "#00ff00", "#ffff00", "#0000ff", "#ff00ff", "#00ffff", "#ffffff"];
this.fg_colors = ["#000000", "#ff0000", "#00ff00", "#ffff00", "#0000ff", "#ff00ff", "#00ffff", "#ffffff"];
this.def_attr = (7 << 3) | 0;
this.cur_attr = this.def_attr;
this.is_mac = (navigator.userAgent.indexOf("Mac") >= 0) ? true : false;
this.key_rep_state = 0;
this.key_rep_str = "";
}
Term.prototype.open = function() {
var y, ia, i, ja, c;
this.lines = new Array();
c = 32 | (this.def_attr << 16);
for (y = 0; y < this.cur_h; y++) {
ia = new Array();
for (i = 0; i < this.w; i++)
ia[i] = c;
this.lines[y] = ia;
}
document.writeln('<table border="0" cellspacing="0" cellpadding="0">');
for (y = 0; y < this.h; y++) {
document.writeln('<tr><td class="term" id="tline' + y + '"></td></tr>');
}
document.writeln('</table>');
this.refresh(0, this.h - 1);
document.addEventListener("keydown", this.keyDownHandler.bind(this), true);
document.addEventListener("keypress", this.keyPressHandler.bind(this), true);
ja = this;
setInterval(function() {
ja.cursor_timer_cb();
}, 1000);
};
Term.prototype.refresh = function(ka, la) {
var ma, y, ia, na, c, w, i, oa, pa, qa, ra, sa, ta;
for (y = ka; y <= la; y++) {
ta = y + this.y_disp;
if (ta >= this.cur_h)
ta -= this.cur_h;
ia = this.lines[ta];
na = "";
w = this.w;
if (y == this.y && this.cursor_state && this.y_disp == this.y_base) {
oa = this.x;
} else {
oa = -1;
}
qa = this.def_attr;
for (i = 0; i < w; i++) {
c = ia[i];
pa = c >> 16;
c &= 0xffff;
if (i == oa) {
pa = -1;
}
if (pa != qa) {
if (qa != this.def_attr)
na += '</span>';
if (pa != this.def_attr) {
if (pa == -1) {
na += '<span class="termReverse">';
} else {
na += '<span style="';
ra = (pa >> 3) & 7;
sa = pa & 7;
if (ra != 7) {
na += 'color:' + this.fg_colors[ra] + ';';
}
if (sa != 0) {
na += 'background-color:' + this.bg_colors[sa] + ';';
}
na += '">';
}
}
}
switch (c) {
case 32:
na += "&nbsp;";
break;
case 38:
na += "&amp;";
break;
case 60:
na += "&lt;";
break;
case 62:
na += "&gt;";
break;
default:
if (c < 32) {
na += "&nbsp;";
} else {
na += String.fromCharCode(c);
}
break;
}
qa = pa;
}
if (qa != this.def_attr) {
na += '</span>';
}
ma = document.getElementById("tline" + y);
ma.innerHTML = na;
}
};
Term.prototype.cursor_timer_cb = function() {
this.cursor_state ^= 1;
this.refresh(this.y, this.y);
};
Term.prototype.show_cursor = function() {
if (!this.cursor_state) {
this.cursor_state = 1;
this.refresh(this.y, this.y);
}
};
Term.prototype.scroll = function() {
var y, ia, x, c, ta;
if (this.cur_h < this.tot_h) {
this.cur_h++;
}
if (++this.y_base == this.cur_h)
this.y_base = 0;
this.y_disp = this.y_base;
c = 32 | (this.def_attr << 16);
ia = new Array();
for (x = 0; x < this.w; x++)
ia[x] = c;
ta = this.y_base + this.h - 1;
if (ta >= this.cur_h)
ta -= this.cur_h;
this.lines[ta] = ia;
};
Term.prototype.scroll_disp = function(n) {
var i, ta;
if (n >= 0) {
for (i = 0; i < n; i++) {
if (this.y_disp == this.y_base)
break;
if (++this.y_disp == this.cur_h)
this.y_disp = 0;
}
} else {
n = -n;
ta = this.y_base + this.h;
if (ta >= this.cur_h)
ta -= this.cur_h;
for (i = 0; i < n; i++) {
if (this.y_disp == ta)
break;
if (--this.y_disp < 0)
this.y_disp = this.cur_h - 1;
}
}
this.refresh(0, this.h - 1);
};
Term.prototype.write = function(ua) {
function va(y) {
ka = Math.min(ka, y);
la = Math.max(la, y);
}
function wa(s, x, y) {
var l, i, c, ta;
ta = s.y_base + y;
if (ta >= s.cur_h)
ta -= s.cur_h;
l = s.lines[ta];
c = 32 | (s.def_attr << 16);
for (i = x; i < s.w; i++)
l[i] = c;
va(y);
}
function xa(s, ya) {
var j, n;
if (ya.length == 0) {
s.cur_attr = s.def_attr;
} else {
for (j = 0; j < ya.length; j++) {
n = ya[j];
if (n >= 30 && n <= 37) {
s.cur_attr = (s.cur_attr & ~(7 << 3)) | ((n - 30) << 3);
} else if (n >= 40 && n <= 47) {
s.cur_attr = (s.cur_attr & ~7) | (n - 40);
} else if (n == 0) {
s.cur_attr = s.def_attr;
}
}
}
}
var za = 0;
var Aa = 1;
var Ba = 2;
var i, c, ka, la, l, n, j, ta;
ka = this.h;
la = -1;
va(this.y);
if (this.y_base != this.y_disp) {
this.y_disp = this.y_base;
ka = 0;
la = this.h - 1;
}
for (i = 0; i < ua.length; i++) {
c = ua.charCodeAt(i);
switch (this.state) {
case za:
switch (c) {
case 10:
if (this.convert_lf_to_crlf) {
this.x = 0;
}
this.y++;
if (this.y >= this.h) {
this.y--;
this.scroll();
ka = 0;
la = this.h - 1;
}
break;
case 13:
this.x = 0;
break;
case 8:
if (this.x > 0) {
this.x--;
}
break;
case 9:
n = (this.x + 8) & ~7;
if (n <= this.w) {
this.x = n;
}
break;
case 27:
this.state = Aa;
break;
default:
if (c >= 32) {
if (this.x >= this.w) {
this.x = 0;
this.y++;
if (this.y >= this.h) {
this.y--;
this.scroll();
ka = 0;
la = this.h - 1;
}
}
ta = this.y + this.y_base;
if (ta >= this.cur_h)
ta -= this.cur_h;
this.lines[ta][this.x] = (c & 0xffff) | (this.cur_attr << 16);
this.x++;
va(this.y);
}
break;
}
break;
case Aa:
if (c == 91) {
this.esc_params = new Array();
this.cur_param = 0;
this.state = Ba;
} else {
this.state = za;
}
break;
case Ba:
if (c >= 48 && c <= 57) {
this.cur_param = this.cur_param * 10 + c - 48;
} else {
this.esc_params[this.esc_params.length] = this.cur_param;
this.cur_param = 0;
if (c == 59)
break;
this.state = za;
switch (c) {
case 65:
n = this.esc_params[0];
if (n < 1)
n = 1;
this.y -= n;
if (this.y < 0)
this.y = 0;
break;
case 66:
n = this.esc_params[0];
if (n < 1)
n = 1;
this.y += n;
if (this.y >= this.h)
this.y = this.h - 1;
break;
case 67:
n = this.esc_params[0];
if (n < 1)
n = 1;
this.x += n;
if (this.x >= this.w - 1)
this.x = this.w - 1;
break;
case 68:
n = this.esc_params[0];
if (n < 1)
n = 1;
this.x -= n;
if (this.x < 0)
this.x = 0;
break;
case 72:
{
var Ca, ta;
ta = this.esc_params[0] - 1;
if (this.esc_params.length >= 2)
Ca = this.esc_params[1] - 1;
else
Ca = 0;
if (ta < 0)
ta = 0;
else if (ta >= this.h)
ta = this.h - 1;
if (Ca < 0)
Ca = 0;
else if (Ca >= this.w)
Ca = this.w - 1;
this.x = Ca;
this.y = ta;
}
break;
case 74:
wa(this, this.x, this.y);
for (j = this.y + 1; j < this.h; j++)
wa(this, 0, j);
break;
case 75:
wa(this, this.x, this.y);
break;
case 109:
xa(this, this.esc_params);
break;
case 110:
this.queue_chars("\x1b[" + (this.y + 1) + ";" + (this.x + 1) + "R");
break;
default:
break;
}
}
break;
}
}
va(this.y);
if (la >= ka)
this.refresh(ka, la);
};
Term.prototype.writeln = function(ua) {
this.write(ua + '\r\n');
};
Term.prototype.keyDownHandler = function(Da) {
var ua;
ua = "";
switch (Da.keyCode) {
case 8:
ua = "";
break;
case 9:
ua = "\t";
break;
case 13:
ua = "\r";
break;
case 27:
ua = "\x1b";
break;
case 37:
ua = "\x1b[D";
break;
case 39:
ua = "\x1b[C";
break;
case 38:
if (Da.ctrlKey) {
this.scroll_disp(-1);
} else {
ua = "\x1b[A";
}
break;
case 40:
if (Da.ctrlKey) {
this.scroll_disp(1);
} else {
ua = "\x1b[B";
}
break;
case 46:
ua = "\x1b[3~";
break;
case 45:
ua = "\x1b[2~";
break;
case 36:
ua = "\x1bOH";
break;
case 35:
ua = "\x1bOF";
break;
case 33:
if (Da.ctrlKey) {
this.scroll_disp(-(this.h - 1));
} else {
ua = "\x1b[5~";
}
break;
case 34:
if (Da.ctrlKey) {
this.scroll_disp(this.h - 1);
} else {
ua = "\x1b[6~";
}
break;
default:
if (Da.ctrlKey) {
if (Da.keyCode >= 65 && Da.keyCode <= 90) {
ua = String.fromCharCode(Da.keyCode - 64);
} else if (Da.keyCode == 32) {
ua = String.fromCharCode(0);
}
} else if ((!this.is_mac && Da.altKey) || (this.is_mac && Da.metaKey)) {
if (Da.keyCode >= 65 && Da.keyCode <= 90) {
ua = "\x1b" + String.fromCharCode(Da.keyCode + 32);
}
}
break;
}
if (ua) {
if (Da.stopPropagation)
Da.stopPropagation();
if (Da.preventDefault)
Da.preventDefault();
this.show_cursor();
this.key_rep_state = 1;
this.key_rep_str = ua;
this.handler(ua);
return false;
} else {
this.key_rep_state = 0;
return true;
}
};
Term.prototype.keyPressHandler = function(Da) {
var ua, Ea;
if (Da.stopPropagation)
Da.stopPropagation();
if (Da.preventDefault)
Da.preventDefault();
ua = "";
if (!("charCode" in Da)) {
Ea = Da.keyCode;
if (this.key_rep_state == 1) {
this.key_rep_state = 2;
return false;
} else if (this.key_rep_state == 2) {
this.show_cursor();
this.handler(this.key_rep_str);
return false;
}
} else {
Ea = Da.charCode;
}
if (Ea != 0) {
if (!Da.ctrlKey && ((!this.is_mac && !Da.altKey) || (this.is_mac && !Da.metaKey))) {
ua = String.fromCharCode(Ea);
}
}
if (ua) {
this.show_cursor();
this.handler(ua);
return false;
} else {
return true;
}
};
Term.prototype.queue_chars = function(ua) {
this.output_queue += ua;
if (this.output_queue)
setTimeout(this.outputHandler.bind(this), 0);
};
Term.prototype.outputHandler = function() {
if (this.output_queue) {
this.handler(this.output_queue);
this.output_queue = "";
}
};