1 /* g/e.c
2 **
3 */
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <sys/stat.h>
7 
8 #include "all.h"
9 
10 #if 0
11 /* Image check.
12 */
13 struct {
14   c3_w nor_w;
15   c3_w sou_w;
16   c3_w mug_w[u3a_pages];
17 } u3K;
18 
19 /* _ce_check_page(): checksum page.
20 */
21 static c3_w
22 _ce_check_page(c3_w pag_w)
23 {
24   c3_w* mem_w = u3_Loom + (pag_w << u3a_page);
25   c3_w  mug_w = u3r_mug_words(mem_w, (1 << u3a_page));
26 
27   return mug_w;
28 }
29 
30 /* u3e_check(): compute a checksum on all memory within the watermarks.
31 */
32 void
33 u3e_check(c3_c* cap_c)
34 {
35   c3_w nor_w = 0;
36   c3_w sou_w = 0;
37 
38   {
39     c3_w nwr_w, swu_w;
40 
41     u3m_water(&nwr_w, &swu_w);
42 
43     nor_w = (nwr_w + ((1 << u3a_page) - 1)) >> u3a_page;
44     sou_w = (swu_w + ((1 << u3a_page) - 1)) >> u3a_page;
45   }
46 
47   /* Count dirty pages.
48   */
49   {
50     c3_w i_w, sum_w, mug_w;
51 
52     sum_w = 0;
53     for ( i_w = 0; i_w < nor_w; i_w++ ) {
54       mug_w = _ce_check_page(i_w);
55       if ( strcmp(cap_c, "boot") ) {
56         c3_assert(mug_w == u3K.mug_w[i_w]);
57       }
58       sum_w += mug_w;
59     }
60     for ( i_w = 0; i_w < sou_w; i_w++ ) {
61       mug_w = _ce_check_page((u3a_pages - (i_w + 1)));
62       if ( strcmp(cap_c, "boot") ) {
63         c3_assert(mug_w == u3K.mug_w[(u3a_pages - (i_w + 1))]);
64       }
65       sum_w += mug_w;
66     }
67     printf("%s: sum %x (%x, %x)\r\n", cap_c, sum_w, nor_w, sou_w);
68   }
69 }
70 
71 /* _ce_maplloc(): crude off-loom allocator.
72 */
73 static void*
74 _ce_maplloc(c3_w len_w)
75 {
76   void* map_v;
77 
78   map_v = mmap(0,
79                len_w,
80                (PROT_READ | PROT_WRITE),
81                (MAP_ANON | MAP_PRIVATE),
82                -1, 0);
83 
84   if ( -1 == (c3_ps)map_v ) {
85     c3_assert(0);
86   }
87   else {
88     c3_w* map_w = map_v;
89 
90     map_w[0] = len_w;
91 
92     return map_w + 1;
93   }
94 }
95 
96 /* _ce_mapfree(): crude off-loom allocator.
97 */
98 static void
99 _ce_mapfree(void* map_v)
100 {
101   c3_w* map_w = map_v;
102   c3_i res_i;
103 
104   map_w -= 1;
105   res_i = munmap(map_w, map_w[0]);
106 
107   c3_assert(0 == res_i);
108 }
109 #endif
110 
111 /* u3e_fault(): handle a memory event with libsigsegv protocol.
112 */
113 c3_i
u3e_fault(void * adr_v,c3_i ser_i)114 u3e_fault(void* adr_v, c3_i ser_i)
115 {
116   //  Let the stack overflow handler run.
117   if ( 0 == ser_i ) {
118     return 0;
119   }
120 
121   c3_w* adr_w = (c3_w*) adr_v;
122 
123   if ( (adr_w < u3_Loom) || (adr_w >= (u3_Loom + u3a_words)) ) {
124     fprintf(stderr, "address %p out of loom!\r\n", adr_v);
125     fprintf(stderr, "loom: [%p : %p)\r\n", u3_Loom, u3_Loom + u3a_words);
126     c3_assert(0);
127     return 0;
128   }
129   else {
130     c3_w off_w = (adr_w - u3_Loom);
131     c3_w pag_w = off_w >> u3a_page;
132     c3_w blk_w = (pag_w >> 5);
133     c3_w bit_w = (pag_w & 31);
134 
135 #if 0
136     if ( pag_w == 131041 ) {
137       printf("dirty page %d (at %p); unprotecting %p to %p\r\n",
138               pag_w,
139               adr_v,
140               (u3_Loom + (pag_w << u3a_page)),
141               (u3_Loom + (pag_w << u3a_page) + (1 << u3a_page)));
142     }
143 #endif
144     if ( 0 != (u3P.dit_w[blk_w] & (1 << bit_w)) ) {
145       fprintf(stderr, "strange page: %d, at %p, off %x\r\n",
146                       pag_w, adr_w, off_w);
147       abort();
148     }
149 
150     c3_assert(0 == (u3P.dit_w[blk_w] & (1 << bit_w)));
151     u3P.dit_w[blk_w] |= (1 << bit_w);
152 
153     if ( -1 == mprotect((void *)(u3_Loom + (pag_w << u3a_page)),
154                         (1 << (u3a_page + 2)),
155                         (PROT_READ | PROT_WRITE)) )
156     {
157       perror("mprotect");
158       c3_assert(0);
159       return 0;
160     }
161   }
162   return 1;
163 }
164 
165 /* _ce_image_open(): open or create image.
166 */
167 static c3_o
_ce_image_open(u3e_image * img_u,c3_o nuu_o)168 _ce_image_open(u3e_image* img_u, c3_o nuu_o)
169 {
170   c3_i mod_i = _(nuu_o) ? (O_RDWR | O_CREAT) : O_RDWR;
171   c3_c ful_c[8193];
172 
173   snprintf(ful_c, 8192, "%s", u3P.dir_c);
174   mkdir(ful_c, 0700);
175 
176   snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c);
177   mkdir(ful_c, 0700);
178 
179   snprintf(ful_c, 8192, "%s/.urb/chk", u3P.dir_c);
180   mkdir(ful_c, 0700);
181 
182   snprintf(ful_c, 8192, "%s/.urb/chk/%s.bin", u3P.dir_c, img_u->nam_c);
183   if ( -1 == (img_u->fid_i = open(ful_c, mod_i, 0666)) ) {
184     perror(ful_c);
185     return c3n;
186   }
187   else {
188     struct stat buf_u;
189 
190     if ( -1 == fstat(img_u->fid_i, &buf_u) ) {
191       perror(ful_c);
192       c3_assert(0);
193       return c3n;
194     }
195     else {
196       c3_d siz_d = buf_u.st_size;
197       c3_d pgs_d = (siz_d + (c3_d)((1 << (u3a_page + 2)) - 1)) >>
198                    (c3_d)(u3a_page + 2);
199 
200       if ( c3y == nuu_o ) {
201         if ( siz_d ) {
202           c3_assert(0);
203           return c3n;
204         }
205         return c3y;
206       }
207       else {
208         if ( siz_d != (pgs_d << (c3_d)(u3a_page + 2)) ) {
209           fprintf(stderr, "%s: corrupt size %" PRIx64 "\r\n", ful_c, siz_d);
210           return c3n;
211         }
212         img_u->pgs_w = (c3_w) pgs_d;
213         c3_assert(pgs_d == (c3_d)img_u->pgs_w);
214 
215         return c3y;
216       }
217     }
218   }
219 }
220 
221 /* _ce_patch_write_control(): write control block file.
222 */
223 static void
_ce_patch_write_control(u3_ce_patch * pat_u)224 _ce_patch_write_control(u3_ce_patch* pat_u)
225 {
226   c3_w len_w = sizeof(u3e_control) +
227                (pat_u->con_u->pgs_w * sizeof(u3e_line));
228 
229   if ( len_w != write(pat_u->ctl_i, pat_u->con_u, len_w) ) {
230     c3_assert(0);
231   }
232 }
233 
234 /* _ce_patch_read_control(): read control block file.
235 */
236 static c3_o
_ce_patch_read_control(u3_ce_patch * pat_u)237 _ce_patch_read_control(u3_ce_patch* pat_u)
238 {
239   c3_w len_w;
240 
241   c3_assert(0 == pat_u->con_u);
242   {
243     struct stat buf_u;
244 
245     if ( -1 == fstat(pat_u->ctl_i, &buf_u) ) {
246       c3_assert(0);
247       return c3n;
248     }
249     len_w = (c3_w) buf_u.st_size;
250   }
251 
252   pat_u->con_u = malloc(len_w);
253   if ( (len_w != read(pat_u->ctl_i, pat_u->con_u, len_w)) ||
254         (len_w != sizeof(u3e_control) +
255                   (pat_u->con_u->pgs_w * sizeof(u3e_line))) )
256   {
257     free(pat_u->con_u);
258     pat_u->con_u = 0;
259     return c3n;
260   }
261   return c3y;
262 }
263 
264 /* _ce_patch_create(): create patch files.
265 */
266 static void
_ce_patch_create(u3_ce_patch * pat_u)267 _ce_patch_create(u3_ce_patch* pat_u)
268 {
269   c3_c ful_c[8193];
270 
271   snprintf(ful_c, 8192, "%s", u3P.dir_c);
272   mkdir(ful_c, 0700);
273 
274   snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c);
275   mkdir(ful_c, 0700);
276 
277   snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c);
278   if ( -1 == (pat_u->ctl_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0666)) ) {
279     c3_assert(0);
280   }
281 
282   snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c);
283   if ( -1 == (pat_u->mem_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0666)) ) {
284     c3_assert(0);
285   }
286 }
287 
288 /* _ce_patch_delete(): delete a patch.
289 */
290 static void
_ce_patch_delete(void)291 _ce_patch_delete(void)
292 {
293   c3_c ful_c[8193];
294 
295   snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c);
296   unlink(ful_c);
297 
298   snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c);
299   unlink(ful_c);
300 }
301 
302 /* _ce_patch_verify(): check patch data mug.
303 */
304 static c3_o
_ce_patch_verify(u3_ce_patch * pat_u)305 _ce_patch_verify(u3_ce_patch* pat_u)
306 {
307   c3_w i_w;
308 
309   for ( i_w = 0; i_w < pat_u->con_u->pgs_w; i_w++ ) {
310     c3_w pag_w = pat_u->con_u->mem_u[i_w].pag_w;
311     c3_w mug_w = pat_u->con_u->mem_u[i_w].mug_w;
312     c3_w mem_w[1 << u3a_page];
313 
314     if ( -1 == lseek(pat_u->mem_i, (i_w << (u3a_page + 2)), SEEK_SET) ) {
315       perror("seek");
316       c3_assert(0);
317       return c3n;
318     }
319     if ( -1 == read(pat_u->mem_i, mem_w, (1 << (u3a_page + 2))) ) {
320       perror("read");
321       c3_assert(0);
322       return c3n;
323     }
324     {
325       c3_w nug_w = u3r_mug_words(mem_w, (1 << u3a_page));
326 
327       if ( mug_w != nug_w ) {
328         printf("_ce_patch_verify: mug mismatch %d/%d; (%x, %x)\r\n",
329             pag_w, i_w, mug_w, nug_w);
330         c3_assert(0);
331         return c3n;
332       }
333 #if 0
334       else {
335         printf("verify: patch %d/%d, %x\r\n", pag_w, i_w, mug_w);
336       }
337 #endif
338     }
339   }
340   return c3y;
341 }
342 
343 /* _ce_patch_free(): free a patch.
344 */
345 static void
_ce_patch_free(u3_ce_patch * pat_u)346 _ce_patch_free(u3_ce_patch* pat_u)
347 {
348   free(pat_u->con_u);
349   close(pat_u->ctl_i);
350   close(pat_u->mem_i);
351   free(pat_u);
352 }
353 
354 /* _ce_patch_open(): open patch, if any.
355 */
356 static u3_ce_patch*
_ce_patch_open(void)357 _ce_patch_open(void)
358 {
359   u3_ce_patch* pat_u;
360   c3_c ful_c[8193];
361   c3_i ctl_i, mem_i;
362 
363   snprintf(ful_c, 8192, "%s", u3P.dir_c);
364   mkdir(ful_c, 0700);
365 
366   snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c);
367   mkdir(ful_c, 0700);
368 
369   snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c);
370   if ( -1 == (ctl_i = open(ful_c, O_RDWR)) ) {
371     return 0;
372   }
373 
374   snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c);
375   if ( -1 == (mem_i = open(ful_c, O_RDWR)) ) {
376     close(ctl_i);
377 
378     _ce_patch_delete();
379     return 0;
380   }
381   pat_u = malloc(sizeof(u3_ce_patch));
382   pat_u->ctl_i = ctl_i;
383   pat_u->mem_i = mem_i;
384   pat_u->con_u = 0;
385 
386   if ( c3n == _ce_patch_read_control(pat_u) ) {
387     close(pat_u->ctl_i);
388     close(pat_u->mem_i);
389     free(pat_u);
390 
391     _ce_patch_delete();
392     return 0;
393   }
394   if ( c3n == _ce_patch_verify(pat_u) ) {
395     _ce_patch_free(pat_u);
396     _ce_patch_delete();
397     return 0;
398   }
399   return pat_u;
400 }
401 
402 /* _ce_patch_write_page(): write a page of patch memory.
403 */
404 static void
_ce_patch_write_page(u3_ce_patch * pat_u,c3_w pgc_w,c3_w * mem_w)405 _ce_patch_write_page(u3_ce_patch* pat_u,
406                      c3_w         pgc_w,
407                      c3_w*        mem_w)
408 {
409   if ( -1 == lseek(pat_u->mem_i, (pgc_w << (u3a_page + 2)), SEEK_SET) ) {
410     c3_assert(0);
411   }
412   if ( (1 << (u3a_page + 2)) !=
413        write(pat_u->mem_i, mem_w, (1 << (u3a_page + 2))) )
414   {
415     c3_assert(0);
416   }
417 }
418 
419 /* _ce_patch_count_page(): count a page, producing new counter.
420 */
421 static c3_w
_ce_patch_count_page(c3_w pag_w,c3_w pgc_w)422 _ce_patch_count_page(c3_w pag_w,
423                      c3_w pgc_w)
424 {
425   c3_w blk_w = (pag_w >> 5);
426   c3_w bit_w = (pag_w & 31);
427 
428   if ( u3P.dit_w[blk_w] & (1 << bit_w) ) {
429     pgc_w += 1;
430   }
431   return pgc_w;
432 }
433 
434 /* _ce_patch_save_page(): save a page, producing new page counter.
435 */
436 static c3_w
_ce_patch_save_page(u3_ce_patch * pat_u,c3_w pag_w,c3_w pgc_w)437 _ce_patch_save_page(u3_ce_patch* pat_u,
438                     c3_w         pag_w,
439                     c3_w         pgc_w)
440 {
441   c3_w blk_w = (pag_w >> 5);
442   c3_w bit_w = (pag_w & 31);
443 
444   if ( u3P.dit_w[blk_w] & (1 << bit_w) ) {
445     c3_w* mem_w = u3_Loom + (pag_w << u3a_page);
446 
447     pat_u->con_u->mem_u[pgc_w].pag_w = pag_w;
448     pat_u->con_u->mem_u[pgc_w].mug_w = u3r_mug_words(mem_w,
449                                                        (1 << u3a_page));
450 
451 #if 0
452     printf("protect a: page %d\r\n", pag_w);
453 #endif
454     _ce_patch_write_page(pat_u, pgc_w, mem_w);
455 
456     if ( -1 == mprotect(u3_Loom + (pag_w << u3a_page),
457                         (1 << (u3a_page + 2)),
458                         PROT_READ) )
459     {
460       c3_assert(0);
461     }
462 
463     u3P.dit_w[blk_w] &= ~(1 << bit_w);
464     pgc_w += 1;
465   }
466   return pgc_w;
467 }
468 
469 /* _ce_patch_junk_page(): mark a page as junk.
470 */
471 static void
_ce_patch_junk_page(u3_ce_patch * pat_u,c3_w pag_w)472 _ce_patch_junk_page(u3_ce_patch* pat_u,
473                     c3_w         pag_w)
474 {
475   c3_w blk_w = (pag_w >> 5);
476   c3_w bit_w = (pag_w & 31);
477 
478   // printf("protect b: page %d\r\n", pag_w);
479   if ( -1 == mprotect(u3_Loom + (pag_w << u3a_page),
480                       (1 << (u3a_page + 2)),
481                       PROT_READ) )
482   {
483     c3_assert(0);
484   }
485   u3P.dit_w[blk_w] &= ~(1 << bit_w);
486 }
487 
488 /* u3e_dirty(): count dirty pages.
489 */
490 c3_w
u3e_dirty(void)491 u3e_dirty(void)
492 {
493   c3_w pgs_w = 0;
494   c3_w nor_w = 0;
495   c3_w sou_w = 0;
496 
497   /* Calculate number of saved pages, north and south.
498   */
499   {
500     c3_w nwr_w, swu_w;
501 
502     u3m_water(&nwr_w, &swu_w);
503 
504     nor_w = (nwr_w + ((1 << u3a_page) - 1)) >> u3a_page;
505     sou_w = (swu_w + ((1 << u3a_page) - 1)) >> u3a_page;
506   }
507   //  u3K.nor_w = nor_w;
508   //  u3K.sou_w = sou_w;
509 
510   /* Count dirty pages.
511   */
512   {
513     c3_w i_w;
514 
515     for ( i_w = 0; i_w < nor_w; i_w++ ) {
516       pgs_w = _ce_patch_count_page(i_w, pgs_w);
517     }
518     for ( i_w = 0; i_w < sou_w; i_w++ ) {
519       pgs_w = _ce_patch_count_page((u3a_pages - (i_w + 1)), pgs_w);
520     }
521   }
522   return pgs_w;
523 }
524 
525 /* _ce_patch_compose(): make and write current patch.
526 */
527 static u3_ce_patch*
_ce_patch_compose(void)528 _ce_patch_compose(void)
529 {
530   c3_w pgs_w = 0;
531   c3_w nor_w = 0;
532   c3_w sou_w = 0;
533 
534   /* Calculate number of saved pages, north and south.
535   */
536   {
537     c3_w nwr_w, swu_w;
538 
539     u3m_water(&nwr_w, &swu_w);
540 
541     nor_w = (nwr_w + ((1 << u3a_page) - 1)) >> u3a_page;
542     sou_w = (swu_w + ((1 << u3a_page) - 1)) >> u3a_page;
543   }
544   //  u3K.nor_w = nor_w;
545   //  u3K.sou_w = sou_w;
546 
547   /* Count dirty pages.
548   */
549   {
550     c3_w i_w;
551 
552     for ( i_w = 0; i_w < nor_w; i_w++ ) {
553       pgs_w = _ce_patch_count_page(i_w, pgs_w);
554     }
555     for ( i_w = 0; i_w < sou_w; i_w++ ) {
556       pgs_w = _ce_patch_count_page((u3a_pages - (i_w + 1)), pgs_w);
557     }
558   }
559 
560   if ( !pgs_w ) {
561     return 0;
562   }
563   else {
564     u3_ce_patch* pat_u = malloc(sizeof(u3_ce_patch));
565     c3_w i_w, pgc_w;
566 
567     _ce_patch_create(pat_u);
568     pat_u->con_u = malloc(sizeof(u3e_control) + (pgs_w * sizeof(u3e_line)));
569     pgc_w = 0;
570 
571     for ( i_w = 0; i_w < nor_w; i_w++ ) {
572       pgc_w = _ce_patch_save_page(pat_u, i_w, pgc_w);
573     }
574     for ( i_w = 0; i_w < sou_w; i_w++ ) {
575       pgc_w = _ce_patch_save_page(pat_u, (u3a_pages - (i_w + 1)), pgc_w);
576     }
577     for ( i_w = nor_w; i_w < (u3a_pages - sou_w); i_w++ ) {
578       _ce_patch_junk_page(pat_u, i_w);
579     }
580 
581     pat_u->con_u->nor_w = nor_w;
582     pat_u->con_u->sou_w = sou_w;
583     pat_u->con_u->pgs_w = pgc_w;
584 
585     _ce_patch_write_control(pat_u);
586     return pat_u;
587   }
588 }
589 
590 /* _ce_sync(): sync a file descriptor.
591 */
592 static void
_ce_sync(c3_i fid_i)593 _ce_sync(c3_i fid_i)
594 {
595 #if defined(U3_OS_linux)
596   fdatasync(fid_i);
597 #elif defined(U3_OS_osx)
598   fcntl(fid_i, F_FULLFSYNC);
599 #elif defined(U3_OS_bsd)
600   fsync(fid_i);
601 #else
602 # error "port: datasync"
603 #endif
604 }
605 
606 /* _ce_patch_sync(): make sure patch is synced to disk.
607 */
608 static void
_ce_patch_sync(u3_ce_patch * pat_u)609 _ce_patch_sync(u3_ce_patch* pat_u)
610 {
611   _ce_sync(pat_u->ctl_i);
612   _ce_sync(pat_u->mem_i);
613 }
614 
615 /* _ce_image_sync(): make sure image is synced to disk.
616 */
617 static void
_ce_image_sync(u3e_image * img_u)618 _ce_image_sync(u3e_image* img_u)
619 {
620   _ce_sync(img_u->fid_i);
621 }
622 
623 /* _ce_patch_apply(): apply patch to image.
624 */
625 static void
_ce_patch_apply(u3_ce_patch * pat_u)626 _ce_patch_apply(u3_ce_patch* pat_u)
627 {
628   c3_w i_w;
629 
630   //printf("image: nor_w %d, new %d\r\n", u3P.nor_u.pgs_w, pat_u->con_u->nor_w);
631   //printf("image: sou_w %d, new %d\r\n", u3P.sou_u.pgs_w, pat_u->con_u->sou_w);
632 
633   if ( u3P.nor_u.pgs_w > pat_u->con_u->nor_w ) {
634     ftruncate(u3P.nor_u.fid_i, u3P.nor_u.pgs_w << (u3a_page + 2));
635   }
636   u3P.nor_u.pgs_w = pat_u->con_u->nor_w;
637 
638   if ( u3P.sou_u.pgs_w > pat_u->con_u->sou_w ) {
639     ftruncate(u3P.sou_u.fid_i, u3P.sou_u.pgs_w << (u3a_page + 2));
640   }
641   u3P.sou_u.pgs_w = pat_u->con_u->sou_w;
642 
643   if ( (-1 == lseek(pat_u->mem_i, 0, SEEK_SET)) ||
644        (-1 == lseek(u3P.nor_u.fid_i, 0, SEEK_SET)) ||
645        (-1 == lseek(u3P.sou_u.fid_i, 0, SEEK_SET)) )
646   {
647     perror("apply: seek");
648     c3_assert(0);
649   }
650 
651   for ( i_w = 0; i_w < pat_u->con_u->pgs_w; i_w++ ) {
652     c3_w pag_w = pat_u->con_u->mem_u[i_w].pag_w;
653     c3_w mem_w[1 << u3a_page];
654     c3_i fid_i;
655     c3_w off_w;
656 
657     if ( pag_w < pat_u->con_u->nor_w ) {
658       fid_i = u3P.nor_u.fid_i;
659       off_w = pag_w;
660     }
661     else {
662       fid_i = u3P.sou_u.fid_i;
663       off_w = (u3a_pages - (pag_w + 1));
664     }
665 
666     if ( -1 == read(pat_u->mem_i, mem_w, (1 << (u3a_page + 2))) ) {
667       perror("apply: read");
668       c3_assert(0);
669     }
670     else {
671       if ( -1 == lseek(fid_i, (off_w << (u3a_page + 2)), SEEK_SET) ) {
672         perror("apply: lseek");
673         c3_assert(0);
674       }
675       if ( -1 == write(fid_i, mem_w, (1 << (u3a_page + 2))) ) {
676         perror("apply: write");
677         c3_assert(0);
678       }
679     }
680 #if 0
681     printf("apply: %d, %x\n", pag_w, u3r_mug_words(mem_w, (1 << u3a_page)));
682 #endif
683   }
684 }
685 
686 /* _ce_image_blit(): apply image to memory.
687 */
688 static void
_ce_image_blit(u3e_image * img_u,c3_w * ptr_w,c3_ws stp_ws)689 _ce_image_blit(u3e_image* img_u,
690                c3_w*        ptr_w,
691                c3_ws        stp_ws)
692 {
693   c3_w i_w;
694 
695   lseek(img_u->fid_i, 0, SEEK_SET);
696   for ( i_w=0; i_w < img_u->pgs_w; i_w++ ) {
697     if ( -1 == read(img_u->fid_i, ptr_w, (1 << (u3a_page + 2))) ) {
698       perror("read");
699       c3_assert(0);
700     }
701 #if 0
702     {
703       c3_w off_w = (ptr_w - u3_Loom);
704       c3_w pag_w = (off_w >> u3a_page);
705 
706       printf("blit: page %d, mug %x\r\n", pag_w,
707           u3r_mug_words(ptr_w, (1 << u3a_page)));
708     }
709 #endif
710     ptr_w += stp_ws;
711   }
712 }
713 
714 #if 0
715 /* _ce_image_fine(): compare image to memory.
716 */
717 static void
718 _ce_image_fine(u3e_image* img_u,
719                c3_w*        ptr_w,
720                c3_ws        stp_ws)
721 {
722   c3_w i_w;
723   c3_w buf_w[1 << u3a_page];
724 
725   lseek(img_u->fid_i, 0, SEEK_SET);
726   for ( i_w=0; i_w < img_u->pgs_w; i_w++ ) {
727     c3_w mem_w, fil_w;
728 
729     if ( -1 == read(img_u->fid_i, buf_w, (1 << (u3a_page + 2))) ) {
730       perror("read");
731       c3_assert(0);
732     }
733     mem_w = u3r_mug_words(ptr_w, (1 << u3a_page));
734     fil_w = u3r_mug_words(buf_w, (1 << u3a_page));
735 
736     if ( mem_w != fil_w ) {
737       c3_w pag_w = (ptr_w - u3_Loom) >> u3a_page;
738 
739       fprintf(stderr, "mismatch: page %d, mem_w %x, fil_w %x, K %x\r\n",
740                        pag_w,
741                        mem_w,
742                        fil_w,
743                        u3K.mug_w[pag_w]);
744       abort();
745     }
746     ptr_w += stp_ws;
747   }
748 }
749 #endif
750 
751 /* u3e_save(): save current changes.
752 */
753 void
u3e_save(void)754 u3e_save(void)
755 {
756   u3_ce_patch* pat_u;
757 
758   //  In dry-run mode, we never touch this stuff.
759   //
760   if ( u3C.wag_w & u3o_dryrun ) {
761     return;
762   }
763 
764   //  Write all dirty pages to disk; clear protection and dirty bits.
765   //
766   //  This has to block the main thread.  All further processing can happen
767   //  in a separate thread, though we can't save again till this completes.
768   //
769 
770   if ( !(pat_u = _ce_patch_compose()) ) {
771     return;
772   }
773 
774   //  Sync the patch files.
775   //
776   // u3a_print_memory("sync: save", 4096 * pat_u->con_u->pgs_w);
777   _ce_patch_sync(pat_u);
778 
779   //  Verify the patch - because why not?
780   //
781   // printf("_ce_patch_verify\r\n");
782   _ce_patch_verify(pat_u);
783 
784   //  Write the patch data into the image file.  Idempotent.
785   //
786   // printf("_ce_patch_apply\r\n");
787   _ce_patch_apply(pat_u);
788 
789 #if 0
790   {
791     _ce_image_fine(&u3P.nor_u,
792                    u3_Loom,
793                    (1 << u3a_page));
794 
795     _ce_image_fine(&u3P.sou_u,
796                    (u3_Loom + (1 << u3a_bits) - (1 << u3a_page)),
797                    -(1 << u3a_page));
798 
799     c3_assert(u3P.nor_u.pgs_w == u3K.nor_w);
800     c3_assert(u3P.sou_u.pgs_w == u3K.sou_w);
801   }
802 #endif
803 
804   //  Sync the image file.
805   //
806   // printf("_ce_image_sync\r\n");
807   _ce_image_sync(&u3P.nor_u);
808   _ce_image_sync(&u3P.sou_u);
809 
810   //  Delete the patchfile and free it.
811   //
812   // printf("_ce_patch_delete\r\n");
813   _ce_patch_delete();
814   // printf("_ce_patch_free\r\n");
815   _ce_patch_free(pat_u);
816 }
817 
818 /* u3e_live(): start the persistence system.
819 */
820 c3_o
u3e_live(c3_o nuu_o,c3_c * dir_c)821 u3e_live(c3_o nuu_o, c3_c* dir_c)
822 {
823   u3P.dir_c = dir_c;
824   u3P.nor_u.nam_c = "north";
825   u3P.sou_u.nam_c = "south";
826 
827 #if 0
828   if ( u3C.wag_w & u3o_dryrun ) {
829     return c3y;
830   } else
831 #endif
832   {
833     /* Open and apply any patches.
834     */
835     if ( _(nuu_o) ) {
836       if ( (c3n == _ce_image_open(&u3P.nor_u, c3y)) ||
837            (c3n == _ce_image_open(&u3P.sou_u, c3y)) )
838       {
839         printf("boot: image failed\r\n");
840         exit(1);
841       }
842     }
843     else {
844       u3_ce_patch* pat_u;
845 
846       /* Open image files.
847       */
848       {
849         if ( (c3n == _ce_image_open(&u3P.nor_u, c3n)) ||
850              (c3n == _ce_image_open(&u3P.sou_u, c3n)) )
851         {
852           fprintf(stderr, "boot: no image\r\n");
853           return u3e_live(c3y, dir_c);
854         }
855       }
856       /* Load any patch files; apply them to images.
857       */
858       if ( 0 != (pat_u = _ce_patch_open()) ) {
859         printf("_ce_patch_apply\r\n");
860         _ce_patch_apply(pat_u);
861 
862         printf("_ce_image_sync\r\n");
863         _ce_image_sync(&u3P.nor_u);
864         _ce_image_sync(&u3P.sou_u);
865 
866         printf("_ce_patch_delete\r\n");
867         _ce_patch_delete();
868         printf("_ce_patch_free\r\n");
869         _ce_patch_free(pat_u);
870       }
871 
872       /* Write image files to memory; reinstate protection.
873       */
874       {
875         _ce_image_blit(&u3P.nor_u,
876                        u3_Loom,
877                        (1 << u3a_page));
878 
879         _ce_image_blit(&u3P.sou_u,
880                        (u3_Loom + (1 << u3a_bits) - (1 << u3a_page)),
881                        -(1 << u3a_page));
882 
883         if ( 0 != mprotect((void *)u3_Loom, u3a_bytes, PROT_READ) ) {
884           perror("protect");
885           c3_assert(0);
886         }
887         printf("protected loom\r\n");
888       }
889 
890       /* If the images were empty, we are logically booting.
891       */
892       if ( (0 == u3P.nor_u.pgs_w) && (0 == u3P.sou_u.pgs_w) ) {
893         printf("live: logical boot\r\n");
894         nuu_o = c3y;
895       }
896       else {
897         u3a_print_memory("live: loaded",
898                          (u3P.nor_u.pgs_w + u3P.sou_u.pgs_w) << u3a_page);
899       }
900     }
901   }
902   return nuu_o;
903 }
904 
905