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 a0f3d6c4d39..8308fc7cdc2 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; |
