|
@@ -516,6 +516,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
|
|
|
int err = 0, err1, i;
|
|
|
struct uni_pagedir *p, *q;
|
|
|
|
|
|
+ /* Save original vc_unipagdir_loc in case we allocate a new one */
|
|
|
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
|
|
|
if (p->readonly) return -EIO;
|
|
|
|
|
@@ -528,26 +529,57 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
|
|
|
err1 = con_clear_unimap(vc, NULL);
|
|
|
if (err1) return err1;
|
|
|
|
|
|
+ /*
|
|
|
+ * Since refcount was > 1, con_clear_unimap() allocated a
|
|
|
+ * a new uni_pagedir for this vc. Re: p != q
|
|
|
+ */
|
|
|
q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
|
|
|
- for (i = 0, l = 0; i < 32; i++)
|
|
|
+
|
|
|
+ /*
|
|
|
+ * uni_pgdir is a 32*32*64 table with rows allocated
|
|
|
+ * when its first entry is added. The unicode value must
|
|
|
+ * still be incremented for empty rows. We are copying
|
|
|
+ * entries from "p" (old) to "q" (new).
|
|
|
+ */
|
|
|
+ l = 0; /* unicode value */
|
|
|
+ for (i = 0; i < 32; i++)
|
|
|
if ((p1 = p->uni_pgdir[i]))
|
|
|
for (j = 0; j < 32; j++)
|
|
|
- if ((p2 = p1[j]))
|
|
|
+ if ((p2 = p1[j])) {
|
|
|
for (k = 0; k < 64; k++, l++)
|
|
|
if (p2[k] != 0xffff) {
|
|
|
+ /*
|
|
|
+ * Found one, copy entry for unicode
|
|
|
+ * l with fontpos value p2[k].
|
|
|
+ */
|
|
|
err1 = con_insert_unipair(q, l, p2[k]);
|
|
|
if (err1) {
|
|
|
p->refcount++;
|
|
|
*vc->vc_uni_pagedir_loc = (unsigned long)p;
|
|
|
con_release_unimap(q);
|
|
|
kfree(q);
|
|
|
- return err1;
|
|
|
+ return err1;
|
|
|
}
|
|
|
- }
|
|
|
- p = q;
|
|
|
- } else if (p == dflt)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ /* Account for row of 64 empty entries */
|
|
|
+ l += 64;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ /* Account for empty table */
|
|
|
+ l += 32 * 64;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Finished copying font table, set vc_uni_pagedir to new table
|
|
|
+ */
|
|
|
+ p = q;
|
|
|
+ } else if (p == dflt) {
|
|
|
dflt = NULL;
|
|
|
-
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Insert user specified unicode pairs into new table.
|
|
|
+ */
|
|
|
while (ct--) {
|
|
|
unsigned short unicode, fontpos;
|
|
|
__get_user(unicode, &list->unicode);
|
|
@@ -557,11 +589,14 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
|
|
|
list++;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * Merge with fontmaps of any other virtual consoles.
|
|
|
+ */
|
|
|
if (con_unify_unimap(vc, p))
|
|
|
return err;
|
|
|
|
|
|
for (i = 0; i <= 3; i++)
|
|
|
- set_inverse_transl(vc, p, i); /* Update all inverse translations */
|
|
|
+ set_inverse_transl(vc, p, i); /* Update inverse translations */
|
|
|
set_inverse_trans_unicode(vc, p);
|
|
|
|
|
|
return err;
|