Changes in uspace/app/sysinst/sysinst.c [9b95b964:2c21595] in mainline
- File:
-
- 1 edited
-
uspace/app/sysinst/sysinst.c (modified) (23 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/sysinst/sysinst.c
r9b95b964 r2c21595 1 1 /* 2 * Copyright (c) 202 4Jiri Svoboda2 * Copyright (c) 2026 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 41 41 #include <errno.h> 42 42 #include <fdisk.h> 43 #include <fmgt.h> 44 #include <gfx/render.h> 45 #include <io/log.h> 43 46 #include <loc.h> 44 47 #include <stdio.h> … … 46 49 #include <str.h> 47 50 #include <str_error.h> 51 #include <system.h> 52 #include <ui/msgdialog.h> 53 #include <ui/ui.h> 54 #include <ui/window.h> 48 55 #include <vfs/vfs.h> 49 56 #include <vol.h> 50 57 51 #include "futil.h"52 58 #include "grub.h" 53 59 #include "rdimg.h" 54 60 #include "volume.h" 61 #include "sysinst.h" 62 63 #define NAME "sysinst" 55 64 56 65 /** Device to install to … … 63 72 */ 64 73 #define DEFAULT_DEV_0 "devices/\\hw\\sys\\00:01.1\\c0d0" 65 #define DEFAULT_DEV_1 "devices/\\hw\\sys\\00:01.0\\ata1\\c0d0" 74 #define DEFAULT_DEV_1 "devices/\\hw\\sys\\ide1\\c0d0" 75 #define DEFAULT_DEV_2 "devices/\\hw\\sys\\00:01.0\\ide1\\c0d0" 66 76 //#define DEFAULT_DEV "devices/\\hw\\pci0\\00:01.2\\uhci_rh\\usb01_a1\\mass-storage0\\l0" 77 /** Index of partition which we must install to (hardwired in load.cfg) */ 78 #define INST_PART_IDX 1 79 /* File system type cannot be changed without modifying core.img */ 80 #define INST_FSTYPE fs_ext4 67 81 /** Volume label for the new file system */ 68 82 #define INST_VOL_LABEL "HelenOS" … … 77 91 #define CD_MOUNT_POINT "/vol/" CD_VOL_LABEL 78 92 79 #define BOOT_FILES_SRC CD_MOUNT_POINT 93 #define BOOT_FILES_SRC CD_MOUNT_POINT "/boot" 80 94 #define BOOT_BLOCK_IDX 0 /* MBR */ 95 96 #define CFG_FILES_SRC "/cfg" 97 #define CFG_FILES_DEST MOUNT_POINT 81 98 82 99 static const char *default_devs[] = { 83 100 DEFAULT_DEV_0, 84 101 DEFAULT_DEV_1, 102 DEFAULT_DEV_2, 85 103 NULL 86 104 }; … … 92 110 }; 93 111 112 static fibril_mutex_t shutdown_lock; 113 static fibril_condvar_t shutdown_cv; 114 static bool shutdown_stopped; 115 static bool shutdown_failed; 116 117 static void sysinst_shutdown_complete(void *); 118 static void sysinst_shutdown_failed(void *); 119 120 static system_cb_t sysinst_system_cb = { 121 .shutdown_complete = sysinst_shutdown_complete, 122 .shutdown_failed = sysinst_shutdown_failed 123 }; 124 125 static void wnd_close(ui_window_t *, void *); 126 static errno_t bg_wnd_paint(ui_window_t *, void *); 127 128 static ui_window_cb_t bg_window_cb = { 129 .close = wnd_close, 130 .paint = bg_wnd_paint 131 }; 132 133 static ui_window_cb_t progress_window_cb = { 134 .close = wnd_close 135 }; 136 137 static void sysinst_confirm_button(ui_msg_dialog_t *, void *, unsigned); 138 static void sysinst_confirm_close(ui_msg_dialog_t *, void *); 139 140 static ui_msg_dialog_cb_t sysinst_confirm_cb = { 141 .button = sysinst_confirm_button, 142 .close = sysinst_confirm_close 143 }; 144 145 static void sysinst_upgrade_confirm_button(ui_msg_dialog_t *, void *, unsigned); 146 static void sysinst_upgrade_confirm_close(ui_msg_dialog_t *, void *); 147 148 static ui_msg_dialog_cb_t sysinst_upgrade_confirm_cb = { 149 .button = sysinst_upgrade_confirm_button, 150 .close = sysinst_upgrade_confirm_close 151 }; 152 153 static errno_t sysinst_restart_dlg_create(sysinst_t *); 154 static void sysinst_restart_dlg_button(ui_msg_dialog_t *, void *, unsigned); 155 static void sysinst_restart_dlg_close(ui_msg_dialog_t *, void *); 156 157 static ui_msg_dialog_cb_t sysinst_restart_dlg_cb = { 158 .button = sysinst_restart_dlg_button, 159 .close = sysinst_restart_dlg_close 160 }; 161 162 static int sysinst_start(sysinst_t *); 163 static errno_t sysinst_restart(sysinst_t *); 164 static void sysinst_progress_destroy(sysinst_progress_t *); 165 static void sysinst_progress(sysinst_t *, const char *); 166 static void sysinst_action(sysinst_t *, const char *); 167 static void sysinst_error(sysinst_t *, const char *); 168 static void sysinst_debug(sysinst_t *, const char *); 169 170 static fmgt_exists_action_t sysinst_fmgt_exists_query(void *, fmgt_exists_t *); 171 static void sysinst_fmgt_action(void *, fmgt_action_t, const char *, 172 const char *); 173 static void sysinst_fmgt_progress(void *, fmgt_progress_t *); 174 static errno_t sysinst_eject_dev(sysinst_t *, service_id_t); 175 static errno_t sysinst_eject_phys_by_mp(sysinst_t *, const char *); 176 static errno_t sysinst_upgrade_confirm_create(sysinst_t *); 177 178 static fmgt_cb_t sysinst_fmgt_cb = { 179 .exists_query = sysinst_fmgt_exists_query, 180 .action = sysinst_fmgt_action, 181 .progress = sysinst_fmgt_progress 182 }; 183 184 static void sysinst_error_msg_button(ui_msg_dialog_t *, void *, unsigned); 185 static void sysinst_error_msg_close(ui_msg_dialog_t *, void *); 186 187 static ui_msg_dialog_cb_t sysinst_error_msg_cb = { 188 .button = sysinst_error_msg_button, 189 .close = sysinst_error_msg_close 190 }; 191 192 /** Close window. 193 * 194 * @param window Window 195 * @param arg Argument (sysinst_t *) 196 */ 197 static void wnd_close(ui_window_t *window, void *arg) 198 { 199 (void)window; 200 (void)arg; 201 } 202 203 /** Paint background window. 204 * 205 * @param window Window 206 * @param arg Argument (sysinst_t *) 207 */ 208 static errno_t bg_wnd_paint(ui_window_t *window, void *arg) 209 { 210 sysinst_t *sysinst = (sysinst_t *)arg; 211 gfx_rect_t app_rect; 212 gfx_context_t *gc; 213 errno_t rc; 214 215 gc = ui_window_get_gc(window); 216 217 rc = gfx_set_color(gc, sysinst->bg_color); 218 if (rc != EOK) 219 return rc; 220 221 ui_window_get_app_rect(window, &app_rect); 222 223 rc = gfx_fill_rect(gc, &app_rect); 224 if (rc != EOK) 225 return rc; 226 227 rc = gfx_update(gc); 228 if (rc != EOK) 229 return rc; 230 231 return EOK; 232 } 233 234 /** Installation confirm dialog OK button press. 235 * 236 * @param dialog Message dialog 237 * @param arg Argument (sysinst_t *) 238 * @param btn Button number 239 * @param earg Entry argument 240 */ 241 static void sysinst_confirm_button(ui_msg_dialog_t *dialog, void *arg, 242 unsigned btn) 243 { 244 sysinst_t *sysinst = (sysinst_t *) arg; 245 246 ui_msg_dialog_destroy(dialog); 247 248 switch (btn) { 249 case 0: 250 /* OK */ 251 sysinst_start(sysinst); 252 break; 253 default: 254 /* Cancel */ 255 ui_quit(sysinst->ui); 256 break; 257 } 258 } 259 260 /** Installation confirm dialog close request. 261 * 262 * @param dialog Message dialog 263 * @param arg Argument (sysinst_t *) 264 */ 265 static void sysinst_confirm_close(ui_msg_dialog_t *dialog, void *arg) 266 { 267 sysinst_t *sysinst = (sysinst_t *) arg; 268 269 ui_msg_dialog_destroy(dialog); 270 ui_quit(sysinst->ui); 271 } 272 273 /** Upgrade confirm dialog OK button press. 274 * 275 * @param dialog Message dialog 276 * @param arg Argument (sysinst_t *) 277 * @param btn Button number 278 * @param earg Entry argument 279 */ 280 static void sysinst_upgrade_confirm_button(ui_msg_dialog_t *dialog, void *arg, 281 unsigned btn) 282 { 283 sysinst_t *sysinst = (sysinst_t *) arg; 284 285 ui_msg_dialog_destroy(dialog); 286 287 switch (btn) { 288 case 0: 289 /* OK */ 290 fibril_mutex_lock(&sysinst->responded_lock); 291 sysinst->responded = true; 292 sysinst->quit = false; 293 fibril_mutex_unlock(&sysinst->responded_lock); 294 fibril_condvar_signal(&sysinst->responded_cv); 295 break; 296 default: 297 /* Cancel */ 298 fibril_mutex_lock(&sysinst->responded_lock); 299 sysinst->responded = true; 300 sysinst->quit = true; 301 fibril_mutex_unlock(&sysinst->responded_lock); 302 fibril_condvar_signal(&sysinst->responded_cv); 303 break; 304 } 305 } 306 307 /** Upgrade confirm dialog close request. 308 * 309 * @param dialog Message dialog 310 * @param arg Argument (sysinst_t *) 311 */ 312 static void sysinst_upgrade_confirm_close(ui_msg_dialog_t *dialog, void *arg) 313 { 314 sysinst_t *sysinst = (sysinst_t *) arg; 315 316 ui_msg_dialog_destroy(dialog); 317 ui_quit(sysinst->ui); 318 } 319 320 /** Restart system dialog OK button press. 321 * 322 * @param dialog Message dialog 323 * @param arg Argument (sysinst_t *) 324 * @param btn Button number 325 * @param earg Entry argument 326 */ 327 static void sysinst_restart_dlg_button(ui_msg_dialog_t *dialog, void *arg, 328 unsigned btn) 329 { 330 sysinst_t *sysinst = (sysinst_t *) arg; 331 332 ui_msg_dialog_destroy(dialog); 333 334 (void)sysinst; 335 336 switch (btn) { 337 case 0: 338 /* OK */ 339 sysinst_action(sysinst, "Ejecting installation media."); 340 (void)sysinst_eject_phys_by_mp(sysinst, CD_MOUNT_POINT); 341 (void)sysinst_restart(sysinst); 342 break; 343 default: 344 /* Cancel */ 345 ui_quit(sysinst->ui); 346 break; 347 } 348 } 349 350 /** Restat system dialog close request. 351 * 352 * @param dialog Message dialog 353 * @param arg Argument (sysinst_t *) 354 */ 355 static void sysinst_restart_dlg_close(ui_msg_dialog_t *dialog, void *arg) 356 { 357 sysinst_t *sysinst = (sysinst_t *) arg; 358 359 ui_msg_dialog_destroy(dialog); 360 ui_quit(sysinst->ui); 361 } 362 363 /** Installation error message dialog button press. 364 * 365 * @param dialog Message dialog 366 * @param arg Argument (sysinst_t *) 367 * @param bnum Button number 368 */ 369 static void sysinst_error_msg_button(ui_msg_dialog_t *dialog, 370 void *arg, unsigned bnum) 371 { 372 sysinst_t *sysinst = (sysinst_t *) arg; 373 374 ui_msg_dialog_destroy(dialog); 375 ui_quit(sysinst->ui); 376 } 377 378 /** Installation error message dialog close request. 379 * 380 * @param dialog Message dialog 381 * @param arg Argument (shutdown_dlg_t *) 382 */ 383 static void sysinst_error_msg_close(ui_msg_dialog_t *dialog, void *arg) 384 { 385 sysinst_t *sysinst = (sysinst_t *) arg; 386 387 ui_msg_dialog_destroy(dialog); 388 ui_quit(sysinst->ui); 389 } 390 391 /** Create error message dialog. 392 * 393 * @param sysinst System installer 394 * @return EOK on success or an error code 395 */ 396 static errno_t sysinst_error_msg_create(sysinst_t *sysinst) 397 { 398 ui_msg_dialog_params_t params; 399 ui_msg_dialog_t *dialog; 400 errno_t rc; 401 402 ui_msg_dialog_params_init(¶ms); 403 params.caption = "Error"; 404 params.text = sysinst->errmsg; 405 params.flags |= umdf_topmost | umdf_center; 406 407 rc = ui_msg_dialog_create(sysinst->ui, ¶ms, &dialog); 408 if (rc != EOK) 409 return rc; 410 411 ui_msg_dialog_set_cb(dialog, &sysinst_error_msg_cb, (void *)sysinst); 412 413 return EOK; 414 } 415 416 /** Called when fmgt hits an existing file while copying. 417 * 418 * @param arg Argument (sysinst_t *) 419 * @param exists Information about existing file 420 * @return Existing file recovery action 421 */ 422 fmgt_exists_action_t sysinst_fmgt_exists_query(void *arg, fmgt_exists_t *exists) 423 { 424 sysinst_t *sysinst = (sysinst_t *)arg; 425 426 (void)sysinst; 427 (void)exists->fname; 428 429 sysinst_action(sysinst, exists->fname); 430 431 /* 432 * Before starting fmgt operation, the caller would specify 433 * whether to overwrite existing files. 434 */ 435 if (sysinst->overwrite) 436 return fmgt_exr_overwrite; 437 else 438 return fmgt_exr_skip; 439 } 440 441 /** Called when fmgt is starting to perform action on a file. 442 * 443 * @param arg Argument (sysinst_t *) 444 * @param action Action being performed 445 * @param src Source or only path 446 * @param dest Destination path or @c NULL 447 */ 448 static void sysinst_fmgt_action(void *arg, fmgt_action_t action, 449 const char *src, const char *dest) 450 { 451 sysinst_t *sysinst = (sysinst_t *)arg; 452 char buf[128]; 453 454 (void)src; 455 456 switch (action) { 457 case fmgt_ac_create: 458 snprintf(buf, sizeof(buf), "Creating %s.", src); 459 sysinst_action(sysinst, buf); 460 break; 461 case fmgt_ac_copy: 462 snprintf(buf, sizeof(buf), "Copying %s.", dest); 463 sysinst_action(sysinst, buf); 464 break; 465 default: 466 break; 467 } 468 } 469 470 /** Called by fmgt to update on progress. 471 * 472 * @param arg Argument (sysinst_t *) 473 * @param src Source path 474 * @param dest Destination path 475 */ 476 static void sysinst_fmgt_progress(void *arg, fmgt_progress_t *progress) 477 { 478 sysinst_t *sysinst = (sysinst_t *)arg; 479 char buf[128]; 480 481 snprintf(buf, sizeof(buf), "Copied %s files, %s; " 482 "current file: %s done.", progress->total_procf, 483 progress->total_procb, progress->curf_percent); 484 sysinst_progress(sysinst, buf); 485 } 486 487 /** System shutdown complete. 488 * 489 * @param arg Argument (shutdown_t *) 490 */ 491 static void sysinst_shutdown_complete(void *arg) 492 { 493 (void)arg; 494 495 fibril_mutex_lock(&shutdown_lock); 496 shutdown_stopped = true; 497 shutdown_failed = false; 498 fibril_condvar_broadcast(&shutdown_cv); 499 fibril_mutex_unlock(&shutdown_lock); 500 } 501 502 /** System shutdown failed. 503 * 504 * @param arg Argument (not used) 505 */ 506 static void sysinst_shutdown_failed(void *arg) 507 { 508 (void)arg; 509 510 fibril_mutex_lock(&shutdown_lock); 511 shutdown_stopped = true; 512 shutdown_failed = true; 513 fibril_condvar_broadcast(&shutdown_cv); 514 fibril_mutex_unlock(&shutdown_lock); 515 } 516 94 517 /** Check the if the destination device exists. 95 518 * … … 111 534 } 112 535 113 /** Label the destination device. 114 * 115 * @param dev Disk device to label 116 * @param psvc_id Place to store service ID of the created partition 117 * 118 * @return EOK on success or an error code 119 */ 120 static errno_t sysinst_label_dev(const char *dev, service_id_t *psvc_id) 121 { 122 fdisk_t *fdisk; 123 fdisk_dev_t *fdev; 536 /** Find existing OS partition. 537 * 538 * @param sysinst System installer 539 * @param fdev Destination device 540 * @param rpart Place to store pointer to partition 541 * 542 * @return EOK on success or an error code 543 */ 544 static errno_t sysinst_existing_os_part_find(sysinst_t *sysinst, 545 fdisk_dev_t *fdev, fdisk_part_t **rpart) 546 { 547 fdisk_part_t *part; 548 fdisk_part_info_t pinfo; 549 errno_t rc; 550 551 sysinst_debug(sysinst, "sysinst_existing_os_part_find(): walk partitions"); 552 553 part = fdisk_part_first(fdev); 554 while (part != NULL) { 555 rc = fdisk_part_get_info(part, &pinfo); 556 if (rc != EOK) { 557 sysinst_error(sysinst, 558 "Error getting partition information."); 559 goto error; 560 } 561 562 if (pinfo.index == INST_PART_IDX && pinfo.pkind == lpk_primary) 563 break; 564 565 part = fdisk_part_next(part); 566 } 567 568 /* Partition with index INST_PART_IDX not found? */ 569 if (part == NULL) 570 return ENOENT; 571 572 /* Correct file system type? */ 573 if (pinfo.fstype != INST_FSTYPE) { 574 /* Not a usable existing partition. */ 575 return ENOENT; 576 } 577 578 sysinst_debug(sysinst, "sysinst_existing_os_part_find(): OK"); 579 sysinst->psvc_id = pinfo.svc_id; 580 *rpart = part; 581 return EOK; 582 error: 583 return rc; 584 } 585 586 /** Create installation partition. 587 * 588 * @param sysinst System installer 589 * @param fdev Destination device 590 * 591 * @return EOK on success or an error code 592 */ 593 static errno_t sysinst_inst_part_create(sysinst_t *sysinst, fdisk_dev_t *fdev) 594 { 124 595 fdisk_part_t *part; 125 596 fdisk_part_spec_t pspec; 126 597 fdisk_part_info_t pinfo; 127 598 capa_spec_t capa; 128 service_id_t sid; 129 errno_t rc; 130 131 printf("sysinst_label_dev(): get service ID '%s'\n", dev); 132 rc = loc_service_get_id(dev, &sid, 0); 133 if (rc != EOK) 134 return rc; 135 136 printf("sysinst_label_dev(): open device\n"); 137 138 rc = fdisk_create(&fdisk); 139 if (rc != EOK) { 140 printf("Error initializing fdisk.\n"); 141 return rc; 142 } 143 144 rc = fdisk_dev_open(fdisk, sid, &fdev); 145 if (rc != EOK) { 146 printf("Error opening device.\n"); 147 return rc; 148 } 149 150 printf("sysinst_label_dev(): create mount directory\n"); 151 152 rc = vfs_link_path(MOUNT_POINT, KIND_DIRECTORY, NULL); 153 if (rc != EOK) 154 return rc; 155 156 printf("sysinst_label_dev(): create label\n"); 157 158 rc = fdisk_label_create(fdev, lt_mbr); 159 if (rc != EOK) { 160 printf("Error creating label: %s.\n", str_error(rc)); 161 return rc; 162 } 163 164 printf("sysinst_label_dev(): create partition\n"); 599 errno_t rc; 600 601 sysinst_debug(sysinst, "sysinst_inst_part_create(): get maximum available block"); 165 602 166 603 rc = fdisk_part_get_max_avail(fdev, spc_pri, &capa); 167 604 if (rc != EOK) { 168 printf("Error getting available capacity: %s.\n", str_error(rc)); 169 return rc; 605 sysinst_error(sysinst, 606 "Error getting available capacity."); 607 goto error; 170 608 } 171 609 … … 173 611 pspec.capacity = capa; 174 612 pspec.pkind = lpk_primary; 175 pspec.fstype = fs_ext4; /* Cannot be changed without modifying core.img */613 pspec.fstype = INST_FSTYPE; /* Cannot be changed without modifying core.img */ 176 614 pspec.mountp = MOUNT_POINT; 615 pspec.index = INST_PART_IDX; /* Cannot be changed without modifying core.img */ 177 616 pspec.label = INST_VOL_LABEL; 178 617 179 618 rc = fdisk_part_create(fdev, &pspec, &part); 180 619 if (rc != EOK) { 181 printf("Error creating partition.\n"); 620 sysinst_error(sysinst, "Error creating partition."); 621 goto error; 622 } 623 624 rc = fdisk_part_get_info(part, &pinfo); 625 if (rc != EOK) { 626 sysinst_error(sysinst, "Error getting partition information."); 627 goto error; 628 } 629 630 sysinst_debug(sysinst, "sysinst_inst_part_create(): OK"); 631 sysinst->psvc_id = pinfo.svc_id; 632 return EOK; 633 error: 634 return rc; 635 } 636 637 /** Label and mount the destination device. 638 * 639 * @param sysinst System installer 640 * @param dev Disk device to label 641 * 642 * @return EOK on success or an error code 643 */ 644 static errno_t sysinst_label_dev(sysinst_t *sysinst, const char *dev) 645 { 646 fdisk_t *fdisk = NULL; 647 fdisk_dev_t *fdev = NULL; 648 fdisk_part_t *part; 649 fdisk_label_info_t linfo; 650 bool create_label = false; 651 bool dir_created = false; 652 bool label_created = false; 653 service_id_t sid; 654 errno_t rc; 655 656 sysinst_debug(sysinst, "sysinst_label_dev(): get service ID"); 657 658 rc = loc_service_get_id(dev, &sid, 0); 659 if (rc != EOK) 660 goto error; 661 662 sysinst_debug(sysinst, "sysinst_label_dev(): open device"); 663 664 rc = fdisk_create(&fdisk); 665 if (rc != EOK) { 666 sysinst_error(sysinst, "Error initializing fdisk."); 667 goto error; 668 } 669 670 rc = fdisk_dev_open(fdisk, sid, &fdev); 671 if (rc != EOK) { 672 sysinst_error(sysinst, "Error opening device."); 673 goto error; 674 } 675 676 sysinst_debug(sysinst, "sysinst_label_dev(): create mount directory"); 677 678 rc = vfs_link_path(MOUNT_POINT, KIND_DIRECTORY, NULL); 679 if (rc != EOK) { 680 sysinst_error(sysinst, "Error creating mount directory."); 681 goto error; 682 } 683 684 dir_created = true; 685 686 sysinst_debug(sysinst, "sysinst_label_dev(): create label"); 687 688 rc = fdisk_label_get_info(fdev, &linfo); 689 if (rc != EOK) { 690 sysinst_error(sysinst, "Error analyzing device."); 691 goto error; 692 } 693 694 switch (linfo.ltype) { 695 case lt_none: 696 /* need to create label */ 697 create_label = true; 698 break; 699 case lt_mbr: 700 /* MBR label already present */ 701 break; 702 default: 703 /* a different type of label already present */ 704 sysinst_error(sysinst, "Disk contains unusable label."); 705 goto error; 706 } 707 708 /* Need to create label? */ 709 if (create_label) { 710 rc = fdisk_label_create(fdev, lt_mbr); 711 if (rc != EOK) { 712 sysinst_error(sysinst, "Error creating label."); 713 goto error; 714 } 715 } 716 717 label_created = true; 718 719 sysinst_debug(sysinst, "sysinst_label_dev(): create partition"); 720 721 /* Existing OS partition? */ 722 rc = sysinst_existing_os_part_find(sysinst, fdev, &part); 723 if (rc == EOK) { 724 /* Open dialog to confirm that user wants to upgrade. */ 725 rc = sysinst_upgrade_confirm_create(sysinst); 726 if (rc != EOK) { 727 sysinst_error(sysinst, "Cannot create window."); 728 goto error; 729 } 730 731 fibril_mutex_lock(&sysinst->responded_lock); 732 while (!sysinst->responded) 733 fibril_condvar_wait(&sysinst->responded_cv, 734 &sysinst->responded_lock); 735 fibril_mutex_unlock(&sysinst->responded_lock); 736 737 /* User decided not to upgrade existing installation? */ 738 if (sysinst->quit) { 739 (void)vfs_unlink_path(MOUNT_POINT); 740 return EOK; 741 } 742 743 /* Set mount point for installation partition. */ 744 rc = fdisk_part_set_mountp(part, MOUNT_POINT); 745 if (rc != EOK) { 746 sysinst_error(sysinst, "Cannot mount installation " 747 "partition."); 748 goto error; 749 } 750 751 /* performing OS upgrade */ 752 sysinst->oper = sio_upgrade; 753 if (sysinst->progress != NULL) { 754 (void)ui_label_set_text(sysinst->progress->label, 755 "Upgrading system. Please wait..."); 756 (void)ui_label_paint(sysinst->progress->label); 757 (void)ui_window_set_caption(sysinst->bgwindow, 758 "System Upgrade"); 759 } 760 } else { 761 /* Create installation partition. */ 762 rc = sysinst_inst_part_create(sysinst, fdev); 763 if (rc != EOK) 764 goto error; 765 766 /* performing initial OS installation */ 767 sysinst->oper = sio_install; 768 } 769 770 return EOK; 771 error: 772 if (label_created) 773 fdisk_label_destroy(fdev); 774 if (dir_created) 775 (void)vfs_unlink_path(MOUNT_POINT); 776 if (fdev != NULL) 777 fdisk_dev_close(fdev); 778 if (fdisk != NULL) 779 fdisk_destroy(fdisk); 780 return rc; 781 } 782 783 /** Finish/unmount destination device. 784 * 785 * @param sysinst System installer 786 * 787 * @return EOK on success or an error code 788 */ 789 static errno_t sysinst_finish_dev(sysinst_t *sysinst) 790 { 791 errno_t rc; 792 793 sysinst_debug(sysinst, "sysinst_finish_dev(): eject target volume"); 794 rc = sysinst_eject_dev(sysinst, sysinst->psvc_id); 795 if (rc != EOK) 182 796 return rc; 183 } 184 185 rc = fdisk_part_get_info(part, &pinfo); 186 if (rc != EOK) { 187 printf("Error getting partition information.\n"); 188 return rc; 189 } 190 191 printf("sysinst_label_dev(): OK\n"); 192 *psvc_id = pinfo.svc_id; 797 798 sysinst_debug(sysinst, "sysinst_finish_dev(): " 799 "deleting mount directory"); 800 (void)vfs_unlink_path(MOUNT_POINT); 801 193 802 return EOK; 194 803 } … … 196 805 /** Set up system volume structure. 197 806 * 198 * @return EOK on success or an error code 199 */ 200 static errno_t sysinst_setup_sysvol(void) 807 * @param sysinst System installer 808 * @return EOK on success or an error code 809 */ 810 static errno_t sysinst_setup_sysvol(sysinst_t *sysinst) 201 811 { 202 812 errno_t rc; 203 813 char *path = NULL; 204 814 const char **cp; 815 fmgt_flist_t *flist = NULL; 205 816 int rv; 206 817 … … 214 825 215 826 rc = vfs_link_path(path, KIND_DIRECTORY, NULL); 216 if (rc != EOK ) {217 printf("Error creating directory '%s'.\n", path);827 if (rc != EOK && rc != EEXIST) { 828 sysinst_error(sysinst, "Error creating directory."); 218 829 goto error; 219 830 } … … 227 838 path = NULL; 228 839 840 /* Copy initial configuration files */ 841 842 log_msg(LOG_DEFAULT, LVL_NOTE, 843 "sysinst_copy_boot_files(): copy initial configuration files"); 844 845 rc = fmgt_flist_create(&flist); 846 if (rc != EOK) 847 goto error; 848 849 rc = fmgt_flist_append(flist, CFG_FILES_SRC); 850 if (rc != EOK) 851 goto error; 852 853 /* Do not overwrite configuration files. */ 854 sysinst->overwrite = false; 855 rc = fmgt_copy(sysinst->fmgt, flist, CFG_FILES_DEST); 856 if (rc != EOK) { 857 sysinst_error(sysinst, "Error copying initial configuration " 858 "files."); 859 goto error; 860 } 861 862 fmgt_flist_destroy(flist); 863 log_msg(LOG_DEFAULT, LVL_NOTE, 864 "sysinst_copy_boot_files(): copy initial configuration files OK"); 229 865 return EOK; 230 866 error: 867 if (flist != NULL) 868 fmgt_flist_destroy(flist); 231 869 if (path != NULL) 232 870 free(path); … … 238 876 * @return EOK on success or an error code 239 877 */ 240 static errno_t sysinst_copy_boot_files(void) 241 { 242 errno_t rc; 243 244 printf("sysinst_copy_boot_files(): copy bootloader files\n"); 245 rc = futil_rcopy_contents(BOOT_FILES_SRC, MOUNT_POINT); 246 if (rc != EOK) 247 return rc; 248 249 printf("sysinst_copy_boot_files(): OK\n"); 878 static errno_t sysinst_copy_boot_files(sysinst_t *sysinst) 879 { 880 fmgt_flist_t *flist = NULL; 881 errno_t rc; 882 883 log_msg(LOG_DEFAULT, LVL_NOTE, 884 "sysinst_copy_boot_files(): copy bootloader files"); 885 rc = fmgt_flist_create(&flist); 886 if (rc != EOK) 887 goto error; 888 889 rc = fmgt_flist_append(flist, BOOT_FILES_SRC); 890 if (rc != EOK) 891 goto error; 892 893 /* Overwrite boot files with new ones during upgrade. */ 894 sysinst->overwrite = true; 895 rc = fmgt_copy(sysinst->fmgt, flist, MOUNT_POINT); 896 if (rc != EOK) { 897 sysinst_error(sysinst, "Error copying bootloader " 898 "files."); 899 goto error; 900 } 901 902 fmgt_flist_destroy(flist); 903 sysinst_debug(sysinst, "sysinst_copy_boot_files(): OK"); 250 904 return EOK; 905 error: 906 if (flist != NULL) 907 fmgt_flist_destroy(flist); 908 return rc; 251 909 } 252 910 253 911 /** Set up configuration in the initial RAM disk. 254 912 * 255 * @return EOK on success or an error code 256 */ 257 static errno_t sysinst_customize_initrd(void) 913 * @param sysinst System installer 914 * @return EOK on success or an error code 915 */ 916 static errno_t sysinst_customize_initrd(sysinst_t *sysinst) 258 917 { 259 918 errno_t rc; … … 267 926 rc = rd_img_open(MOUNT_POINT "/boot/initrd.img", &rdpath, &rd); 268 927 if (rc != EOK) { 269 printf("Error opening initial RAM disk image.\n");270 goto error; 271 } 272 273 rv = asprintf(&path, "%s%s", rdpath, "/cfg/ volsrv.sif");928 sysinst_error(sysinst, "Error opening initial RAM disk image."); 929 goto error; 930 } 931 932 rv = asprintf(&path, "%s%s", rdpath, "/cfg/initvol.sif"); 274 933 if (rv < 0) { 275 934 rc = ENOMEM; … … 277 936 } 278 937 279 printf("Configuring volume server.\n"); 938 sysinst_debug(sysinst, "Configuring volume server."); 939 280 940 rc = vol_volumes_create(path, &volumes); 281 941 if (rc != EOK) { 282 printf("Error creating volume server configuration.\n"); 942 sysinst_error(sysinst, 943 "Error creating volume server configuration."); 283 944 rc = EIO; 284 945 goto error; 285 946 } 286 947 287 printf("Configuring volume server: look up volume\n");948 sysinst_debug(sysinst, "Configuring volume server: look up volume"); 288 949 rc = vol_volume_lookup_ref(volumes, INST_VOL_LABEL, &volume); 289 950 if (rc != EOK) { 290 printf("Error creating volume server configuration.\n"); 951 sysinst_error(sysinst, 952 "Error creating volume server configuration."); 291 953 rc = EIO; 292 954 goto error; 293 955 } 294 956 295 printf("Configuring volume server: set mount point\n");957 sysinst_debug(sysinst, "Configuring volume server: set mount point"); 296 958 rc = vol_volume_set_mountp(volume, INST_VOL_MP); 297 959 if (rc != EOK) { 298 printf("Error creating system partition configuration.\n"); 960 sysinst_error(sysinst, 961 "Error creating system partition configuration."); 299 962 rc = EIO; 300 963 goto error; 301 964 } 302 965 303 printf("Configuring volume server: delete reference\n"); 966 rc = vol_volumes_sync(volumes); 967 if (rc != EOK) { 968 sysinst_error(sysinst, "Error saving volume confiuration."); 969 goto error; 970 } 971 972 log_msg(LOG_DEFAULT, LVL_NOTE, 973 "Configuring volume server: delete reference"); 304 974 vol_volume_del_ref(volume); 305 975 volume = NULL; 306 printf("Configuring volume server: destroy volumes object\n"); 976 log_msg(LOG_DEFAULT, LVL_NOTE, 977 "Configuring volume server: destroy volumes object"); 307 978 vol_volumes_destroy(volumes); 308 979 volumes = NULL; … … 310 981 rc = rd_img_close(rd); 311 982 if (rc != EOK) { 312 printf("Error closing initial RAM disk image.\n");983 sysinst_error(sysinst, "Error closing initial RAM disk image."); 313 984 rc = EIO; 314 985 goto error; … … 349 1020 } 350 1021 1022 /** Return file contents as a heap-allocated block of bytes. 1023 * 1024 * @param srcp File path 1025 * @param rdata Place to store pointer to data 1026 * @param rsize Place to store size of data 1027 * 1028 * @return EOK on success, ENOENT if failed to open file, EIO on other 1029 * I/O error, ENOMEM if out of memory 1030 */ 1031 static errno_t sysinst_get_file(const char *srcp, void **rdata, size_t *rsize) 1032 { 1033 int sf; 1034 size_t nr; 1035 errno_t rc; 1036 size_t fsize; 1037 char *data; 1038 vfs_stat_t st; 1039 1040 rc = vfs_lookup_open(srcp, WALK_REGULAR, MODE_READ, &sf); 1041 if (rc != EOK) 1042 return ENOENT; 1043 1044 if (vfs_stat(sf, &st) != EOK) { 1045 vfs_put(sf); 1046 return EIO; 1047 } 1048 1049 fsize = st.size; 1050 1051 data = calloc(fsize, 1); 1052 if (data == NULL) { 1053 vfs_put(sf); 1054 return ENOMEM; 1055 } 1056 1057 rc = vfs_read(sf, (aoff64_t []) { 0 }, data, fsize, &nr); 1058 if (rc != EOK || nr != fsize) { 1059 vfs_put(sf); 1060 free(data); 1061 return EIO; 1062 } 1063 1064 (void) vfs_put(sf); 1065 *rdata = data; 1066 *rsize = fsize; 1067 1068 return EOK; 1069 } 1070 351 1071 /** Copy boot blocks. 352 1072 * 353 1073 * Install Grub's boot blocks. 354 1074 * 1075 * @param sysinst System installer 355 1076 * @param devp Disk device 356 1077 * @return EOK on success or an error code 357 1078 */ 358 static errno_t sysinst_copy_boot_blocks( const char *devp)1079 static errno_t sysinst_copy_boot_blocks(sysinst_t *sysinst, const char *devp) 359 1080 { 360 1081 void *boot_img; … … 370 1091 errno_t rc; 371 1092 372 printf("sysinst_copy_boot_blocks: Read boot block image.\n"); 373 rc = futil_get_file(BOOT_FILES_SRC "/boot/grub/i386-pc/boot.img", 1093 log_msg(LOG_DEFAULT, LVL_NOTE, 1094 "sysinst_copy_boot_blocks: Read boot block image."); 1095 1096 rc = sysinst_get_file(BOOT_FILES_SRC "/grub/i386-pc/boot.img", 374 1097 &boot_img, &boot_img_size); 375 if (rc != EOK || boot_img_size != 512) 1098 if (rc != EOK || boot_img_size != 512) { 1099 sysinst_error(sysinst, "Error reading boot block image."); 376 1100 return EIO; 377 378 printf("sysinst_copy_boot_blocks: Read GRUB core image.\n"); 379 rc = futil_get_file(BOOT_FILES_SRC "/boot/grub/i386-pc/core.img", 1101 } 1102 1103 log_msg(LOG_DEFAULT, LVL_NOTE, 1104 "sysinst_copy_boot_blocks: Read GRUB core image."); 1105 1106 rc = sysinst_get_file(BOOT_FILES_SRC "/grub/i386-pc/core.img", 380 1107 &core_img, &core_img_size); 381 if (rc != EOK) 1108 if (rc != EOK) { 1109 sysinst_error(sysinst, "Error reading GRUB core image."); 382 1110 return EIO; 383 384 printf("sysinst_copy_boot_blocks: get service ID.\n"); 1111 } 1112 1113 log_msg(LOG_DEFAULT, LVL_NOTE, 1114 "sysinst_copy_boot_blocks: get service ID."); 1115 385 1116 rc = loc_service_get_id(devp, &sid, 0); 386 1117 if (rc != EOK) 387 1118 return rc; 388 1119 389 printf("sysinst_copy_boot_blocks: block_init.\n"); 1120 log_msg(LOG_DEFAULT, LVL_NOTE, 1121 "sysinst_copy_boot_blocks: block_init."); 1122 390 1123 rc = block_init(sid); 391 if (rc != EOK) 1124 if (rc != EOK) { 1125 sysinst_error(sysinst, "Error opening block device."); 392 1126 return rc; 393 394 printf("sysinst_copy_boot_blocks: get block size\n"); 1127 } 1128 1129 log_msg(LOG_DEFAULT, LVL_NOTE, 1130 "sysinst_copy_boot_blocks: get block size"); 1131 395 1132 rc = block_get_bsize(sid, &bsize); 396 if (rc != EOK) 1133 if (rc != EOK) { 1134 sysinst_error(sysinst, "Error getting block size."); 397 1135 return rc; 1136 } 398 1137 399 1138 if (bsize != 512) { 400 printf("Device block size != 512.\n");1139 sysinst_error(sysinst, "Device block size != 512."); 401 1140 return EIO; 402 1141 } 403 1142 404 printf("sysinst_copy_boot_blocks: read boot block\n"); 1143 log_msg(LOG_DEFAULT, LVL_NOTE, 1144 "sysinst_copy_boot_blocks: read boot block"); 1145 405 1146 rc = block_read_direct(sid, BOOT_BLOCK_IDX, 1, bbuf); 406 if (rc != EOK) 1147 if (rc != EOK) { 1148 sysinst_error(sysinst, "Error reading boot block."); 407 1149 return EIO; 1150 } 408 1151 409 1152 core_start = 16; … … 417 1160 --bl; 418 1161 if ((void *)bl < core_img) { 419 printf("No block terminator in core image.\n"); 1162 sysinst_error(sysinst, 1163 "No block terminator in core image."); 420 1164 return EIO; 421 1165 } … … 431 1175 set_unaligned_u64le(bbuf + grub_boot_machine_kernel_sector, core_start); 432 1176 433 printf("sysinst_copy_boot_blocks: write boot block\n"); 1177 log_msg(LOG_DEFAULT, LVL_NOTE, 1178 "sysinst_copy_boot_blocks: write boot block"); 1179 434 1180 rc = block_write_direct(sid, BOOT_BLOCK_IDX, 1, bbuf); 435 if (rc != EOK) 1181 if (rc != EOK) { 1182 sysinst_error(sysinst, "Error writing boot block."); 436 1183 return EIO; 437 438 printf("sysinst_copy_boot_blocks: write core blocks\n"); 1184 } 1185 1186 log_msg(LOG_DEFAULT, LVL_NOTE, 1187 "sysinst_copy_boot_blocks: write core blocks"); 1188 439 1189 /* XXX Must pad last block with zeros */ 440 1190 rc = block_write_direct(sid, core_start, core_blocks, core_img); 441 if (rc != EOK) 1191 if (rc != EOK) { 1192 sysinst_error(sysinst, "Error writing GRUB core blocks."); 442 1193 return EIO; 443 444 printf("sysinst_copy_boot_blocks: OK.\n"); 1194 } 1195 1196 log_msg(LOG_DEFAULT, LVL_NOTE, 1197 "sysinst_copy_boot_blocks: OK."); 1198 445 1199 return EOK; 446 1200 } … … 448 1202 /** Eject installation volume. 449 1203 * 450 * @param psvc_id Partition service ID 451 */ 452 static errno_t sysinst_eject_dev(service_id_t part_id) 1204 * @param sysinst System installer 1205 * @param part_id Partition service ID 1206 * @return EOK on success or an error code 1207 */ 1208 static errno_t sysinst_eject_dev(sysinst_t *sysinst, service_id_t part_id) 453 1209 { 454 1210 vol_t *vol = NULL; … … 457 1213 rc = vol_create(&vol); 458 1214 if (rc != EOK) { 459 printf("Error contacting volume service.\n");1215 sysinst_error(sysinst, "Error contacting volume service."); 460 1216 goto out; 461 1217 } 462 1218 463 rc = vol_part_eject(vol, part_id );464 if (rc != EOK) { 465 printf("Error ejecting volume.\n");1219 rc = vol_part_eject(vol, part_id, vef_none); 1220 if (rc != EOK) { 1221 sysinst_error(sysinst, "Error ejecting volume."); 466 1222 goto out; 467 1223 } … … 473 1229 } 474 1230 1231 /** Physically eject volume by mount point. 1232 * 1233 * @param sysinst System installer 1234 * @param path Mount point 1235 * @return EOK on success or an error code 1236 */ 1237 static errno_t sysinst_eject_phys_by_mp(sysinst_t *sysinst, const char *path) 1238 { 1239 vol_t *vol = NULL; 1240 sysarg_t part_id; 1241 errno_t rc; 1242 1243 log_msg(LOG_DEFAULT, LVL_NOTE, 1244 "sysinst_eject_phys_by_mp(%s)", path); 1245 1246 rc = vol_create(&vol); 1247 if (rc != EOK) { 1248 sysinst_error(sysinst, "Error contacting volume service."); 1249 goto out; 1250 } 1251 1252 log_msg(LOG_DEFAULT, LVL_NOTE, "vol_part_by_mp: mp='%s'\n", 1253 path); 1254 rc = vol_part_by_mp(vol, path, &part_id); 1255 if (rc != EOK) { 1256 sysinst_error(sysinst, 1257 "Error finding installation media mount point."); 1258 goto out; 1259 } 1260 1261 log_msg(LOG_DEFAULT, LVL_NOTE, "eject svc_id %lu", (unsigned long)part_id); 1262 rc = vol_part_eject(vol, part_id, vef_physical); 1263 if (rc != EOK) { 1264 sysinst_error(sysinst, "Error ejecting volume."); 1265 goto out; 1266 } 1267 1268 rc = EOK; 1269 out: 1270 vol_destroy(vol); 1271 return rc; 1272 } 1273 1274 /** Restart the system. 1275 * 1276 * @param sysinst System installer 1277 * @return EOK on success or an error code 1278 */ 1279 static errno_t sysinst_restart(sysinst_t *sysinst) 1280 { 1281 errno_t rc; 1282 system_t *system; 1283 1284 fibril_mutex_initialize(&shutdown_lock); 1285 fibril_condvar_initialize(&shutdown_cv); 1286 shutdown_stopped = false; 1287 shutdown_failed = false; 1288 1289 sysinst_action(sysinst, "Restarting the system."); 1290 1291 rc = system_open(SYSTEM_DEFAULT, &sysinst_system_cb, NULL, &system); 1292 if (rc != EOK) { 1293 sysinst_error(sysinst, 1294 "Failed opening system control service."); 1295 return rc; 1296 } 1297 1298 rc = system_restart(system); 1299 if (rc != EOK) { 1300 system_close(system); 1301 sysinst_error(sysinst, "Failed requesting system restart."); 1302 return rc; 1303 } 1304 1305 fibril_mutex_lock(&shutdown_lock); 1306 sysinst_debug(sysinst, "The system is shutting down..."); 1307 1308 while (!shutdown_stopped) 1309 fibril_condvar_wait(&shutdown_cv, &shutdown_lock); 1310 1311 if (shutdown_failed) { 1312 sysinst_error(sysinst, "Shutdown failed."); 1313 system_close(system); 1314 return rc; 1315 } 1316 1317 log_msg(LOG_DEFAULT, LVL_NOTE, 1318 "Shutdown complete. It is now safe to remove power."); 1319 1320 /* Sleep forever */ 1321 while (true) 1322 fibril_condvar_wait(&shutdown_cv, &shutdown_lock); 1323 1324 fibril_mutex_unlock(&shutdown_lock); 1325 1326 system_close(system); 1327 return 0; 1328 1329 } 1330 475 1331 /** Install system to a device. 476 1332 * 1333 * @parma sysinst System installer 477 1334 * @param dev Device to install to. 478 1335 * @return EOK on success or an error code 479 1336 */ 480 static errno_t sysinst_install(const char *dev) 481 { 482 errno_t rc; 483 service_id_t psvc_id; 484 485 rc = sysinst_label_dev(dev, &psvc_id); 1337 static errno_t sysinst_install(sysinst_t *sysinst, const char *dev) 1338 { 1339 errno_t rc; 1340 bool clean_dev = false; 1341 1342 sysinst_action(sysinst, "Creating device label and file system."); 1343 1344 rc = sysinst_label_dev(sysinst, dev); 1345 if (rc != EOK) 1346 goto error; 1347 if (sysinst->quit) 1348 return EOK; 1349 1350 clean_dev = true; 1351 1352 sysinst_action(sysinst, "Creating system directory structure."); 1353 rc = sysinst_setup_sysvol(sysinst); 1354 if (rc != EOK) 1355 goto error; 1356 1357 sysinst_action(sysinst, "Copying boot files."); 1358 rc = sysinst_copy_boot_files(sysinst); 1359 if (rc != EOK) 1360 goto error; 1361 1362 sysinst_action(sysinst, "Configuring the system."); 1363 rc = sysinst_customize_initrd(sysinst); 1364 if (rc != EOK) 1365 goto error; 1366 1367 sysinst_action(sysinst, "Finishing system volume."); 1368 rc = sysinst_finish_dev(sysinst); 1369 if (rc != EOK) 1370 goto error; 1371 1372 clean_dev = false; 1373 1374 sysinst_action(sysinst, "Installing boot blocks."); 1375 rc = sysinst_copy_boot_blocks(sysinst, dev); 486 1376 if (rc != EOK) 487 1377 return rc; 488 1378 489 printf("FS created and mounted. Creating system directory structure.\n");490 rc = sysinst_setup_sysvol();491 if (rc != EOK)492 return rc;493 494 printf("Directories created. Copying boot files.\n");495 rc = sysinst_copy_boot_files();496 if (rc != EOK)497 return rc;498 499 printf("Boot files done. Configuring the system.\n");500 rc = sysinst_customize_initrd();501 if (rc != EOK)502 return rc;503 504 printf("Boot files done. Installing boot blocks.\n");505 rc = sysinst_copy_boot_blocks(dev);506 if (rc != EOK)507 return rc;508 509 printf("Ejecting device.\n");510 rc = sysinst_eject_dev(psvc_id);511 if (rc != EOK)512 return rc;513 514 1379 return EOK; 515 } 516 517 int main(int argc, char *argv[]) 518 { 1380 error: 1381 if (clean_dev) 1382 (void)sysinst_finish_dev(sysinst); 1383 return rc; 1384 } 1385 1386 /** Installation fibril. 1387 * 1388 * @param arg Argument (sysinst_t *) 1389 * @return EOK on success or an error code 1390 */ 1391 static errno_t sysinst_install_fibril(void *arg) 1392 { 1393 sysinst_t *sysinst = (sysinst_t *)arg; 519 1394 unsigned i; 520 1395 errno_t rc; 1396 1397 (void)sysinst; 521 1398 522 1399 i = 0; … … 525 1402 if (rc == EOK) 526 1403 break; 1404 ++i; 527 1405 } 528 1406 529 1407 if (default_devs[i] == NULL) { 530 printf("Cannot determine installation device.\n"); 1408 sysinst_error(sysinst, "Cannot determine installation device."); 1409 rc = ENOENT; 1410 goto error; 1411 } 1412 1413 rc = sysinst_install(sysinst, default_devs[i]); 1414 if (rc != EOK) 1415 goto error; 1416 1417 sysinst_progress_destroy(sysinst->progress); 1418 sysinst->progress = NULL; 1419 1420 /* User decided not to upgrade system? */ 1421 if (sysinst->quit) { 1422 ui_quit(sysinst->ui); 1423 return EOK; 1424 } 1425 1426 rc = sysinst_restart_dlg_create(sysinst); 1427 if (rc != EOK) 1428 goto error; 1429 1430 return EOK; 1431 error: 1432 ui_lock(sysinst->ui); 1433 sysinst_progress_destroy(sysinst->progress); 1434 (void)sysinst_error_msg_create(sysinst); 1435 ui_unlock(sysinst->ui); 1436 return rc; 1437 } 1438 1439 /** Create installation progress window. 1440 * 1441 * @param sysinst System installer 1442 * @param rprogress Place to store pointer to new progress window 1443 * @return EOK on success or an error code 1444 */ 1445 static errno_t sysinst_progress_create(sysinst_t *sysinst, 1446 sysinst_progress_t **rprogress) 1447 { 1448 ui_wnd_params_t params; 1449 ui_window_t *window = NULL; 1450 gfx_rect_t rect; 1451 gfx_rect_t arect; 1452 ui_resource_t *ui_res; 1453 sysinst_progress_t *progress; 1454 ui_fixed_t *fixed = NULL; 1455 errno_t rc; 1456 1457 ui_wnd_params_init(¶ms); 1458 params.caption = "System Installation"; 1459 params.style &= ~ui_wds_titlebar; 1460 params.flags |= ui_wndf_topmost; 1461 params.placement = ui_wnd_place_center; 1462 if (ui_is_textmode(sysinst->ui)) { 1463 params.rect.p0.x = 0; 1464 params.rect.p0.y = 0; 1465 params.rect.p1.x = 64; 1466 params.rect.p1.y = 7; 1467 } else { 1468 params.rect.p0.x = 0; 1469 params.rect.p0.y = 0; 1470 params.rect.p1.x = 500; 1471 params.rect.p1.y = 90; 1472 } 1473 1474 progress = calloc(1, sizeof(sysinst_progress_t)); 1475 if (progress == NULL) { 1476 rc = ENOMEM; 1477 sysinst_error(sysinst, "Out of memory."); 1478 goto error; 1479 } 1480 1481 rc = ui_window_create(sysinst->ui, ¶ms, &window); 1482 if (rc != EOK) { 1483 sysinst_error(sysinst, "Error creating window."); 1484 goto error; 1485 } 1486 1487 ui_window_set_cb(window, &progress_window_cb, (void *)sysinst); 1488 1489 ui_res = ui_window_get_res(window); 1490 1491 rc = ui_fixed_create(&fixed); 1492 if (rc != EOK) { 1493 sysinst_error(sysinst, "Error creating fixed layout."); 1494 goto error; 1495 } 1496 1497 /* Installing/upgrading system line */ 1498 rc = ui_label_create(ui_res, "Installing system. Please wait...", 1499 &progress->label); 1500 if (rc != EOK) { 1501 sysinst_error(sysinst, "Error creating label."); 1502 goto error; 1503 } 1504 1505 ui_window_get_app_rect(window, &arect); 1506 1507 if (ui_is_textmode(sysinst->ui)) { 1508 rect.p0.x = arect.p0.x; 1509 rect.p0.y = arect.p0.y; 1510 rect.p1.x = arect.p1.x; 1511 rect.p1.y = 2; 1512 } else { 1513 rect.p0.x = arect.p0.x; 1514 rect.p0.y = arect.p0.y; 1515 rect.p1.x = arect.p1.x; 1516 rect.p1.y = 30; 1517 } 1518 ui_label_set_rect(progress->label, &rect); 1519 ui_label_set_halign(progress->label, gfx_halign_center); 1520 ui_label_set_valign(progress->label, gfx_valign_center); 1521 1522 rc = ui_fixed_add(fixed, ui_label_ctl(progress->label)); 1523 if (rc != EOK) { 1524 sysinst_error(sysinst, "Error adding control to layout."); 1525 ui_label_destroy(progress->label); 1526 progress->label = NULL; 1527 goto error; 1528 } 1529 1530 /* Action line */ 1531 rc = ui_label_create(ui_res, "", 1532 &progress->action); 1533 if (rc != EOK) { 1534 sysinst_error(sysinst, "Error creating label."); 1535 goto error; 1536 } 1537 1538 if (ui_is_textmode(sysinst->ui)) { 1539 rect.p0.x = arect.p0.x; 1540 rect.p0.y = 3; 1541 rect.p1.x = arect.p1.x; 1542 rect.p1.y = 4; 1543 } else { 1544 rect.p0.x = arect.p0.x; 1545 rect.p0.y = 40; 1546 rect.p1.x = arect.p1.x; 1547 rect.p1.y = 60; 1548 } 1549 ui_label_set_rect(progress->action, &rect); 1550 ui_label_set_halign(progress->action, gfx_halign_center); 1551 ui_label_set_valign(progress->action, gfx_valign_top); 1552 1553 rc = ui_fixed_add(fixed, ui_label_ctl(progress->action)); 1554 if (rc != EOK) { 1555 sysinst_error(sysinst, "Error adding control to layout."); 1556 ui_label_destroy(progress->label); 1557 progress->label = NULL; 1558 goto error; 1559 } 1560 1561 /* Progress line */ 1562 rc = ui_label_create(ui_res, "", 1563 &progress->progress); 1564 if (rc != EOK) { 1565 sysinst_error(sysinst, "Error creating label."); 1566 goto error; 1567 } 1568 1569 if (ui_is_textmode(sysinst->ui)) { 1570 rect.p0.x = arect.p0.x; 1571 rect.p0.y = 5; 1572 rect.p1.x = arect.p1.x; 1573 rect.p1.y = arect.p1.y; 1574 } else { 1575 rect.p0.x = arect.p0.x; 1576 rect.p0.y = 70; 1577 rect.p1.x = arect.p1.x; 1578 rect.p1.y = arect.p1.y; 1579 } 1580 ui_label_set_rect(progress->progress, &rect); 1581 ui_label_set_halign(progress->progress, gfx_halign_center); 1582 ui_label_set_valign(progress->progress, gfx_valign_top); 1583 1584 rc = ui_fixed_add(fixed, ui_label_ctl(progress->progress)); 1585 if (rc != EOK) { 1586 sysinst_error(sysinst, "Error adding control to layout."); 1587 ui_label_destroy(progress->label); 1588 progress->label = NULL; 1589 goto error; 1590 } 1591 1592 ui_window_add(window, ui_fixed_ctl(fixed)); 1593 fixed = NULL; 1594 1595 rc = ui_window_paint(window); 1596 if (rc != EOK) { 1597 sysinst_error(sysinst, "Error painting window."); 1598 goto error; 1599 } 1600 1601 progress->window = window; 1602 progress->fixed = fixed; 1603 *rprogress = progress; 1604 return EOK; 1605 error: 1606 if (progress != NULL && progress->fixed != NULL) 1607 ui_fixed_destroy(progress->fixed); 1608 if (window != NULL) 1609 ui_window_destroy(window); 1610 if (progress != NULL) 1611 free(progress); 1612 return rc; 1613 } 1614 1615 /** Destroy installation progress window. 1616 * 1617 * @param sysinst System installer 1618 * @param rprogress Place to store pointer to new progress window 1619 * @return EOK on success or an error code 1620 */ 1621 static void sysinst_progress_destroy(sysinst_progress_t *progress) 1622 { 1623 if (progress == NULL) 1624 return; 1625 1626 ui_window_destroy(progress->window); 1627 free(progress); 1628 } 1629 1630 /** Set current progress message. 1631 * 1632 * @param sysinst System installer 1633 * @param progress Progress text 1634 */ 1635 static void sysinst_progress(sysinst_t *sysinst, const char *progress) 1636 { 1637 log_msg(LOG_DEFAULT, LVL_NOTE, "%s", progress); 1638 1639 if (sysinst->progress == NULL) 1640 return; 1641 1642 ui_label_set_text(sysinst->progress->progress, progress); 1643 ui_label_paint(sysinst->progress->progress); 1644 } 1645 1646 /** Set current action message. 1647 * 1648 * @param sysinst System installer 1649 * @param action Action text 1650 */ 1651 static void sysinst_action(sysinst_t *sysinst, const char *action) 1652 { 1653 log_msg(LOG_DEFAULT, LVL_NOTE, "%s", action); 1654 1655 if (sysinst->progress == NULL) 1656 return; 1657 1658 ui_label_set_text(sysinst->progress->action, action); 1659 ui_label_paint(sysinst->progress->action); 1660 } 1661 1662 /** Set current error message. 1663 * 1664 * @param sysinst System installer 1665 * @param errmsg Error message 1666 */ 1667 static void sysinst_error(sysinst_t *sysinst, const char *errmsg) 1668 { 1669 str_cpy(sysinst->errmsg, sizeof(sysinst->errmsg), errmsg); 1670 log_msg(LOG_DEFAULT, LVL_ERROR, errmsg); 1671 } 1672 1673 /** Log a debug message. 1674 * 1675 * @param sysinst System installer 1676 * @param errmsg Error message 1677 */ 1678 static void sysinst_debug(sysinst_t *sysinst, const char *msg) 1679 { 1680 log_msg(LOG_DEFAULT, LVL_ERROR, msg); 1681 } 1682 1683 /** Start system installation. 1684 * 1685 * @param sysinst System installer 1686 * @return EOK on success or an error code 1687 */ 1688 static int sysinst_start(sysinst_t *sysinst) 1689 { 1690 errno_t rc; 1691 fid_t fid; 1692 1693 rc = sysinst_progress_create(sysinst, &sysinst->progress); 1694 if (rc != EOK) 1695 return rc; 1696 1697 fid = fibril_create(sysinst_install_fibril, (void *)sysinst); 1698 if (fid == 0) { 1699 sysinst_error(sysinst, "Out of memory."); 1700 return ENOMEM; 1701 } 1702 1703 fibril_add_ready(fid); 1704 return EOK; 1705 } 1706 1707 /** Create installation confirmation dialog. 1708 * 1709 * @param sysinst System installer 1710 * @return EOK on success or an error code 1711 */ 1712 static errno_t sysinst_confirm_create(sysinst_t *sysinst) 1713 { 1714 ui_msg_dialog_params_t params; 1715 ui_msg_dialog_t *dialog; 1716 errno_t rc; 1717 1718 ui_msg_dialog_params_init(¶ms); 1719 params.caption = "System installation"; 1720 params.text = "This will install HelenOS to your computer. Continue?"; 1721 params.choice = umdc_ok_cancel; 1722 params.flags |= umdf_topmost | umdf_center; 1723 1724 rc = ui_msg_dialog_create(sysinst->ui, ¶ms, &dialog); 1725 if (rc != EOK) 1726 return rc; 1727 1728 ui_msg_dialog_set_cb(dialog, &sysinst_confirm_cb, sysinst); 1729 return EOK; 1730 } 1731 1732 /** Create upgrade confirmation dialog. 1733 * 1734 * @param sysinst System installer 1735 * @return EOK on success or an error code 1736 */ 1737 static errno_t sysinst_upgrade_confirm_create(sysinst_t *sysinst) 1738 { 1739 ui_msg_dialog_params_t params; 1740 ui_msg_dialog_t *dialog; 1741 errno_t rc; 1742 1743 ui_msg_dialog_params_init(¶ms); 1744 params.caption = "System upgrade"; 1745 params.text = "Existing installation found. " 1746 "Do you want to upgrade it?"; 1747 params.choice = umdc_ok_cancel; 1748 params.flags |= umdf_topmost | umdf_center; 1749 1750 rc = ui_msg_dialog_create(sysinst->ui, ¶ms, &dialog); 1751 if (rc != EOK) 1752 return rc; 1753 1754 ui_msg_dialog_set_cb(dialog, &sysinst_upgrade_confirm_cb, sysinst); 1755 return EOK; 1756 } 1757 1758 /** Create restart dialog. 1759 * 1760 * @param sysinst System installer 1761 * @return EOK on success or an error code 1762 */ 1763 static errno_t sysinst_restart_dlg_create(sysinst_t *sysinst) 1764 { 1765 ui_msg_dialog_params_t params; 1766 ui_msg_dialog_t *dialog; 1767 errno_t rc; 1768 1769 ui_msg_dialog_params_init(¶ms); 1770 params.caption = "Restart System"; 1771 1772 if (sysinst->oper == sio_install) 1773 params.text = "Installation complete. Restart the system?"; 1774 else 1775 params.text = "Upgrade complete. Restart the system?"; 1776 1777 params.choice = umdc_ok_cancel; 1778 params.flags |= umdf_topmost | umdf_center; 1779 1780 rc = ui_msg_dialog_create(sysinst->ui, ¶ms, &dialog); 1781 if (rc != EOK) 1782 return rc; 1783 1784 ui_msg_dialog_set_cb(dialog, &sysinst_restart_dlg_cb, sysinst); 1785 return EOK; 1786 } 1787 1788 /** Run system installer on display. 1789 * 1790 * @param display_spec Display specification 1791 * @return EOK on success or an error code 1792 */ 1793 static errno_t sysinst_run(const char *display_spec) 1794 { 1795 ui_t *ui = NULL; 1796 sysinst_t *sysinst; 1797 ui_wnd_params_t params; 1798 errno_t rc; 1799 1800 sysinst = calloc(1, sizeof(sysinst_t)); 1801 if (sysinst == NULL) 1802 return ENOMEM; 1803 1804 fibril_condvar_initialize(&sysinst->responded_cv); 1805 fibril_mutex_initialize(&sysinst->responded_lock); 1806 1807 rc = fmgt_create(&sysinst->fmgt); 1808 if (rc != EOK) { 1809 printf("Out of memory.\n"); 1810 goto error; 1811 } 1812 1813 fmgt_set_cb(sysinst->fmgt, &sysinst_fmgt_cb, (void *)sysinst); 1814 fmgt_set_init_update(sysinst->fmgt, true); 1815 1816 rc = ui_create(display_spec, &ui); 1817 if (rc != EOK) { 1818 printf("Error creating UI on display %s.\n", display_spec); 1819 goto error; 1820 } 1821 1822 sysinst->ui = ui; 1823 1824 ui_wnd_params_init(¶ms); 1825 params.caption = "System Installation"; 1826 params.style &= ~ui_wds_decorated; 1827 params.placement = ui_wnd_place_full_screen; 1828 params.flags |= ui_wndf_topmost | ui_wndf_nofocus; 1829 1830 rc = ui_window_create(sysinst->ui, ¶ms, &sysinst->bgwindow); 1831 if (rc != EOK) { 1832 printf("Error creating window.\n"); 1833 goto error; 1834 } 1835 1836 ui_window_set_cb(sysinst->bgwindow, &bg_window_cb, (void *)sysinst); 1837 1838 if (ui_is_textmode(sysinst->ui)) { 1839 rc = gfx_color_new_ega(0x17, &sysinst->bg_color); 1840 if (rc != EOK) { 1841 printf("Error allocating color.\n"); 1842 goto error; 1843 } 1844 } else { 1845 rc = gfx_color_new_rgb_i16(0x8000, 0xc800, 0xffff, &sysinst->bg_color); 1846 if (rc != EOK) { 1847 printf("Error allocating color.\n"); 1848 goto error; 1849 } 1850 } 1851 1852 rc = ui_window_paint(sysinst->bgwindow); 1853 if (rc != EOK) { 1854 printf("Error painting window.\n"); 1855 goto error; 1856 } 1857 1858 rc = sysinst_confirm_create(sysinst); 1859 if (rc != EOK) { 1860 printf("Error creating window.\n"); 1861 goto error; 1862 } 1863 1864 ui_run(ui); 1865 1866 if (sysinst->bgwindow != NULL) 1867 ui_window_destroy(sysinst->bgwindow); 1868 if (sysinst->system != NULL) 1869 system_close(sysinst->system); 1870 gfx_color_delete(sysinst->bg_color); 1871 ui_destroy(ui); 1872 free(sysinst); 1873 return EOK; 1874 error: 1875 if (sysinst->fmgt != NULL) 1876 fmgt_destroy(sysinst->fmgt); 1877 if (sysinst->system != NULL) 1878 system_close(sysinst->system); 1879 if (sysinst->bg_color != NULL) 1880 gfx_color_delete(sysinst->bg_color); 1881 if (sysinst->bgwindow != NULL) 1882 ui_window_destroy(sysinst->bgwindow); 1883 if (ui != NULL) 1884 ui_destroy(ui); 1885 free(sysinst); 1886 return rc; 1887 } 1888 1889 static void print_syntax(void) 1890 { 1891 printf("Syntax: " NAME " [-d <display-spec>]\n"); 1892 } 1893 1894 int main(int argc, char *argv[]) 1895 { 1896 const char *display_spec = UI_ANY_DEFAULT; 1897 errno_t rc; 1898 int i; 1899 1900 i = 1; 1901 while (i < argc && argv[i][0] == '-') { 1902 if (str_cmp(argv[i], "-d") == 0) { 1903 ++i; 1904 if (i >= argc) { 1905 printf("Argument missing.\n"); 1906 print_syntax(); 1907 return 1; 1908 } 1909 1910 display_spec = argv[i++]; 1911 } else { 1912 printf("Invalid option '%s'.\n", argv[i]); 1913 print_syntax(); 1914 return 1; 1915 } 1916 } 1917 1918 if (i < argc) { 1919 print_syntax(); 531 1920 return 1; 532 1921 } 533 1922 534 return sysinst_install(default_devs[i]); 1923 if (log_init(NAME) != EOK) { 1924 printf(NAME ": Failed to initialize logging.\n"); 1925 return 1; 1926 } 1927 1928 rc = sysinst_run(display_spec); 1929 if (rc != EOK) 1930 return 1; 1931 1932 return 0; 535 1933 } 536 1934
Note:
See TracChangeset
for help on using the changeset viewer.
