[rendering] Add batch mode to the simple code
[wikipediardware.git] / mbr / menu.c
blob06341e81f65a6336b292de373dcfc92adc5899d1
1 /*
2 e07 bootloader suite - boot menu
3 Copyright (c) 2009 Christopher Hall <hsw@openmoko.com>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #define APPLICATION_TITLE "boot menu"
21 #include "application.h"
22 #include "lcd.h"
23 #include "eeprom.h"
26 struct guilib_image
28 u32 width;
29 u32 height;
30 u8 data[];
32 #include "splash.h"
34 #define MAXIMUM_BLOCKS 8
35 #define HEADER_MAGIC 0x4f4d4153
37 struct {
38 u32 magic;
39 char name[32];
40 } header;
42 static const char spinner[4] = "-\\|/";
45 int process(int block, int status);
46 void print_cpu_type(void);
49 // this must be the first executable code as the loader executes from the first program address
50 ReturnType menu(int block, int status)
52 register int i = 0;
53 APPLICATION_INITIALISE();
54 init_lcd();
55 i = process(block, status);
57 // next program
58 APPLICATION_FINALISE(i, 0);
61 static void fill(u8 value)
63 int x = 0;
64 int y = 0;
65 u8 *fb = (u8*)LCD_VRAM;
67 for (y = 0; y < LCD_HEIGHT_LINES; ++y) {
68 for (x = 0; x < LCD_VRAM_WIDTH_BYTES; ++x) {
69 *fb++ = value;
73 static void display_image(u8 background, u8 toggle)
75 int xOffset = (LCD_WIDTH_PIXELS - splash_image.width) / (2 * 8);
76 u8 *fb = (u8*)LCD_VRAM;
77 unsigned int y = 0;
78 unsigned int x = 0;
79 unsigned int width = (splash_image.width + 7) / 8;
80 const u8 *src = splash_image.data;
82 fill(background);
83 fb += (LCD_HEIGHT_LINES - splash_image.height) / 2 * LCD_VRAM_WIDTH_BYTES;
84 for (y = 0; y < splash_image.height; ++y) {
85 for (x = 0; x < width; ++x) {
86 fb[x + xOffset] = toggle ^ *src++;
88 fb += LCD_VRAM_WIDTH_BYTES;
92 int process(int block, int status)
94 int i = 0;
95 int k = 0;
96 u8 valid[MAXIMUM_BLOCKS] = {0};
98 display_image(0x00, 0xff);
100 if (0 != status) {
101 print_cpu_type();
102 print("\nmenu? ");
103 for (i = 0; i < 20; ++i) {
104 for (k = 0; k < sizeof(spinner); ++k) {
105 delay_us(10000);
106 print_char(spinner[k]);
107 print_char('\x08');
109 if (serial_input_available()) {
110 status = 0;
111 break;
115 print_char('\n');
117 if (0 == status) {
118 print("\nBoot Menu\n\n");
120 // not zero since this program should be in block zero
121 for (i = 1; i < MAXIMUM_BLOCKS; ++i) {
122 eeprom_load((i << 13), (void *)&header, sizeof(header));
124 if (HEADER_MAGIC == header.magic) {
125 print_char(('A' - 1) + i);
126 print(". ");
127 for (k = 0; k < sizeof(header.name); ++k) {
128 if ('\0' == header.name[k] || '\xff' == header.name[k]) {
129 break;
131 print_char(header.name[k]);
133 print_char('\n');
134 valid[i] = 1;
137 print("\nEnter selection: ");
138 for (;;) {
139 k = serial_input_char();
140 if ('A' <= k && 'Z' >= k) {
141 k += 'a' - 'A';
143 i = k - 'a' + 1;
144 if (0 < i && MAXIMUM_BLOCKS > i) {
145 if (valid[i]) {
146 print_char(k);
147 print_char('\n');
148 break;
152 } else {
153 i = block + 1;
155 return i;
158 void print_cpu_type(void)
160 print("CPU: ");
161 switch (CORE_ID) {
162 case CORE_ID_STANDARD:
163 print(CORE_ID_STANDARD_DESC);
164 break;
165 case CORE_ID_MINI:
166 print(CORE_ID_MINI_DESC);
167 break;
168 case CORE_ID_ADVANCED:
169 print(CORE_ID_ADVANCED_DESC);
170 break;
171 case CORE_ID_PE:
172 print(CORE_ID_PE_DESC);
173 break;
174 case CORE_ID_PE_LE:
175 print(CORE_ID_PE_LE_DESC);
176 break;
177 default:
178 print("CORE unknown");
179 break;
181 print(" ");
182 switch (PRODUCT_ID) {
183 case PRODUCT_ID_3:
184 print(PRODUCT_ID_3_DESC);
185 break;
186 case PRODUCT_ID_4:
187 print(PRODUCT_ID_4_DESC);
188 break;
189 case PRODUCT_ID_3E:
190 print(PRODUCT_ID_3E_DESC);
191 break;
192 case PRODUCT_ID_3L:
193 print(PRODUCT_ID_3L_DESC);
194 break;
196 print_byte(MODEL_ID);
197 print(" V 0x");
198 print_byte(VERSION_ID);
199 print_char('\n');