Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | // SPDX-License-Identifier: GPL-2.0+ /* * Bootflow internal functions using U-Boot headers * * This demonstrates functions that need direct access to U-Boot internal * structures and would be compiled with U-Boot headers first. * * Copyright 2025 Canonical Ltd. * Written by Simon Glass <simon.glass@canonical.com> */ /* This file uses U-Boot headers first */ #include <bootflow.h> #include <bootdev.h> #include <bootmeth.h> #include <bootstd.h> #include <dm/device.h> #include <sandbox_host.h> #include <u-boot-api.h> static void show_bootflow(int num, struct bootflow *bflow) { ub_printf("Bootflow %d:\n", num); ub_printf(" name: '%s'\n", bflow->name ? bflow->name : "(null)"); ub_printf(" state: %s\n", bootflow_state_get_name(bflow->state)); ub_printf(" method: '%s'\n", bflow->method ? bflow->method->name : "(null)"); ub_printf(" fname: '%s'\n", bflow->fname ? bflow->fname : "(null)"); ub_printf(" dev: '%s'\n", bflow->dev ? bflow->dev->name : "(null)"); ub_printf(" part: %d\n", bflow->part); ub_printf(" size: %d\n", bflow->size); ub_printf(" err: %d\n", bflow->err); if (bflow->os_name) ub_printf(" os_name: '%s'\n", bflow->os_name); if (bflow->logo) ub_printf(" logo: present (%zu bytes)\n", bflow->logo_size); ub_printf("\n"); } int bootflow_internal_scan(void) { struct bootflow bflow; struct bootflow_iter iter; struct bootstd_priv *std; struct bootflow *first_bflow; struct udevice *host_dev; int ret, count = 0; ub_printf("Internal bootflow scan using U-Boot headers first\n"); /* Get bootstd private data */ ret = bootstd_get_priv(&std); if (ret) { ub_printf("bootstd_get_priv() failed: %d\n", ret); return ret; } /* Set bootmethod order to only use extlinux and efi */ ret = bootmeth_set_order("extlinux efi"); if (ret) { ub_printf("bootmeth_set_order() failed: %d\n", ret); return ret; } ub_printf("Set bootmethod order to: extlinux efi\n"); /* Now we can actually use bootflow.h definitions! */ ub_printf("BOOTFLOWST_MEDIA = %d\n", BOOTFLOWST_MEDIA); ub_printf("sizeof(struct bootflow) = %zu\n", sizeof(struct bootflow)); ub_printf("sizeof(struct bootflow_iter) = %zu\n", sizeof(struct bootflow_iter)); /* Attach the MMC image file to make bootflows available */ ub_printf("Attaching mmc1.img file...\n"); ret = host_create_attach_file("mmc1", "/home/sglass/u/mmc1.img", false, 512, &host_dev); if (ret) { ub_printf("host_create_attach_file() failed: %d\n", ret); return ret; } /* List all available bootdevs */ ub_printf("Available bootdevs:\n"); bootdev_list(true); /* Try to scan for the first bootflow */ ret = bootflow_scan_first(NULL, NULL, &iter, BOOTFLOWIF_SHOW, &bflow); if (ret) { ub_printf("bootflow_scan_first() failed: %d\n", ret); return ret; } /* Iterate through all bootflows */ do { count++; show_bootflow(count, &bflow); /* Add bootflow to the global list */ ret = bootstd_add_bootflow(&bflow); if (ret < 0) { ub_printf("bootstd_add_bootflow() failed: %d\n", ret); bootflow_free(&bflow); } /* Get next bootflow */ ret = bootflow_scan_next(&iter, &bflow); } while (!ret); ub_printf("Found %d total bootflows\n", count); /* Clean up the iterator */ bootflow_iter_uninit(&iter); /* Return immediately if no bootflows found */ if (!count) { ub_printf("No bootflows found to boot\n"); return 0; } /* Boot the first bootflow */ /* Get the first bootflow from the global list */ first_bflow = alist_getw(&std->bootflows, 0, struct bootflow); if (!first_bflow) { ub_printf("Failed to get first bootflow from global list\n"); return -1; } ub_printf("\bBooting: %s\n", first_bflow->name ? first_bflow->name : "(unnamed)"); if (first_bflow->os_name) ub_printf("OS: %s\n", first_bflow->os_name); ret = bootflow_boot(first_bflow); if (ret) ub_printf("bootflow_boot() failed: %dE\n", ret); else ub_printf("bootflow_boot() succeeded (shouldn't reach here!)\n"); return 0; } |