25 */
26
27 #include <stdio.h>
28 #include <errno.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <limits.h>
35 #include <fcntl.h>
36 #include <strings.h>
37
38 #include <sys/mman.h>
39 #include <sys/elf.h>
40 #include <sys/multiboot.h>
41
42 #include "bootadm.h"
43
44 direct_or_multi_t bam_direct = BAM_DIRECT_NOT_SET;
45 hv_t bam_is_hv = BAM_HV_UNKNOWN;
46 findroot_t bam_is_findroot = BAM_FINDROOT_UNKNOWN;
47
48 static void
49 get_findroot_cap(const char *osroot)
50 {
51 FILE *fp;
52 char path[PATH_MAX];
53 char buf[BAM_MAXLINE];
54 struct stat sb;
55 int dboot;
56 int error;
57 int ret;
58 const char *fcn = "get_findroot_cap()";
59
60 (void) snprintf(path, sizeof (path), "%s/%s",
61 osroot, "boot/grub/capability");
62
63 if (stat(path, &sb) == -1) {
64 bam_is_findroot = BAM_FINDROOT_ABSENT;
65 BAM_DPRINTF(("%s: findroot capability absent\n", fcn));
187 /*
188 * The GRUB multiboot header must be 32-bit aligned and completely
189 * contained in the 1st 8K of the file. If the unix binary has
190 * a multiboot header, then it is a 'dboot' kernel. Otherwise,
191 * this kernel must be booted via multiboot -- we call this a
192 * 'multiboot' kernel.
193 */
194 bam_direct = BAM_DIRECT_MULTIBOOT;
195 for (m = 0; m < 8192 - sizeof (multiboot_header_t); m += 4) {
196 mbh = (void *)(image + m);
197 if (mbh->magic == MB_HEADER_MAGIC) {
198 BAM_DPRINTF(("%s: is DBOOT unix\n", fcn));
199 bam_direct = BAM_DIRECT_DBOOT;
200 break;
201 }
202 }
203 (void) munmap(image, 8192);
204 (void) close(fd);
205
206 INJECT_ERROR1("GET_CAP_MULTIBOOT", bam_direct = BAM_DIRECT_MULTIBOOT);
207 if (bam_direct == BAM_DIRECT_DBOOT) {
208 if (bam_is_hv == BAM_HV_PRESENT) {
209 BAM_DPRINTF(("%s: is xVM system\n", fcn));
210 } else {
211 BAM_DPRINTF(("%s: is *NOT* xVM system\n", fcn));
212 }
213 } else {
214 BAM_DPRINTF(("%s: is MULTIBOOT unix\n", fcn));
215 }
216
217 /* Not a fatal error if this fails */
218 get_findroot_cap(osroot);
219
220 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
221 return (BAM_SUCCESS);
222 }
223
224 #define INST_RELEASE "var/sadm/system/admin/INST_RELEASE"
225
226 /*
227 * Return true if root has been bfu'ed. bfu will blow away
228 * var/sadm/system/admin/INST_RELEASE, so if it's still there, we can
229 * assume the system has not been bfu'ed.
230 */
231 static int
232 is_bfu_system(const char *root)
233 {
795 }
796 if (line == entry->end) {
797 BAM_DPRINTF(("%s: entry has ended\n", fcn));
798 break;
799 }
800 }
801 entry = find_matching_entry(entry->next, grubsign, grubroot,
802 root_opt);
803 }
804
805 if (update_num) {
806 BAM_DPRINTF(("%s: updated numbering\n", fcn));
807 update_numbering(mp);
808 }
809
810 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
811 return (BAM_SUCCESS);
812 }
813
814 static error_t
815 bam_add_hv(menu_t *mp, char *grubsign, char *grubroot, int root_opt)
816 {
817 entry_t *entry;
818 const char *fcn = "bam_add_hv()";
819
820 bam_print(_("adding xVM entries...\n"));
821
822 entry = find_matching_entry(mp->entries, grubsign, grubroot, root_opt);
823 while (entry != NULL) {
824 if (entry->flags & BAM_ENTRY_HV) {
825 BAM_DPRINTF(("%s: entry %d already converted to "
826 "xvm HV\n", fcn, entry->entryNum));
827 return (BAM_SUCCESS);
828 }
829 entry = find_matching_entry(entry->next, grubsign, grubroot,
830 root_opt);
831 }
832
833 (void) add_boot_entry(mp, NEW_HV_ENTRY, grubsign, XEN_MENU,
834 XEN_KERNEL_MODULE_LINE, DIRECT_BOOT_ARCHIVE, NULL);
835
836 BAM_DPRINTF(("%s: added xVM HV entry via add_boot_entry()\n", fcn));
837
838 update_numbering(mp);
839
840 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
841
842 return (BAM_SUCCESS);
843 }
844
845 static error_t
846 bam_add_dboot(
847 menu_t *mp,
848 char *osroot,
849 char *grubsign,
850 char *grubroot,
851 int root_opt)
852 {
853 int msg = 0;
854 entry_t *entry;
855 line_t *line;
856 error_t ret;
857 const char *fcn = "bam_add_dboot()";
858
859 bam_print(_("converting entries to dboot...\n"));
860
861 entry = find_matching_entry(mp->entries, grubsign, grubroot, root_opt);
862 while (entry != NULL) {
863 for (line = entry->start; line; line = line->next) {
864 if (line->cmd == NULL || line->arg == NULL) {
865 if (line == entry->end) {
918 }
919 }
920 entry = find_matching_entry(entry->next, grubsign, grubroot,
921 root_opt);
922 }
923
924 ret = msg ? BAM_MSG : BAM_SUCCESS;
925 BAM_DPRINTF(("%s: returning ret = %d\n", fcn, ret));
926 return (ret);
927 }
928
929 /*ARGSUSED*/
930 error_t
931 upgrade_menu(menu_t *mp, char *osroot, char *menu_root)
932 {
933 char *osdev;
934 char *grubsign;
935 char *grubroot;
936 int ret1;
937 int ret2;
938 int ret3;
939 const char *fcn = "upgrade_menu()";
940
941 assert(osroot);
942 assert(menu_root);
943
944 BAM_DPRINTF(("%s: entered. args: %s %s\n", fcn, osroot, menu_root));
945
946 /*
947 * We only support upgrades. Xen may not be present
948 * on smaller metaclusters so we don't check for that.
949 */
950 if (bam_is_findroot != BAM_FINDROOT_PRESENT ||
951 bam_direct != BAM_DIRECT_DBOOT) {
952 bam_error(_("automated downgrade of GRUB menu to older "
953 "version not supported.\n"));
954 return (BAM_ERROR);
955 }
956
957 /*
958 * First get the GRUB signature
959 */
960 osdev = get_special(osroot);
961 INJECT_ERROR1("UPGRADE_OSDEV", osdev = NULL);
962 if (osdev == NULL) {
963 bam_error(_("cant find special file for mount-point %s\n"),
964 osroot);
965 return (BAM_ERROR);
966 }
967
968 grubsign = get_grubsign(osroot, osdev);
969 INJECT_ERROR1("UPGRADE_GRUBSIGN", grubsign = NULL);
970 if (grubsign == NULL) {
971 free(osdev);
972 bam_error(_("cannot find GRUB signature for %s\n"), osroot);
973 return (BAM_ERROR);
974 }
975
976 /* not fatal if we can't get grubroot */
977 grubroot = get_grubroot(osroot, osdev, menu_root);
978 INJECT_ERROR1("UPGRADE_GRUBROOT", grubroot = NULL);
979
980 free(osdev);
981
982 ret1 = bam_add_findroot(mp, grubsign,
983 grubroot, root_optional(osroot, menu_root));
984 INJECT_ERROR1("UPGRADE_ADD_FINDROOT", ret1 = BAM_ERROR);
985 if (ret1 == BAM_ERROR)
986 goto abort;
987
988 if (bam_is_hv == BAM_HV_PRESENT) {
989 ret2 = bam_add_hv(mp, grubsign, grubroot,
990 root_optional(osroot, menu_root));
991 INJECT_ERROR1("UPGRADE_ADD_HV", ret2 = BAM_ERROR);
992 if (ret2 == BAM_ERROR)
993 goto abort;
994 } else
995 ret2 = BAM_SUCCESS;
996
997 ret3 = bam_add_dboot(mp, osroot, grubsign,
998 grubroot, root_optional(osroot, menu_root));
999 INJECT_ERROR1("UPGRADE_ADD_DBOOT", ret3 = BAM_ERROR);
1000 if (ret3 == BAM_ERROR)
1001 goto abort;
1002
1003 if (ret1 == BAM_MSG || ret2 == BAM_MSG || ret3 == BAM_MSG) {
1004 bam_error(_("one or more GRUB menu entries were not "
1005 "automatically upgraded\nFor details on manually "
1006 "updating entries, see %s\n"), MENU_URL(osroot));
1007 } else {
1008 bam_warn_hand_entries(mp, osroot);
1009 }
1010
1011 free(grubsign);
1012
1013 BAM_DPRINTF(("%s: returning ret = %d\n", fcn, BAM_WRITE));
1014 return (BAM_WRITE);
1015
1016 abort:
1017 free(grubsign);
1018 bam_error(_("error upgrading GRUB menu entries on %s. Aborting.\n"
1019 "For details on manually updating entries, see %s\n"), osroot,
1020 MENU_URL(osroot));
1021 return (BAM_ERROR);
1022 }
|
25 */
26
27 #include <stdio.h>
28 #include <errno.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <limits.h>
35 #include <fcntl.h>
36 #include <strings.h>
37
38 #include <sys/mman.h>
39 #include <sys/elf.h>
40 #include <sys/multiboot.h>
41
42 #include "bootadm.h"
43
44 direct_or_multi_t bam_direct = BAM_DIRECT_NOT_SET;
45 findroot_t bam_is_findroot = BAM_FINDROOT_UNKNOWN;
46
47 static void
48 get_findroot_cap(const char *osroot)
49 {
50 FILE *fp;
51 char path[PATH_MAX];
52 char buf[BAM_MAXLINE];
53 struct stat sb;
54 int dboot;
55 int error;
56 int ret;
57 const char *fcn = "get_findroot_cap()";
58
59 (void) snprintf(path, sizeof (path), "%s/%s",
60 osroot, "boot/grub/capability");
61
62 if (stat(path, &sb) == -1) {
63 bam_is_findroot = BAM_FINDROOT_ABSENT;
64 BAM_DPRINTF(("%s: findroot capability absent\n", fcn));
186 /*
187 * The GRUB multiboot header must be 32-bit aligned and completely
188 * contained in the 1st 8K of the file. If the unix binary has
189 * a multiboot header, then it is a 'dboot' kernel. Otherwise,
190 * this kernel must be booted via multiboot -- we call this a
191 * 'multiboot' kernel.
192 */
193 bam_direct = BAM_DIRECT_MULTIBOOT;
194 for (m = 0; m < 8192 - sizeof (multiboot_header_t); m += 4) {
195 mbh = (void *)(image + m);
196 if (mbh->magic == MB_HEADER_MAGIC) {
197 BAM_DPRINTF(("%s: is DBOOT unix\n", fcn));
198 bam_direct = BAM_DIRECT_DBOOT;
199 break;
200 }
201 }
202 (void) munmap(image, 8192);
203 (void) close(fd);
204
205 INJECT_ERROR1("GET_CAP_MULTIBOOT", bam_direct = BAM_DIRECT_MULTIBOOT);
206 if (bam_direct != BAM_DIRECT_DBOOT) {
207 BAM_DPRINTF(("%s: is MULTIBOOT unix\n", fcn));
208 }
209
210 /* Not a fatal error if this fails */
211 get_findroot_cap(osroot);
212
213 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
214 return (BAM_SUCCESS);
215 }
216
217 #define INST_RELEASE "var/sadm/system/admin/INST_RELEASE"
218
219 /*
220 * Return true if root has been bfu'ed. bfu will blow away
221 * var/sadm/system/admin/INST_RELEASE, so if it's still there, we can
222 * assume the system has not been bfu'ed.
223 */
224 static int
225 is_bfu_system(const char *root)
226 {
788 }
789 if (line == entry->end) {
790 BAM_DPRINTF(("%s: entry has ended\n", fcn));
791 break;
792 }
793 }
794 entry = find_matching_entry(entry->next, grubsign, grubroot,
795 root_opt);
796 }
797
798 if (update_num) {
799 BAM_DPRINTF(("%s: updated numbering\n", fcn));
800 update_numbering(mp);
801 }
802
803 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
804 return (BAM_SUCCESS);
805 }
806
807 static error_t
808 bam_add_dboot(
809 menu_t *mp,
810 char *osroot,
811 char *grubsign,
812 char *grubroot,
813 int root_opt)
814 {
815 int msg = 0;
816 entry_t *entry;
817 line_t *line;
818 error_t ret;
819 const char *fcn = "bam_add_dboot()";
820
821 bam_print(_("converting entries to dboot...\n"));
822
823 entry = find_matching_entry(mp->entries, grubsign, grubroot, root_opt);
824 while (entry != NULL) {
825 for (line = entry->start; line; line = line->next) {
826 if (line->cmd == NULL || line->arg == NULL) {
827 if (line == entry->end) {
880 }
881 }
882 entry = find_matching_entry(entry->next, grubsign, grubroot,
883 root_opt);
884 }
885
886 ret = msg ? BAM_MSG : BAM_SUCCESS;
887 BAM_DPRINTF(("%s: returning ret = %d\n", fcn, ret));
888 return (ret);
889 }
890
891 /*ARGSUSED*/
892 error_t
893 upgrade_menu(menu_t *mp, char *osroot, char *menu_root)
894 {
895 char *osdev;
896 char *grubsign;
897 char *grubroot;
898 int ret1;
899 int ret2;
900 const char *fcn = "upgrade_menu()";
901
902 assert(osroot);
903 assert(menu_root);
904
905 BAM_DPRINTF(("%s: entered. args: %s %s\n", fcn, osroot, menu_root));
906
907 /*
908 * We only support upgrades.
909 */
910 if (bam_is_findroot != BAM_FINDROOT_PRESENT ||
911 bam_direct != BAM_DIRECT_DBOOT) {
912 bam_error(_("automated downgrade of GRUB menu to older "
913 "version not supported.\n"));
914 return (BAM_ERROR);
915 }
916
917 /*
918 * First get the GRUB signature
919 */
920 osdev = get_special(osroot);
921 INJECT_ERROR1("UPGRADE_OSDEV", osdev = NULL);
922 if (osdev == NULL) {
923 bam_error(_("cant find special file for mount-point %s\n"),
924 osroot);
925 return (BAM_ERROR);
926 }
927
928 grubsign = get_grubsign(osroot, osdev);
929 INJECT_ERROR1("UPGRADE_GRUBSIGN", grubsign = NULL);
930 if (grubsign == NULL) {
931 free(osdev);
932 bam_error(_("cannot find GRUB signature for %s\n"), osroot);
933 return (BAM_ERROR);
934 }
935
936 /* not fatal if we can't get grubroot */
937 grubroot = get_grubroot(osroot, osdev, menu_root);
938 INJECT_ERROR1("UPGRADE_GRUBROOT", grubroot = NULL);
939
940 free(osdev);
941
942 ret1 = bam_add_findroot(mp, grubsign,
943 grubroot, root_optional(osroot, menu_root));
944 INJECT_ERROR1("UPGRADE_ADD_FINDROOT", ret1 = BAM_ERROR);
945 if (ret1 == BAM_ERROR)
946 goto abort;
947
948 ret2 = bam_add_dboot(mp, osroot, grubsign,
949 grubroot, root_optional(osroot, menu_root));
950 INJECT_ERROR1("UPGRADE_ADD_DBOOT", ret2 = BAM_ERROR);
951 if (ret2 == BAM_ERROR)
952 goto abort;
953
954 if (ret1 == BAM_MSG || ret2 == BAM_MSG) {
955 bam_error(_("one or more GRUB menu entries were not "
956 "automatically upgraded\nFor details on manually "
957 "updating entries, see %s\n"), MENU_URL(osroot));
958 } else {
959 bam_warn_hand_entries(mp, osroot);
960 }
961
962 free(grubsign);
963
964 BAM_DPRINTF(("%s: returning ret = %d\n", fcn, BAM_WRITE));
965 return (BAM_WRITE);
966
967 abort:
968 free(grubsign);
969 bam_error(_("error upgrading GRUB menu entries on %s. Aborting.\n"
970 "For details on manually updating entries, see %s\n"), osroot,
971 MENU_URL(osroot));
972 return (BAM_ERROR);
973 }
|