]> Joshua Wise's Git repositories - netwatch.git/blob - cs410/cs410.c
First pass of 410watch UI code.
[netwatch.git] / cs410 / cs410.c
1 /* cs410.c
2  * Entry points for 15-410 extensions
3  * NetWatch system management mode administration console
4  *
5  * Copyright (c) 2008 Jacob Potter and Joshua Wise.  All rights reserved.
6  * This program is free software; you can redistribute and/or modify it under
7  * the terms found in the file LICENSE in the root of this source tree.
8  *
9  */
10
11 #include <io.h>
12 #include <smi.h>
13 #include <smram.h>
14 #include <video_defines.h>
15 #include <output.h>
16 #include <minilib.h>
17
18 #define CONSCOLOR 0x1F
19
20 unsigned char oldcons[80 * 25 * 2];
21
22 static unsigned char vga_read(unsigned char idx)
23 {
24         outb(CRTC_IDX_REG, idx);
25         return inb(CRTC_DATA_REG);
26 }
27
28 static char * vga_base()
29 {
30         return (char *) (
31                 0xB8000
32                 + (((unsigned int) vga_read(CRTC_START_ADDR_MSB_IDX)) << 9)
33                 + (((unsigned int) vga_read(CRTC_START_ADDR_LSB_IDX)) << 1)
34         );
35 }
36
37 static void grey_console()
38 {
39         int i;
40         char *p = vga_base();
41         
42         for (i = 0; i < 80*25; i++, p+=2)
43                 p[1] &= ~0xF8;  /* Clear the background and any brightness. */
44 }
45
46 #define CHAR(x, y) (base[((y)*80+(x))*2])
47 #define COLOR(x, y) (base[((y)*80+(x))*2+1])
48
49 static void ui_frame(int xp, int yp, int xs, int ys, char *title)
50 {
51         int x, y;
52         char *base = vga_base();
53         
54         /* Blank and fill the region. */
55         for (y = yp; y <= (yp + ys); y++)
56                 for (x = xp; x <= (xp + xs); x++)
57                 {
58                         CHAR(x, y) = ' ';
59                         COLOR(x, y) = CONSCOLOR;
60                 }
61
62         /* Draw the top and the bottom (and the bar if need be). */     
63         for (x = xp; x <= (xp + xs); x++)
64         {
65                 CHAR(x, yp) = 0xCD /* double line horizontal */;
66                 CHAR(x, yp+ys) = 0xCD /* double line horizontal */;
67                 if (title)
68                         CHAR(x, yp+2) = 0xC4 /* single line horizontal */;
69         }
70         
71         /* Draw the left and right. */
72         for (y = yp; y <= (yp + ys); y++)
73         {
74                 CHAR(xp, y) = 0xBA /* double line vertical */;
75                 CHAR(xp+xs, y) = 0xBA /* double line vertical */;
76         }
77         
78         /* Drop in the corners. */
79         CHAR(xp, yp) = 0xC9;
80         CHAR(xp+xs, yp) = 0xBB;
81         CHAR(xp, yp+ys) = 0xC8;
82         CHAR(xp+xs, yp+ys) = 0xBC;
83         if (title)
84         {
85                 CHAR(xp, yp+2) = 0xC7;
86                 CHAR(xp+xs, yp+2) = 0xB6;
87         }
88         
89         /* Drop in the text. */
90         if (title)
91                 for (x = (xs - strlen(title)) / 2 + xp; *title; x++, title++)
92                         CHAR(x, yp+1) = *title;
93 }
94
95 static void ui_label(int xp, int yp, char *s)
96 {
97         int x;
98         char *base = vga_base();
99         
100         for (x = xp; *s; x++, s++)
101                 CHAR(x, yp) = *s;
102 }
103
104 typedef enum ui_element_type {
105         UI_FRAME = 0,
106         UI_LABEL = 1,
107         UI_END = -1
108 } ui_element_type_t;
109
110 typedef union ui_element {
111         ui_element_type_t type;
112         struct {
113                 ui_element_type_t type;
114                 int xp, yp;
115                 int xs, ys;
116                 char *title;
117         } frame;
118         struct {
119                 ui_element_type_t type;
120                 int xp, yp;
121                 char *text;
122         } label;
123 } ui_element_t;
124
125 static ui_element_t mainmenu[] = {
126         { .frame = {
127                 .type = UI_FRAME,
128                 .xp = 10, .yp = 5,
129                 .xs = 60, .ys = 15,
130                 .title = "NetWatch main menu" } },
131         { .label = {
132                 .type = UI_LABEL,
133                 .xp = 12, .yp = 8,
134                 .text = "Options:" } },
135         { .label = {
136                 .type = UI_LABEL,
137                 .xp = 12, .yp = 10,
138                 .text = "q - Return to system" } },
139         { .type = UI_END }
140 };
141
142 static void ui_render(ui_element_t *ui)
143 {
144         for (; ui->type != UI_END; ui++)
145                 switch (ui->type)
146                 {
147                 case UI_FRAME:
148                         ui_frame(ui->frame.xp, ui->frame.yp,
149                                  ui->frame.xs, ui->frame.ys,
150                                  ui->frame.title);
151                         break;
152                 case UI_LABEL:
153                         ui_label(ui->label.xp, ui->label.yp,
154                                  ui->label.text);
155                         break;
156                 case UI_END:
157                 default:
158                         return; /* ??? */
159                 }
160 }
161
162 void cs410_pwrbtn_handler(smi_event_t ev)
163 {
164         smram_state_t old_state;
165         
166         outputf("410watch: Power button event");
167         
168         /* Save off the console. */
169         old_state = smram_save_state();
170         smram_aseg_set_state(SMRAM_ASEG_SMMCODE);
171         memcpy(oldcons, vga_base(), 80*25*2);
172         
173         /* Pull a Simics, and grey out the console -- why not? */
174         grey_console();
175         
176         /* Show the main menu. */
177         ui_render(mainmenu);
178         
179         /* Allow access to data in ASEG. */
180         smram_restore_state(old_state);
181         
182         /* Now just sit for a while to show off our newly greyed console. */
183         char c;
184         char *p = vga_base() + (11*80+12)*2;
185         extern int getchar();
186         while ((c = getchar()) != 'q')
187         {
188                 smram_aseg_set_state(SMRAM_ASEG_SMMCODE);
189                 *p = c;
190                 p += 2;
191                 smram_restore_state(old_state);
192         }
193         
194         /* Put the console back. */
195         smram_aseg_set_state(SMRAM_ASEG_SMMCODE);
196         memcpy(vga_base(), oldcons, 80*25*2);
197         smram_restore_state(old_state);
198
199 }
This page took 0.037872 seconds and 4 git commands to generate.