]> git.proxmox.com Git - grub2.git/blame - grub-core/video/ieee1275.c
Merge mainline into newreloc. For now without boot tests
[grub2.git] / grub-core / video / ieee1275.c
CommitLineData
fbab7b07
VS
1/*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
4 *
5 * GRUB 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.
9 *
10 * GRUB 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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#define grub_video_render_target grub_video_fbrender_target
20
21#include <grub/err.h>
22#include <grub/types.h>
23#include <grub/dl.h>
24#include <grub/misc.h>
25#include <grub/mm.h>
26#include <grub/video.h>
27#include <grub/video_fb.h>
28#include <grub/ieee1275/ieee1275.h>
29
30/* Only 8-bit indexed color is supported for now. */
31
32static unsigned old_width, old_height;
33static int restore_needed;
34static char *display;
35
36static struct
37{
38 struct grub_video_mode_info mode_info;
39 struct grub_video_render_target *render_target;
40 grub_uint8_t *ptr;
41} framebuffer;
42
43static grub_err_t
44grub_video_ieee1275_set_palette (unsigned int start, unsigned int count,
45 struct grub_video_palette_data *palette_data);
46
47static void
48set_video_mode (unsigned width __attribute__ ((unused)),
49 unsigned height __attribute__ ((unused)))
50{
51 /* TODO */
52}
53
54static void
55find_display (void)
56{
57 auto int hook (struct grub_ieee1275_devalias *alias);
58 int hook (struct grub_ieee1275_devalias *alias)
59 {
60 if (grub_strcmp (alias->type, "display") == 0)
61 {
a3334e79
VS
62 grub_dprintf ("video", "Found display %s\n", alias->path);
63 display = grub_strdup (alias->path);
fbab7b07
VS
64 return 1;
65 }
66 return 0;
67 }
68
69 grub_ieee1275_devices_iterate (hook);
70}
71
72static grub_err_t
73grub_video_ieee1275_init (void)
74{
75 grub_memset (&framebuffer, 0, sizeof(framebuffer));
76 return grub_video_fb_init ();
77}
78
79static grub_err_t
80grub_video_ieee1275_fini (void)
81{
82 if (restore_needed)
83 {
84 set_video_mode (old_width, old_height);
85 restore_needed = 0;
86 }
87 return grub_video_fb_fini ();
88}
89
90static grub_err_t
91grub_video_ieee1275_fill_mode_info (grub_ieee1275_phandle_t dev,
92 struct grub_video_mode_info *out)
93{
94 grub_uint32_t tmp;
95
96 grub_memset (out, 0, sizeof (*out));
97
98 if (grub_ieee1275_get_integer_property (dev, "width", &tmp,
99 sizeof (tmp), 0))
100 return grub_error (GRUB_ERR_IO, "Couldn't retrieve display width.");
101 out->width = tmp;
102
103 if (grub_ieee1275_get_integer_property (dev, "height", &tmp,
104 sizeof (tmp), 0))
105 return grub_error (GRUB_ERR_IO, "Couldn't retrieve display height.");
106 out->height = tmp;
107
108 if (grub_ieee1275_get_integer_property (dev, "linebytes", &tmp,
109 sizeof (tmp), 0))
110 return grub_error (GRUB_ERR_IO, "Couldn't retrieve display pitch.");
111 out->pitch = tmp;
112
113 out->mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
114 out->bpp = 8;
115 out->bytes_per_pixel = 1;
116 out->number_of_colors = 256;
117
118 out->blit_format = grub_video_get_blit_format (out);
119 return GRUB_ERR_NONE;
120}
121
122static grub_err_t
123grub_video_ieee1275_setup (unsigned int width, unsigned int height,
124 unsigned int mode_type __attribute__ ((unused)),
125 unsigned int mode_mask __attribute__ ((unused)))
126{
18d4c6f0 127 grub_uint32_t current_width, current_height, address;
fbab7b07
VS
128 grub_err_t err;
129 grub_ieee1275_phandle_t dev;
130
131 if (!display)
132 return grub_error (GRUB_ERR_IO, "Couldn't find display device.");
133
134 if (grub_ieee1275_finddevice (display, &dev))
135 return grub_error (GRUB_ERR_IO, "Couldn't open display device.");
136
137 if (grub_ieee1275_get_integer_property (dev, "width", &current_width,
138 sizeof (current_width), 0))
139 return grub_error (GRUB_ERR_IO, "Couldn't retrieve display width.");
140
141 if (grub_ieee1275_get_integer_property (dev, "height", &current_height,
142 sizeof (current_width), 0))
143 return grub_error (GRUB_ERR_IO, "Couldn't retrieve display height.");
144
145 if ((width == current_width && height == current_height)
146 || (width == 0 && height == 0))
147 {
148 grub_dprintf ("video", "IEEE1275: keeping current mode %dx%d\n",
149 current_width, current_height);
150 }
151 else
152 {
153 grub_dprintf ("video", "IEEE1275: Setting mode %dx%d\n", width, height);
154 /* TODO. */
58b78c12 155 return grub_error (GRUB_ERR_IO, "can't set mode %dx%d", width, height);
fbab7b07
VS
156 }
157
158 err = grub_video_ieee1275_fill_mode_info (dev, &framebuffer.mode_info);
159 if (err)
160 {
161 grub_dprintf ("video", "IEEE1275: couldn't fill mode info\n");
162 return err;
163 }
164
ec0be08d 165 if (grub_ieee1275_get_integer_property (dev, "address", (void *) &address,
fbab7b07
VS
166 sizeof (address), 0))
167 return grub_error (GRUB_ERR_IO, "Couldn't retrieve display address.");
168
18d4c6f0
VS
169 /* For some reason sparc64 uses 32-bit pointer too. */
170 framebuffer.ptr = (void *) (grub_addr_t) address;
fbab7b07
VS
171
172 grub_video_ieee1275_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
173 grub_video_fbstd_colors);
174
175 grub_dprintf ("video", "IEEE1275: initialising FB @ %p %dx%dx%d\n",
176 framebuffer.ptr, framebuffer.mode_info.width,
177 framebuffer.mode_info.height, framebuffer.mode_info.bpp);
178
179 err = grub_video_fb_create_render_target_from_pointer
180 (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr);
181
182 if (err)
183 {
184 grub_dprintf ("video", "IEEE1275: Couldn't create FB target\n");
185 return err;
186 }
187
188 err = grub_video_fb_set_active_render_target (framebuffer.render_target);
189
190 if (err)
191 {
192 grub_dprintf ("video", "IEEE1275: Couldn't set FB target\n");
193 return err;
194 }
195
196 err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
197 grub_video_fbstd_colors);
198
199 if (err)
200 grub_dprintf ("video", "IEEE1275: Couldn't set palette\n");
201 else
202 grub_dprintf ("video", "IEEE1275: Success\n");
203
204 return err;
205}
206
207static grub_err_t
208grub_video_ieee1275_swap_buffers (void)
209{
210 /* TODO: Implement buffer swapping. */
211 return GRUB_ERR_NONE;
212}
213
214static grub_err_t
215grub_video_ieee1275_set_active_render_target (struct grub_video_render_target *target)
216{
217 if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
218 target = framebuffer.render_target;
219
220 return grub_video_fb_set_active_render_target (target);
221}
222
223static grub_err_t
224grub_video_ieee1275_get_info_and_fini (struct grub_video_mode_info *mode_info,
225 void **framebuf)
226{
227 grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info));
228 *framebuf = (char *) framebuffer.ptr;
229
230 grub_video_fb_fini ();
231
232 return GRUB_ERR_NONE;
233}
234
235static grub_err_t
236grub_video_ieee1275_set_palette (unsigned int start, unsigned int count,
237 struct grub_video_palette_data *palette_data)
238{
239 grub_err_t err;
240 struct grub_video_palette_data fb_palette_data[256];
241
242 err = grub_video_fb_set_palette (start, count, palette_data);
243 if (err)
244 return err;
245
246 grub_video_fb_get_palette (0, 256, fb_palette_data);
247
248 /* TODO. */
249
250 return GRUB_ERR_NONE;
251}
252
253static struct grub_video_adapter grub_video_ieee1275_adapter =
254 {
255 .name = "IEEE1275 video driver",
256
d49703d1
VS
257 .prio = GRUB_VIDEO_ADAPTER_PRIO_FIRMWARE,
258
fbab7b07
VS
259 .init = grub_video_ieee1275_init,
260 .fini = grub_video_ieee1275_fini,
261 .setup = grub_video_ieee1275_setup,
262 .get_info = grub_video_fb_get_info,
263 .get_info_and_fini = grub_video_ieee1275_get_info_and_fini,
264 .set_palette = grub_video_ieee1275_set_palette,
265 .get_palette = grub_video_fb_get_palette,
266 .set_viewport = grub_video_fb_set_viewport,
267 .get_viewport = grub_video_fb_get_viewport,
268 .map_color = grub_video_fb_map_color,
269 .map_rgb = grub_video_fb_map_rgb,
270 .map_rgba = grub_video_fb_map_rgba,
271 .unmap_color = grub_video_fb_unmap_color,
272 .fill_rect = grub_video_fb_fill_rect,
273 .blit_bitmap = grub_video_fb_blit_bitmap,
274 .blit_render_target = grub_video_fb_blit_render_target,
275 .scroll = grub_video_fb_scroll,
276 .swap_buffers = grub_video_ieee1275_swap_buffers,
277 .create_render_target = grub_video_fb_create_render_target,
278 .delete_render_target = grub_video_fb_delete_render_target,
279 .set_active_render_target = grub_video_ieee1275_set_active_render_target,
280 .get_active_render_target = grub_video_fb_get_active_render_target,
281
282 .next = 0
283 };
284
285GRUB_MOD_INIT(ieee1275_fb)
286{
287 find_display ();
288 if (display)
289 grub_video_register (&grub_video_ieee1275_adapter);
290}
291
292GRUB_MOD_FINI(ieee1275_fb)
293{
294 if (restore_needed)
295 {
296 set_video_mode (old_width, old_height);
297 restore_needed = 0;
298 }
299 if (display)
300 grub_video_unregister (&grub_video_ieee1275_adapter);
301 grub_free (display);
302}