]> Joshua Wise's Git repositories - netwatch.git/blobdiff - cs410/cs410.c
First pass of 410watch UI code.
[netwatch.git] / cs410 / cs410.c
diff --git a/cs410/cs410.c b/cs410/cs410.c
new file mode 100644 (file)
index 0000000..6cc1763
--- /dev/null
@@ -0,0 +1,199 @@
+/* cs410.c
+ * Entry points for 15-410 extensions
+ * NetWatch system management mode administration console
+ *
+ * Copyright (c) 2008 Jacob Potter and Joshua Wise.  All rights reserved.
+ * This program is free software; you can redistribute and/or modify it under
+ * the terms found in the file LICENSE in the root of this source tree.
+ *
+ */
+
+#include <io.h>
+#include <smi.h>
+#include <smram.h>
+#include <video_defines.h>
+#include <output.h>
+#include <minilib.h>
+
+#define CONSCOLOR 0x1F
+
+unsigned char oldcons[80 * 25 * 2];
+
+static unsigned char vga_read(unsigned char idx)
+{
+       outb(CRTC_IDX_REG, idx);
+       return inb(CRTC_DATA_REG);
+}
+
+static char * vga_base()
+{
+       return (char *) (
+               0xB8000
+               + (((unsigned int) vga_read(CRTC_START_ADDR_MSB_IDX)) << 9)
+               + (((unsigned int) vga_read(CRTC_START_ADDR_LSB_IDX)) << 1)
+       );
+}
+
+static void grey_console()
+{
+       int i;
+       char *p = vga_base();
+       
+       for (i = 0; i < 80*25; i++, p+=2)
+               p[1] &= ~0xF8;  /* Clear the background and any brightness. */
+}
+
+#define CHAR(x, y) (base[((y)*80+(x))*2])
+#define COLOR(x, y) (base[((y)*80+(x))*2+1])
+
+static void ui_frame(int xp, int yp, int xs, int ys, char *title)
+{
+       int x, y;
+       char *base = vga_base();
+       
+       /* Blank and fill the region. */
+       for (y = yp; y <= (yp + ys); y++)
+               for (x = xp; x <= (xp + xs); x++)
+               {
+                       CHAR(x, y) = ' ';
+                       COLOR(x, y) = CONSCOLOR;
+               }
+
+       /* Draw the top and the bottom (and the bar if need be). */     
+       for (x = xp; x <= (xp + xs); x++)
+       {
+               CHAR(x, yp) = 0xCD /* double line horizontal */;
+               CHAR(x, yp+ys) = 0xCD /* double line horizontal */;
+               if (title)
+                       CHAR(x, yp+2) = 0xC4 /* single line horizontal */;
+       }
+       
+       /* Draw the left and right. */
+       for (y = yp; y <= (yp + ys); y++)
+       {
+               CHAR(xp, y) = 0xBA /* double line vertical */;
+               CHAR(xp+xs, y) = 0xBA /* double line vertical */;
+       }
+       
+       /* Drop in the corners. */
+       CHAR(xp, yp) = 0xC9;
+       CHAR(xp+xs, yp) = 0xBB;
+       CHAR(xp, yp+ys) = 0xC8;
+       CHAR(xp+xs, yp+ys) = 0xBC;
+       if (title)
+       {
+               CHAR(xp, yp+2) = 0xC7;
+               CHAR(xp+xs, yp+2) = 0xB6;
+       }
+       
+       /* Drop in the text. */
+       if (title)
+               for (x = (xs - strlen(title)) / 2 + xp; *title; x++, title++)
+                       CHAR(x, yp+1) = *title;
+}
+
+static void ui_label(int xp, int yp, char *s)
+{
+       int x;
+       char *base = vga_base();
+       
+       for (x = xp; *s; x++, s++)
+               CHAR(x, yp) = *s;
+}
+
+typedef enum ui_element_type {
+       UI_FRAME = 0,
+       UI_LABEL = 1,
+       UI_END = -1
+} ui_element_type_t;
+
+typedef union ui_element {
+       ui_element_type_t type;
+       struct {
+               ui_element_type_t type;
+               int xp, yp;
+               int xs, ys;
+               char *title;
+       } frame;
+       struct {
+               ui_element_type_t type;
+               int xp, yp;
+               char *text;
+       } label;
+} ui_element_t;
+
+static ui_element_t mainmenu[] = {
+       { .frame = {
+               .type = UI_FRAME,
+               .xp = 10, .yp = 5,
+               .xs = 60, .ys = 15,
+               .title = "NetWatch main menu" } },
+       { .label = {
+               .type = UI_LABEL,
+               .xp = 12, .yp = 8,
+               .text = "Options:" } },
+       { .label = {
+               .type = UI_LABEL,
+               .xp = 12, .yp = 10,
+               .text = "q - Return to system" } },
+       { .type = UI_END }
+};
+
+static void ui_render(ui_element_t *ui)
+{
+       for (; ui->type != UI_END; ui++)
+               switch (ui->type)
+               {
+               case UI_FRAME:
+                       ui_frame(ui->frame.xp, ui->frame.yp,
+                                ui->frame.xs, ui->frame.ys,
+                                ui->frame.title);
+                       break;
+               case UI_LABEL:
+                       ui_label(ui->label.xp, ui->label.yp,
+                                ui->label.text);
+                       break;
+               case UI_END:
+               default:
+                       return; /* ??? */
+               }
+}
+
+void cs410_pwrbtn_handler(smi_event_t ev)
+{
+       smram_state_t old_state;
+       
+       outputf("410watch: Power button event");
+       
+       /* Save off the console. */
+       old_state = smram_save_state();
+       smram_aseg_set_state(SMRAM_ASEG_SMMCODE);
+       memcpy(oldcons, vga_base(), 80*25*2);
+       
+       /* Pull a Simics, and grey out the console -- why not? */
+       grey_console();
+       
+       /* Show the main menu. */
+       ui_render(mainmenu);
+       
+       /* Allow access to data in ASEG. */
+       smram_restore_state(old_state);
+       
+       /* Now just sit for a while to show off our newly greyed console. */
+       char c;
+       char *p = vga_base() + (11*80+12)*2;
+       extern int getchar();
+       while ((c = getchar()) != 'q')
+       {
+               smram_aseg_set_state(SMRAM_ASEG_SMMCODE);
+               *p = c;
+               p += 2;
+               smram_restore_state(old_state);
+       }
+       
+       /* Put the console back. */
+       smram_aseg_set_state(SMRAM_ASEG_SMMCODE);
+       memcpy(vga_base(), oldcons, 80*25*2);
+       smram_restore_state(old_state);
+
+}
This page took 0.02606 seconds and 4 git commands to generate.