diff options
-rw-r--r-- | drivers/tty/vt/consolemap.c | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c index a0f3d6c4d39d..8308fc7cdc26 100644 --- a/drivers/tty/vt/consolemap.c +++ b/drivers/tty/vt/consolemap.c | |||
@@ -516,6 +516,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) | |||
516 | int err = 0, err1, i; | 516 | int err = 0, err1, i; |
517 | struct uni_pagedir *p, *q; | 517 | struct uni_pagedir *p, *q; |
518 | 518 | ||
519 | /* Save original vc_unipagdir_loc in case we allocate a new one */ | ||
519 | p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; | 520 | p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; |
520 | if (p->readonly) return -EIO; | 521 | if (p->readonly) return -EIO; |
521 | 522 | ||
@@ -528,26 +529,57 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) | |||
528 | err1 = con_clear_unimap(vc, NULL); | 529 | err1 = con_clear_unimap(vc, NULL); |
529 | if (err1) return err1; | 530 | if (err1) return err1; |
530 | 531 | ||
532 | /* | ||
533 | * Since refcount was > 1, con_clear_unimap() allocated a | ||
534 | * a new uni_pagedir for this vc. Re: p != q | ||
535 | */ | ||
531 | q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; | 536 | q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; |
532 | for (i = 0, l = 0; i < 32; i++) | 537 | |
538 | /* | ||
539 | * uni_pgdir is a 32*32*64 table with rows allocated | ||
540 | * when its first entry is added. The unicode value must | ||
541 | * still be incremented for empty rows. We are copying | ||
542 | * entries from "p" (old) to "q" (new). | ||
543 | */ | ||
544 | l = 0; /* unicode value */ | ||
545 | for (i = 0; i < 32; i++) | ||
533 | if ((p1 = p->uni_pgdir[i])) | 546 | if ((p1 = p->uni_pgdir[i])) |
534 | for (j = 0; j < 32; j++) | 547 | for (j = 0; j < 32; j++) |
535 | if ((p2 = p1[j])) | 548 | if ((p2 = p1[j])) { |
536 | for (k = 0; k < 64; k++, l++) | 549 | for (k = 0; k < 64; k++, l++) |
537 | if (p2[k] != 0xffff) { | 550 | if (p2[k] != 0xffff) { |
551 | /* | ||
552 | * Found one, copy entry for unicode | ||
553 | * l with fontpos value p2[k]. | ||
554 | */ | ||
538 | err1 = con_insert_unipair(q, l, p2[k]); | 555 | err1 = con_insert_unipair(q, l, p2[k]); |
539 | if (err1) { | 556 | if (err1) { |
540 | p->refcount++; | 557 | p->refcount++; |
541 | *vc->vc_uni_pagedir_loc = (unsigned long)p; | 558 | *vc->vc_uni_pagedir_loc = (unsigned long)p; |
542 | con_release_unimap(q); | 559 | con_release_unimap(q); |
543 | kfree(q); | 560 | kfree(q); |
544 | return err1; | 561 | return err1; |
545 | } | 562 | } |
546 | } | 563 | } |
547 | p = q; | 564 | } else { |
548 | } else if (p == dflt) | 565 | /* Account for row of 64 empty entries */ |
566 | l += 64; | ||
567 | } | ||
568 | else | ||
569 | /* Account for empty table */ | ||
570 | l += 32 * 64; | ||
571 | |||
572 | /* | ||
573 | * Finished copying font table, set vc_uni_pagedir to new table | ||
574 | */ | ||
575 | p = q; | ||
576 | } else if (p == dflt) { | ||
549 | dflt = NULL; | 577 | dflt = NULL; |
550 | 578 | } | |
579 | |||
580 | /* | ||
581 | * Insert user specified unicode pairs into new table. | ||
582 | */ | ||
551 | while (ct--) { | 583 | while (ct--) { |
552 | unsigned short unicode, fontpos; | 584 | unsigned short unicode, fontpos; |
553 | __get_user(unicode, &list->unicode); | 585 | __get_user(unicode, &list->unicode); |
@@ -557,11 +589,14 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) | |||
557 | list++; | 589 | list++; |
558 | } | 590 | } |
559 | 591 | ||
592 | /* | ||
593 | * Merge with fontmaps of any other virtual consoles. | ||
594 | */ | ||
560 | if (con_unify_unimap(vc, p)) | 595 | if (con_unify_unimap(vc, p)) |
561 | return err; | 596 | return err; |
562 | 597 | ||
563 | for (i = 0; i <= 3; i++) | 598 | for (i = 0; i <= 3; i++) |
564 | set_inverse_transl(vc, p, i); /* Update all inverse translations */ | 599 | set_inverse_transl(vc, p, i); /* Update inverse translations */ |
565 | set_inverse_trans_unicode(vc, p); | 600 | set_inverse_trans_unicode(vc, p); |
566 | 601 | ||
567 | return err; | 602 | return err; |