1 /* 2 * `Soft' font definitions 3 * 4 * Created 1995 by Geert Uytterhoeven 5 * Rewritten 1998 by Martin Mares <mj@ucw.cz> 6 * 7 * 2001 - Documented with DocBook 8 * - Brad Douglas <brad@neruo.com> 9 * 10 * This file is subject to the terms and conditions of the GNU General Public 11 * License. See the file COPYING in the main directory of this archive 12 * for more details. 13 */ 14 15 #include <linux/container_of.h> 16 #include <linux/kd.h> 17 #include <linux/module.h> 18 #include <linux/overflow.h> 19 #include <linux/slab.h> 20 #include <linux/string.h> 21 #include <linux/types.h> 22 23 #if defined(__mc68000__) 24 #include <asm/setup.h> 25 #endif 26 27 #include "font.h" 28 29 #define console_font_pitch(font) font_glyph_pitch((font)->width) 30 31 /* 32 * Helpers for font_data_t 33 */ 34 35 /* Extra word getters */ 36 #define REFCOUNT(fd) (((int *)(fd))[-1]) 37 #define FNTSIZE(fd) (((int *)(fd))[-2]) 38 #define FNTSUM(fd) (((int *)(fd))[-4]) 39 40 static struct font_data *to_font_data_struct(font_data_t *fd) 41 { 42 return container_of(fd, struct font_data, data[0]); 43 } 44 45 static bool font_data_is_internal(font_data_t *fd) 46 { 47 return !REFCOUNT(fd); /* internal fonts have no reference counting */ 48 } 49 50 static void font_data_free(font_data_t *fd) 51 { 52 kfree(to_font_data_struct(fd)); 53 } 54 55 /** 56 * font_data_import - Allocates and initializes font data from user space 57 * @font: A font from user space 58 * @vpitch: The size of a single glyph in @font in bytes 59 * @calc_csum: An optional helper to calculate a chechsum 60 * 61 * Font data from user space must be translated to the kernel's format. The 62 * font's glyph geometry and data is provided in @font. The parameter @vpitch 63 * gives the number of bytes per glyph, including trailing bytes. 64 * 65 * The parameter @calc_csum is optional. Fbcon passes crc32() to calculate the 66 * font data's checksum. 67 * 68 * Returns: 69 * Newly initialized font data on success, or a pointer-encoded errno value otherwise. 70 */ 71 font_data_t *font_data_import(const struct console_font *font, unsigned int vpitch, 72 u32 (*calc_csum)(u32, const void *, size_t)) 73 { 74 unsigned int pitch = console_font_pitch(font); 75 unsigned int h = font->height; 76 unsigned int charcount = font->charcount; 77 const unsigned char *data = font->data; 78 u32 csum = 0; 79 struct font_data *font_data; 80 int size, alloc_size; 81 unsigned int i; 82 font_data_t *fd; 83 84 /* Check for integer overflow in font-size calculation */ 85 if (check_mul_overflow(h, pitch, &size) || 86 check_mul_overflow(size, charcount, &size)) 87 return ERR_PTR(-EINVAL); 88 89 /* Check for overflow in allocation size calculation */ 90 if (check_add_overflow(sizeof(*font_data), size, &alloc_size)) 91 return ERR_PTR(-EINVAL); 92 93 font_data = kmalloc(alloc_size, GFP_USER); 94 if (!font_data) 95 return ERR_PTR(-ENOMEM); 96 memset(font_data->extra, 0, sizeof(font_data->extra)); 97 98 for (i = 0; i < charcount; ++i) 99 memcpy(font_data->data + i * h * pitch, data + i * vpitch * pitch, h * pitch); 100 101 if (calc_csum) 102 csum = calc_csum(0, font_data->data, size); 103 104 fd = font_data->data; 105 REFCOUNT(fd) = 1; /* start with reference acquired */ 106 FNTSIZE(fd) = size; 107 FNTSUM(fd) = csum; 108 109 return fd; 110 } 111 EXPORT_SYMBOL_GPL(font_data_import); 112 113 /** 114 * font_data_get - Acquires a reference on font data 115 * @fd: Font data 116 * 117 * Font data from user space is reference counted. The helper 118 * font_data_get() increases the reference counter by one. Invoke 119 * font_data_put() to release the reference. 120 * 121 * Internal font data is located in read-only memory. In this case 122 * the helper returns success without modifying the counter field. 123 * It is still required to call font_data_put() on internal font data. 124 */ 125 void font_data_get(font_data_t *fd) 126 { 127 if (font_data_is_internal(fd)) 128 return; /* never ref static data */ 129 130 if (WARN_ON(!REFCOUNT(fd))) 131 return; /* should never be 0 */ 132 ++REFCOUNT(fd); 133 } 134 EXPORT_SYMBOL_GPL(font_data_get); 135 136 /** 137 * font_data_put - Release a reference on font data 138 * @fd: Font data 139 * 140 * Font data from user space is reference counted. The helper 141 * font_data_put() decreases the reference counter by one. If this was 142 * the final reference, it frees the allocated memory. 143 * 144 * Internal font data is located in read-only memory. In this case 145 * the helper returns success without modifying the counter field. 146 * 147 * Returns: 148 * True if the font data's memory buffer has been freed, false otherwise. 149 */ 150 bool font_data_put(font_data_t *fd) 151 { 152 unsigned int count; 153 154 if (font_data_is_internal(fd)) 155 return false; /* never unref static data */ 156 157 if (WARN_ON(!REFCOUNT(fd))) 158 return false; /* should never be 0 */ 159 160 count = --REFCOUNT(fd); 161 if (!count) 162 font_data_free(fd); 163 164 return !count; 165 } 166 EXPORT_SYMBOL_GPL(font_data_put); 167 168 /** 169 * font_data_size - Return size of the font data in bytes 170 * @fd: Font data 171 * 172 * Returns: 173 * The number of bytes in the given font data. 174 */ 175 unsigned int font_data_size(font_data_t *fd) 176 { 177 return FNTSIZE(fd); 178 } 179 EXPORT_SYMBOL_GPL(font_data_size); 180 181 static unsigned int font_data_num_glyphs(font_data_t *fd, unsigned int width, unsigned int height) 182 { 183 return font_data_size(fd) / font_glyph_size(width, height); 184 } 185 186 /** 187 * font_data_glyph_buf() - Returns the glyph for a specific character as raw bytes 188 * @fd: The font data 189 * @width: The glyph width in bits per scanline 190 * @vpitch: The number of scanlines per glyph 191 * @c: The character 192 * 193 * Glyphs start at fixed intervals within the font data. font_data_glyph_buf() 194 * returns the glyph shape of the specified character. If no such glyph 195 * exists in the font, it returns NULL. 196 * 197 * Returns: 198 * The character's raw glyph shape, or NULL if no glyph exists for the character. The 199 * provided buffer is read-only. 200 */ 201 const unsigned char *font_data_glyph_buf(font_data_t *fd, 202 unsigned int width, unsigned int vpitch, 203 unsigned int c) 204 { 205 if (c >= font_data_num_glyphs(fd, width, vpitch)) 206 return NULL; 207 208 return font_data_buf(fd) + font_glyph_size(width, vpitch) * c; 209 } 210 EXPORT_SYMBOL_GPL(font_data_glyph_buf); 211 212 /** 213 * font_data_is_equal - Compares font data for equality 214 * @lhs: Left-hand side font data 215 * @rhs: Right-hand-size font data 216 * 217 * Font data is equal if is constain the same sequence of values. The 218 * helper also use the checksum, if both arguments contain it. Font data 219 * coming from different origins, internal or from user space, is never 220 * equal. Allowing this would break reference counting. 221 * 222 * Returns: 223 * True if the given font data is equal, false otherwise. 224 */ 225 bool font_data_is_equal(font_data_t *lhs, font_data_t *rhs) 226 { 227 if (font_data_is_internal(lhs) != font_data_is_internal(rhs)) 228 return false; 229 if (font_data_size(lhs) != font_data_size(rhs)) 230 return false; 231 if (FNTSUM(lhs) && FNTSUM(rhs) && FNTSUM(lhs) != FNTSUM(rhs)) 232 return false; 233 234 return !memcmp(lhs, rhs, FNTSIZE(lhs)); 235 } 236 EXPORT_SYMBOL_GPL(font_data_is_equal); 237 238 /** 239 * font_data_export - Stores font data for user space 240 * @fd: Font data 241 * @font: A font for user space 242 * @vpitch: The size of a single glyph in @font in bytes 243 * 244 * Store the font data given in @fd to the font in @font. Values and 245 * pointers in @font are pre-initialized. This helper mostly checks some 246 * corner cases and translates glyph sizes according to the value given 247 * @vpitch. 248 * 249 * Returns: 250 * 0 on success, or a negative errno code otherwise. 251 */ 252 int font_data_export(font_data_t *fd, struct console_font *font, unsigned int vpitch) 253 { 254 const unsigned char *font_data = font_data_buf(fd); 255 unsigned char *data = font->data; 256 unsigned int pitch = console_font_pitch(font); 257 unsigned int glyphsize, i; 258 259 if (!font->width || !font->height || !font->charcount || !font->data) 260 return 0; 261 262 glyphsize = font->height * pitch; 263 264 if (font->charcount * glyphsize > font_data_size(fd)) 265 return -EINVAL; 266 267 for (i = 0; i < font->charcount; i++) { 268 memcpy(data, font_data, glyphsize); 269 memset(data + glyphsize, 0, pitch * vpitch - glyphsize); 270 data += pitch * vpitch; 271 font_data += glyphsize; 272 } 273 274 return 0; 275 } 276 EXPORT_SYMBOL_GPL(font_data_export); 277 278 /* 279 * Font lookup 280 */ 281 282 static const struct font_desc *fonts[] = { 283 #ifdef CONFIG_FONT_8x8 284 &font_vga_8x8, 285 #endif 286 #ifdef CONFIG_FONT_8x16 287 &font_vga_8x16, 288 #endif 289 #ifdef CONFIG_FONT_6x11 290 &font_vga_6x11, 291 #endif 292 #ifdef CONFIG_FONT_7x14 293 &font_7x14, 294 #endif 295 #ifdef CONFIG_FONT_SUN8x16 296 &font_sun_8x16, 297 #endif 298 #ifdef CONFIG_FONT_SUN12x22 299 &font_sun_12x22, 300 #endif 301 #ifdef CONFIG_FONT_10x18 302 &font_10x18, 303 #endif 304 #ifdef CONFIG_FONT_ACORN_8x8 305 &font_acorn_8x8, 306 #endif 307 #ifdef CONFIG_FONT_PEARL_8x8 308 &font_pearl_8x8, 309 #endif 310 #ifdef CONFIG_FONT_MINI_4x6 311 &font_mini_4x6, 312 #endif 313 #ifdef CONFIG_FONT_6x10 314 &font_6x10, 315 #endif 316 #ifdef CONFIG_FONT_TER10x18 317 &font_ter_10x18, 318 #endif 319 #ifdef CONFIG_FONT_TER16x32 320 &font_ter_16x32, 321 #endif 322 #ifdef CONFIG_FONT_6x8 323 &font_6x8, 324 #endif 325 }; 326 327 #define num_fonts ARRAY_SIZE(fonts) 328 329 #ifdef NO_FONTS 330 #error No fonts configured. 331 #endif 332 333 334 /** 335 * find_font - find a font 336 * @name: string name of a font 337 * 338 * Find a specified font with string name @name. 339 * 340 * Returns %NULL if no font found, or a pointer to the 341 * specified font. 342 * 343 */ 344 const struct font_desc *find_font(const char *name) 345 { 346 unsigned int i; 347 348 BUILD_BUG_ON(!num_fonts); 349 for (i = 0; i < num_fonts; i++) 350 if (!strcmp(fonts[i]->name, name)) 351 return fonts[i]; 352 return NULL; 353 } 354 EXPORT_SYMBOL(find_font); 355 356 357 /** 358 * get_default_font - get default font 359 * @xres: screen size of X 360 * @yres: screen size of Y 361 * @font_w: bit array of supported widths (1 - FB_MAX_BLIT_WIDTH) 362 * @font_h: bit array of supported heights (1 - FB_MAX_BLIT_HEIGHT) 363 * 364 * Get the default font for a specified screen size. 365 * Dimensions are in pixels. 366 * 367 * font_w or font_h being NULL means all values are supported. 368 * 369 * Returns %NULL if no font is found, or a pointer to the 370 * chosen font. 371 * 372 */ 373 const struct font_desc *get_default_font(int xres, int yres, 374 unsigned long *font_w, 375 unsigned long *font_h) 376 { 377 int i, c, cc, res; 378 const struct font_desc *f, *g; 379 380 g = NULL; 381 cc = -10000; 382 for (i = 0; i < num_fonts; i++) { 383 f = fonts[i]; 384 c = f->pref; 385 #if defined(__mc68000__) 386 #ifdef CONFIG_FONT_PEARL_8x8 387 if (MACH_IS_AMIGA && f->idx == PEARL8x8_IDX) 388 c = 100; 389 #endif 390 #ifdef CONFIG_FONT_6x11 391 if (MACH_IS_MAC && xres < 640 && f->idx == VGA6x11_IDX) 392 c = 100; 393 #endif 394 #endif 395 if ((yres < 400) == (f->height <= 8)) 396 c += 1000; 397 398 /* prefer a bigger font for high resolution */ 399 res = (xres / f->width) * (yres / f->height) / 1000; 400 if (res > 20) 401 c += 20 - res; 402 403 if ((!font_w || test_bit(f->width - 1, font_w)) && 404 (!font_h || test_bit(f->height - 1, font_h))) 405 c += 1000; 406 407 if (c > cc) { 408 cc = c; 409 g = f; 410 } 411 } 412 return g; 413 } 414 EXPORT_SYMBOL(get_default_font); 415 416 MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); 417 MODULE_DESCRIPTION("Console Fonts"); 418 MODULE_LICENSE("GPL"); 419