]>
Commit | Line | Data |
---|---|---|
6093edb5 JW |
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 | } |