diff options
author | 2023-10-10 14:33:42 +0000 | |
---|---|---|
committer | 2023-10-10 14:33:42 +0000 | |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot-sam460ex/board/ACube/menu | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot-sam460ex/board/ACube/menu')
23 files changed, 2413 insertions, 0 deletions
diff --git a/roms/u-boot-sam460ex/board/ACube/menu/bios_menu.c b/roms/u-boot-sam460ex/board/ACube/menu/bios_menu.c new file mode 100644 index 000000000..0f4849aa8 --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/bios_menu.c @@ -0,0 +1,449 @@ +#include "menu.h" +#include "bios_menu.h" +#include "creation.h" + +/* + * These hooks are for usage with popup menus. Assumes that user_data is the name of + * the variable to save to / load from. + * + * entries is the array of entries that may fit. This function returns -1 if none + * of the entries fits, indicating that the default should be considered. + */ + +int cvar_popup_load(void *user_data, popup_entry_t *entries) +{ + char + *var = GETENV((char *)user_data); + int + i=0; + + while (var && entries->value_text) + { + if (entries->value_text != (char *)(~0) && (strcmp(var, entries->value_text) == 0)) + { + return i; + } + i++; + entries++; + } + + return -1; +} + +void cvar_popup_save(void *user_data, popup_entry_t *entry) +{ + SETENV((char *)user_data, entry->value_text); +} + +int cvar_numeric_load(void *user_data, int param2, int def_val) +{ + char *var = GETENV((char *)user_data); + + if (var) return atoi(var); + else return def_val; +} + +static void cvar_numeric_save(void *user_data, int param2, int value) +{ + char buffer[30]; + sprintf(buffer, "%d", value); + SETENV((char *)user_data, buffer); +} + +#define TABLE_END {NULL, NULL, NULL} +#define LABEL(x) menu_item_create(ITEMTYPE_LABEL, menu, #x) +#define SPACER menu_item_create(ITEMTYPE_LABEL, menu, " ") + +#define MAIN_MENU_NAME "U-BOOT Preferences Menu" +#ifdef CONFIG_SAM460EX +#define PCIE_SATA_NAME "PCI-E 1x / SATA-2" +#endif +#define BOOTSEQ_NAME "Boot Sequence" +#define NETBOOT_NAME "Network Boot Options" +#define SYSTEM_INFO_NAME "System Information" +#define AMIGABOOT_NAME "OS MultiBoot Options" +#define VIDEO_NAME "Video Options" + + +/************************************************************************************** + MAIN MENU + *************************************************************************************/ + +menu_t *make_main_menu(form_t *form) +{ + menu_t + *menu = new_menu(MENUTYPE_FORM, MAIN_MENU_NAME, form, NULL); + + if (menu) + { + item_t *item; + + item = menu_item_create(ITEMTYPE_SUBMENU, menu, + "Video Options", VIDEO_NAME); //TEST_ITEM(); + menu_item_set_help(item, "Select the current video card"); + +#ifdef CONFIG_SAM460EX + item = menu_item_create(ITEMTYPE_SUBMENU, menu, + "PCI-E 1x / SATA-2", PCIE_SATA_NAME); //TEST_ITEM(); + menu_item_set_help(item, "Select PCI-E 1x / SATA-2"); +#endif + + item = menu_item_create(ITEMTYPE_SUBMENU, menu, + "Boot Sequence", BOOTSEQ_NAME); //TEST_ITEM(); + menu_item_set_help(item, "Adjust parameters for booting an OS"); + + item = menu_item_create(ITEMTYPE_SUBMENU, menu, + "System Information", SYSTEM_INFO_NAME); //TEST_ITEM(); + menu_item_set_help(item, "Information about the hardware installed on this machine"); + + } + menu_form_add_menu(form, menu); + return menu; +} + +/************************************************************************************** + PCI-E/SATA Menu + *************************************************************************************/ +#ifdef CONFIG_SAM460EX +popup_entry_t pcie_sata_select_entries[] = +{ + {"SATA-2", "sata2", NULL}, + {"PCI-E 1x", "pci-e", NULL}, + TABLE_END, +}; + +menu_t *make_pcie_sata_menu(form_t *form) +{ + menu_t *menu = new_menu(MENUTYPE_FORM, PCIE_SATA_NAME, form, MAIN_MENU_NAME); + + item_t + *item; + + if (menu) + { + item = menu_item_create(ITEMTYPE_POPUP, menu, + "Select PCI-E 1x / SATA-2", 0, "serdes", + cvar_popup_save, cvar_popup_load, + pcie_sata_select_entries); + menu_item_set_help(item, "Choose to acticate PCI-E 1x slot or the onchip "\ + "SATA-2 port (requires reboot and changing J16 on motherboard)"); + } + + menu_form_add_menu(form, menu); + return menu; +} +#endif + +/************************************************************************************** + Video Menu + *************************************************************************************/ + +popup_entry_t video_select_entries[] = +{ +#if defined(CONFIG_SAM440EP_FLEX) + {"PCI", "pci", NULL}, + {"SM502", "sm502", NULL}, +#elif defined(CONFIG_SAM460EX) + {"Onboard", "sm502", NULL}, + {"PCI/PCI-E", "pci", NULL}, +#else + {"Internal", "internal", NULL}, + {"PCI", "pci", NULL}, +#endif + TABLE_END, +}; + +popup_entry_t silent_select_entries[] = +{ + {"Verbose", "0", NULL}, + {"Silent", "1", NULL}, + TABLE_END, +}; + +menu_t *make_video_menu(form_t *form) +{ + menu_t *menu = new_menu(MENUTYPE_FORM, VIDEO_NAME, form, MAIN_MENU_NAME); + + item_t + *item; + + if (menu) + { + item = menu_item_create(ITEMTYPE_POPUP, menu, + "Boot from graphics card", 0, "video_activate", + cvar_popup_save, cvar_popup_load, + video_select_entries); //TEST_ITEM(); + +#if defined(CONFIG_SAM440EP_FLEX) + menu_item_set_help(item, "Choose whether the PCI ATI or the SM502 "\ + "graphics card is activated (requires reboot)"); +#elif defined(CONFIG_SAM460EX) + menu_item_set_help(item, "Choose whether the PCI/PCI-E or the onboard "\ + "graphics card is activated (requires reboot)"); +#else + menu_item_set_help(item, "Choose whether the internal ATI M9 or a PCI "\ + "graphics card is activated (requires reboot)"); +#endif + + item = menu_item_create(ITEMTYPE_POPUP, menu, + "Console", 2, "hush", + cvar_popup_save, cvar_popup_load, + silent_select_entries); + menu_item_set_help(item, "Suppress most console messages on the screen while booting"); + } + + menu_form_add_menu(form, menu); + return menu; +} + +/************************************************************************************** + Boot Sequence + *************************************************************************************/ + +popup_entry_t boot_seq[] = +{ + {"0680 PATA HD", "psii", NULL}, + {"0680 PATA DVD", "psiicdrom", NULL}, + {"3x12 SATA HD", "ssii", NULL}, + {"3x12 SATA DVD", "ssiicdrom", NULL}, + {"3114 SATA HD", "s4sii", NULL}, + {"3114 SATA DVD", "s4siicdrom", NULL}, +#ifdef CONFIG_SAM460EX + {"460 SATA2 HD", "sata2-460", NULL}, +#endif + {"USB DVD", "ucdrom", NULL}, + {"USB HD", "usb", NULL}, + {"Network", "net", NULL}, + {"none", "", NULL}, + TABLE_END, +}; + +menu_t *make_netboot_menu(form_t *form) +{ + menu_t + *menu = new_menu(MENUTYPE_FORM, NETBOOT_NAME, form, BOOTSEQ_NAME); + + item_t + *item; + + if (menu) + { + item = menu_item_create(ITEMTYPE_STRING_CVAR, menu, + "Local TCP/IP Address", "ipaddr", ""); //TEST_ITEM(); + menu_item_set_help(item, "Local TCP/IP address for network boot"); + + item = menu_item_create(ITEMTYPE_STRING_CVAR, menu, + "Server TCP/IP Address", "serverip", ""); //TEST_ITEM(); + menu_item_set_help(item, "Server IP address. Server must be running a supported networking boot service"); + } + + menu_form_add_menu(form, menu); + return menu; +} + +menu_t *make_amigaboot_menu(form_t *form) +{ + menu_t + *menu = new_menu(MENUTYPE_FORM, AMIGABOOT_NAME, form, BOOTSEQ_NAME); + + item_t + *item; + + if (menu) + { + item = menu_item_create(ITEMTYPE_POPUP, menu, + "Boot Device 1", 0, "boot1", + cvar_popup_save, cvar_popup_load, boot_seq); //TEST_ITEM(); + menu_item_set_help(item, "Select first boot device"); + + item = menu_item_create(ITEMTYPE_POPUP, menu, + "Boot Device 2", 2, "boot2", + cvar_popup_save, cvar_popup_load, boot_seq); //TEST_ITEM(); + menu_item_set_help(item, "Select second boot device"); + + item = menu_item_create(ITEMTYPE_POPUP, menu, + "Boot Device 3", 4, "boot3", + cvar_popup_save, cvar_popup_load, boot_seq); //TEST_ITEM(); + menu_item_set_help(item, "Select third boot device"); + + SPACER; + + item = menu_item_create(ITEMTYPE_STRING_CVAR, menu, + "OS Selection timeout", "boota_timeout", "3"); //TEST_ITEM(); + menu_item_set_help(item, "The amount of time the OS selection menu waits before booting"); + + } + + menu_form_add_menu(form, menu); + return menu; +} + +menu_t *make_boot_menu(form_t *form) +{ + menu_t + *menu = new_menu(MENUTYPE_FORM, BOOTSEQ_NAME, form, MAIN_MENU_NAME); + + item_t + *item; + + if (menu) + { + item = menu_item_create(ITEMTYPE_STRING_CVAR, menu, + "Menu Boot delay", "menuboot_delay", "3"); + menu_item_set_help(item, "The amount of time the menu waits before continuing to boot"); + SPACER; + item = menu_item_create(ITEMTYPE_STRING_CVAR, menu, + "Boot arguments for AOS", "os4_commandline", "debuglevel=0"); //TEST_ITEM(); + menu_item_set_help(item, "Argument string passed to AOS"); + + item = menu_item_create(ITEMTYPE_STRING_CVAR, menu, + "Boot arguments for Linux", "bootargs", "root=/dev/sda3"); //TEST_ITEM(); + menu_item_set_help(item, "Argument string passed to Linux"); + + SPACER; + item = menu_item_create(ITEMTYPE_SUBMENU, menu, + "Network Boot Options", NETBOOT_NAME); //TEST_ITEM(); + item = menu_item_create(ITEMTYPE_SUBMENU, menu, + "OS Multiboot Options", AMIGABOOT_NAME); + } + + menu_form_add_menu(form, menu); + return menu; +} + +/************************************************************************************** + System Information + *************************************************************************************/ +static void dummy(void) +{ +} + +char *mystrdup(char *src) +{ + int + i = strlen(src)+1; + + char + *s = malloc(i); + + if (s) + { + strcpy(s, src); + } + + return s; +} + +menu_t *make_sysinfo_menu(form_t *form) +{ + char buffer[64]; + + menu_t + * menu = new_menu(MENUTYPE_FORM, SYSTEM_INFO_NAME, form, MAIN_MENU_NAME); + + item_t + * item; + + int cpu_pvr; + + + sys_info_t + sysinfo; + + get_sys_info(&sysinfo); + + if (menu) + { + { + DECLARE_GLOBAL_DATA_PTR; + cpu_pvr = get_pvr(); + + switch((cpu_pvr&0xffff0000)>>16) + { +#ifdef CONFIG_SAM460EX + case 0x1302: + sprintf (buffer, "CPU Type : AMCC PowerPC 460ex Rev "); + switch (cpu_pvr&0xffff) + { + case 0x18a3: + strcat (buffer, "A"); + break; + case 0x18a4: + strcat (buffer, "B"); + break; + default: + strcat (buffer, "unknown"); + break; + } + break; +#else + case 0x4222: + sprintf (buffer, "CPU Type : AMCC PowerPC 440ep Rev "); + switch (cpu_pvr&0xffff) + { + case 0x18d3: + strcat (buffer, "B"); + break; + case 0x18d4: + strcat (buffer, "C"); + break; + default: + strcat (buffer, "unknown"); + break; + } + break; +#endif + default: + sprintf(buffer, "Unknown: PVR 0x%08X", cpu_pvr); + } + + sprintf(buffer, "%s / %ld MHz", buffer, gd->cpu_clk / 1000000); + item = menu_item_create(ITEMTYPE_LABEL, menu, mystrdup(buffer)); + + sprintf(buffer, "PLB freq : %4ld MHz", sysinfo.freqPLB / 1000000); + item = menu_item_create(ITEMTYPE_LABEL, menu, mystrdup(buffer)); + +#ifdef CONFIG_SAM460EX + sprintf(buffer, "DDR2 freq : %4ld MHz", 2 * sysinfo.freqDDR / 1000000); + item = menu_item_create(ITEMTYPE_LABEL, menu, mystrdup(buffer)); +#else + sprintf(buffer, "DDR freq : %4ld MHz", 2 * sysinfo.freqPLB / 1000000); + item = menu_item_create(ITEMTYPE_LABEL, menu, mystrdup(buffer)); +#endif + + /**** DIMM BANK INFO ****/ + SPACER; + item = menu_item_create(ITEMTYPE_LABEL, menu, "Memory"); + sprintf(buffer, "Total : %ld MB", (gd->bd->bi_memsize) / 1024 / 1024); + item = menu_item_create(ITEMTYPE_LABEL, menu, mystrdup(buffer)); + } + } + + menu_form_add_menu(form, menu); + return menu; +} + +void restore_func(void) +{ + +} + +void recover_func(void) +{ + +} + +/* ********************************************************************************* */ + +void make_menus(form_t *form) +{ + make_video_menu(form); +#ifdef CONFIG_SAM460EX + make_pcie_sata_menu(form); +#endif + make_main_menu(form); + make_netboot_menu(form); + make_amigaboot_menu(form); + make_boot_menu(form); + make_sysinfo_menu(form); +} diff --git a/roms/u-boot-sam460ex/board/ACube/menu/bios_menu.h b/roms/u-boot-sam460ex/board/ACube/menu/bios_menu.h new file mode 100644 index 000000000..d32dc8138 --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/bios_menu.h @@ -0,0 +1,8 @@ +#ifndef BIOS_MENU_H +#define BIOS_MENU_H + +extern popup_entry_t boot_seq[]; +extern void make_menus(form_t *form); + + +#endif //BIOS_MENU_H diff --git a/roms/u-boot-sam460ex/board/ACube/menu/bootselect_menu.c b/roms/u-boot-sam460ex/board/ACube/menu/bootselect_menu.c new file mode 100644 index 000000000..c50b6d1f6 --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/bootselect_menu.c @@ -0,0 +1,112 @@ +#include "menu.h" +#include "bios_menu.h" //For boot_seq. +#include "bootselect_menu.h" +#include "creation.h" + +int return_value = 0; + +int cvar_numeric_load(void *user_data, int param2, int def_val); +void cvar_popup_save(void *user_data, popup_entry_t *entry); +int cvar_popup_load(void *user_data, popup_entry_t *entries); + +#define LABEL(x) menu_item_create(ITEMTYPE_LABEL, menu, #x) +#define SPACER menu_item_create(ITEMTYPE_LABEL, menu, " ") + +#define BOOT_MENU_NAME "U-Boot Boot Select" +#define EXIT_MENU_NAME "Exit Menu" + +#define EXIT_BOOT_CONFIG 0 +#define EXIT_BOOT_NOCONFIG 1 +#define EXIT_GO_MENU 2 + +void my_leave_func(item_t *item, void *dummy, int arg) +{ + setenv("boot2", ""); + setenv("boot3", ""); + + switch (arg) + { + case EXIT_BOOT_CONFIG: + return_value = 0; + leave_func(item, dummy, EXIT_AND_SAVE); + break; + case EXIT_BOOT_NOCONFIG: + return_value = 0; + leave_func(item, dummy, EXIT_AND_NO_SAVE); + break; + case EXIT_GO_MENU: + return_value = 1; + leave_func(item, dummy, EXIT_AND_NO_SAVE); + break; + } +} + +void make_bootselect_menu(form_t *form) +{ + item_t *item; + menu_t *menu; + + // Boot Select // + + menu = new_menu(MENUTYPE_FORM, BOOT_MENU_NAME, form, 0); + + item = menu_item_create(ITEMTYPE_POPUP, menu, + "Boot Device", 0, "boot1", + cvar_popup_save, cvar_popup_load, boot_seq); //TEST_ITEM(); + + menu_item_set_help(item, "Choose which boot device should be attempted first"); + + SPACER; + item = menu_item_create(ITEMTYPE_STRING_CVAR, menu, + "Boot arguments for AOS", "os4_commandline", "debuglevel=0"); //TEST_ITEM(); + menu_item_set_help(item, "Argument string to be passed to AOS"); + + item = menu_item_create(ITEMTYPE_STRING_CVAR, menu, + "Boot arguments for Linux", "bootargs", "root=/dev/Sda3"); //TEST_ITEM(); + menu_item_set_help(item, "Argument string to be passed to Linux"); + + SPACER; + + menu_form_add_menu(form, menu); + + // Exit // + menu = new_menu(MENUTYPE_POPUP, EXIT_MENU_NAME, form, 0); + + item = menu_item_create(ITEMTYPE_FUNC, menu, "Boot this configuration", my_leave_func, NULL, EXIT_BOOT_CONFIG); + menu_item_set_help(item, "Temporarily boot this configuration"); + item = menu_item_create(ITEMTYPE_FUNC, menu, "Go to preferences menu", my_leave_func, NULL, EXIT_GO_MENU); + menu_item_set_help(item, "Abort the changes and go to the preferences menu"); + item = menu_item_create(ITEMTYPE_FUNC, menu, "Continue normal boot", my_leave_func, NULL, EXIT_BOOT_NOCONFIG); + menu_item_set_help(item, "Abort the changes and continue booting the normal configuration"); + menu_set_position(menu, 6, 6); + + menu_form_add_menu(form, menu); +} + +void boot_establish(void) +{ + char *bootfinal = ""; + char *b1 = "boota"; + char *mboot = getenv("menuboot_cmd"); + char *method = getenv("boot_method"); + char *bootcommand = getenv("boot_command"); + + if (method == NULL) method="boota"; + + if (mboot && strncmp(mboot, "noboot", 6) == 0) + { + setenv("menuboot_cmd", " "); + return; + } + + if (strcmp(method, "boota") == 0) + { + bootfinal = b1; + } + else + { + bootfinal = bootcommand; + } + + setenv("menuboot_cmd", bootfinal); +} diff --git a/roms/u-boot-sam460ex/board/ACube/menu/bootselect_menu.h b/roms/u-boot-sam460ex/board/ACube/menu/bootselect_menu.h new file mode 100644 index 000000000..7cc1ef811 --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/bootselect_menu.h @@ -0,0 +1,8 @@ +#ifndef BOOTSELECT_MENU +#define BOOTSELECT_MENU + +extern int return_value; +extern void make_bootselect_menu(form_t *form); +extern void boot_establish(void); + +#endif // BOOTSELECT_MENU diff --git a/roms/u-boot-sam460ex/board/ACube/menu/cmd_menu.c b/roms/u-boot-sam460ex/board/ACube/menu/cmd_menu.c new file mode 100644 index 000000000..f89b0e29d --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/cmd_menu.c @@ -0,0 +1,176 @@ +#include <common.h> +#include <command.h> +#include "menu.h" +#include "bootselect_menu.h" +#include "creation.h" +#include "bios_menu.h" +#include <asm/processor.h> + +static form_t *root = 0; +static form_t *bootselect = 0; + +#define MAIN_MENU_NAME "U-BOOT Preferences Menu" +#define BOOT_MENU_NAME "U-Boot Boot Select" + +static void establish_menu_settings(void); +static int do_menu_countdown(void); +static int fromsilent = 0; + +DECLARE_GLOBAL_DATA_PTR; + +int show_and_do_boot_select(void) +{ + unsigned long delta = TEXT_BASE - gd->relocaddr; + + menu_item_relocate(delta); + + bootselect = new_form(BOOT_MENU_NAME); + if (!bootselect) return 0; + + make_bootselect_menu(bootselect); + menu_set_form(bootselect); + menu_form_switch_menu(bootselect, BOOT_MENU_NAME); + menu_do(false); + + return return_value; +} + +void show_and_do_bios_menu(void) +{ + unsigned long delta = TEXT_BASE - gd->relocaddr; + + menu_item_relocate(delta); + + root = new_form("U-BOOT Setup Menu"); + if (!root) return; + + make_menus(root); + menu_set_form(root); + menu_form_switch_menu(root, MAIN_MENU_NAME); + menu_do(true); +} + +static int do_menu_countdown(void) +{ + int bootdelay; + int current; + char *s, c; + + bootdelay = 0; + s = GETENV("menuboot_delay"); + + if (s) bootdelay = atoi(s); + + if (bootdelay == 0) + { + if (tstc() != -1) return 1; + else return 0; + } + + putc('\n'); + if (fromsilent) puts(" "); + puts("Press SPACE for prefs, ENTER for boot select, ESC for prompt\n"); + if (fromsilent) puts(" "); + puts("Booting... "); + + current = 0; + while (current < bootdelay) + { + int i; + + printf("\b\b\b%2d ", bootdelay - current); + + for (i=0; i<1000; i++) + { + if (tstc()) + { + c = getc(); + + // ESC + if ((c == 5) || (c == 113)) return -10; + + // ENTER + if (c == 13) return show_and_do_boot_select(); + + // SPACE + if (c == 32) return 1; + } + udelay(1000); + } + current++; + } + + return 0; +} + +extern u32 *fb_base_phys; +extern u32 *fb_base_phys_sm502; + +int do_menu( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ) +{ + int ret = 0; + + // if console was silent, revert it back + if (gd->flags & GD_FLG_SILENT) { + fromsilent = 1; + gd->flags &= ~GD_FLG_SILENT; + } + + // only if there is an active vga ------------------------------- +#ifdef CONFIG_SAM440EP + if (fb_base_phys) +#else + if ((fb_base_phys) || (fb_base_phys_sm502)) +#endif + { + if (flag==0) + { + video_set_color(0); + show_and_do_bios_menu(); + puts("\n"); + video_set_color(0); + return 0; + } + else + { + ret = do_menu_countdown(); + + if (ret == -10) + { + puts("\b\b\b break..\n"); + setenv("menuboot_cmd", " "); + return 0; + } + + if (ret == 1) + { + video_set_color(0); + show_and_do_bios_menu(); + } + + video_clear_attr(); + establish_menu_settings(); + puts("\n"); + video_set_color(0); + return 0; + } + } + else return -1; +} + +/* + * This routine establishes all settings from the menu that aren't already done + * by the standard setup. + */ + +static void establish_menu_settings(void) +{ + boot_establish(); + +} + +U_BOOT_CMD( + menu, 1, 1, do_menu, + "Show preferences menu", + "Show the preferences menu that is used to boot an OS\n" + ); diff --git a/roms/u-boot-sam460ex/board/ACube/menu/creation.c b/roms/u-boot-sam460ex/board/ACube/menu/creation.c new file mode 100644 index 000000000..314481e94 --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/creation.c @@ -0,0 +1,168 @@ +#include "menu.h" +#include <stdarg.h> +#include <malloc.h> +#include "func_items.h" +#include "popup_items.h" +#include "string_items.h" +#include "label_items.h" + +#define SINGLE_BOX 0 +#define DOUBLE_BOX 1 + +/* -- Forms -- */ +form_t *new_form(char *title) +{ + form_t *form = (form_t *)malloc(sizeof(form_t)); + if (form) + { + memset(form, 0, sizeof(form_t)); + form->form_title = title; + list_init(& form->menu_list); + } + return form; +} + +void menu_form_set_menu(form_t *form, menu_t *menu) +{ + item_t *item = (item_t *)(menu->item_list.first); + while (item) + { + if (item->f_load) item->f_load(menu, item); + item = (item_t *)(item->link.next); + } + + form->current_menu = menu; + menu_draw_form(form); +} + +void menu_form_add_menu(form_t *form, menu_t *menu) +{ + list_add(&(form->menu_list), (node_t *)menu); +} + +menu_t* menu_form_find_menu(form_t *form, char *name) +{ + node_t *n; + n = form->menu_list.first; + while (n) + { + if (strcmp(name, ((menu_t *)n)->menu_title) == 0) + return (menu_t *)n; + n = n->next; + } + return NULL; +} + +/* -- Menus -- */ +menu_t *new_menu(int type, char *title, form_t *parent, char *parent_menu) +{ + menu_t *menu = (menu_t *)malloc(sizeof(menu_t)); + if (menu) + { + menu->type = type; + menu->menu_title = title; + menu->parent_form = parent; + menu->x = menu->y = 0; + menu->w = menu->h = 0; + menu->needs_layout = true; + menu->item_spacing = 1; + menu->parent_menu = parent_menu; + menu->current_item = NULL; + list_init(&(menu->item_list)); + } + return menu; +} + +void menu_set_position(menu_t *menu, int line, int col) +{ + if (menu) + { + menu->x = col; + menu->y = line; + } +} + +void menu_add_item(menu_t *menu, item_t *item) +{ + list_add(&(menu->item_list), (node_t *)item); + menu->needs_layout = true; +} + +/* Items */ + +typedef struct +{ + int type; + item_t * (*create)(menu_t *, va_list); +} itemtype_t; + + +itemtype_t item_types_templates[] = +{ + //{ ITEMTYPE_BOOL_CVAR, itemtype_bool_cvar_alloc }, + { ITEMTYPE_FUNC, itemtype_func_alloc }, + { ITEMTYPE_SUBMENU, itemtype_submenu_alloc }, + { ITEMTYPE_POPUP, itemtype_popup_alloc }, + { ITEMTYPE_STRING_CVAR, itemtype_string_cvar_alloc }, + { ITEMTYPE_LABEL, itemtype_label_alloc }, + //{ ITEMTYPE_NUMERIC, itemtype_numeric_alloc }, + //{ ITEMTYPE_REGISTER, itemtype_register_alloc }, +}; + +itemtype_t item_types[10]; + + +#define NUM_ITEMTYPES (sizeof(item_types) / sizeof(itemtype_t)) + +void menu_item_relocate(unsigned long offset) +{ + int i; + for (i=0; i<NUM_ITEMTYPES; i++) + { + item_types[i].type = item_types_templates[i].type; + item_types[i].create = + (item_t * (*)(menu_t *, va_list)) ((unsigned char *)item_types_templates[i].create); // - offset); + } +} + +item_t *menu_item_create(int type, menu_t *menu, ...) +{ + va_list args; + int i; + item_t *new_item; + + for (i=0; i<NUM_ITEMTYPES; i++) + { + if (item_types[i].type == type) + { + va_start(args, menu); + new_item = item_types[i].create(menu, args); + va_end(args); + if (menu) + { + menu_add_item(menu, new_item); + } + return new_item; + } + } + + return NULL; +} + +void menu_item_init(item_t *item) +{ + item->disabled = false; + item->break_after = false; + item->help_text = NULL; +} + +void menu_item_break_after(item_t *item) +{ + if (item) item->break_after = true; +} + +void menu_item_set_help(item_t *item, char *help_string) +{ + if (item) + item->help_text = help_string; +} diff --git a/roms/u-boot-sam460ex/board/ACube/menu/creation.h b/roms/u-boot-sam460ex/board/ACube/menu/creation.h new file mode 100644 index 000000000..d5e1668bd --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/creation.h @@ -0,0 +1,20 @@ +#ifndef CREATION_H +#define CREATION_H + +form_t *new_form(char *title); +void menu_form_set_menu(form_t *form, menu_t *menu); +void menu_item_relocate(unsigned long offset); +void menu_form_add_menu(form_t *form, menu_t *menu); +menu_t* menu_form_find_menu(form_t *form, char *name); +menu_t *new_menu(int type, char *title, form_t *parent, char *parent_menu); +void menu_set_position(menu_t *menu, int line, int col); +void menu_add_item(menu_t *menu, item_t *item); + +item_t* menu_item_create(int type, menu_t *menu, ...); +void menu_item_set_help(item_t *item, char *help_string); +void menu_item_init(item_t *item); +void menu_item_break_after(item_t *item); +void *mymalloc(size_t size); + +#endif // CREATION_H + diff --git a/roms/u-boot-sam460ex/board/ACube/menu/func_items.c b/roms/u-boot-sam460ex/board/ACube/menu/func_items.c new file mode 100644 index 000000000..65a905a4c --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/func_items.c @@ -0,0 +1,118 @@ +#include "menu.h" +#include "func_items.h" +#include <stdarg.h> +#include "creation.h" + +struct func_item +{ + item_t item; + char *display_text; + void *param1; + int param2; + void (*func)(item_t *,void *, int); +}; + +void itemtype_func_render(menu_t *menu, item_t *item, int state) +{ + struct func_item *it = (struct func_item *)item; + int x,y; + x = menu->x + item->x; + y = menu->y + item->y; + + video_draw_text(x,y, state, it->display_text, item->w); +} + +void itemtype_func_invoke(menu_t *menu, item_t *item, int key) +{ + struct func_item *it = (struct func_item *)item; + switch(key) + { + case KEY_ACTIVATE: + if (it->func) + { + it->func(item, it->param1, it->param2); + } + break; + } +} + +item_t *itemtype_func_alloc(menu_t *menu, va_list args) +{ + //char *s; + struct func_item *item = (struct func_item *)malloc(sizeof(struct func_item)); + if (!item) return NULL; + menu_item_init(&item->item); + + item->display_text = va_arg(args, char *); + item->func = va_arg(args, void *); + item->param1 = va_arg(args, void *); + item->param2 = va_arg(args, int); + + item->item.f_render = itemtype_func_render; + item->item.f_save = NULL; + item->item.f_invoke = itemtype_func_invoke; + item->item.f_load = NULL; + + item->item.w = item->item.front_width = strlen(item->display_text); + item->item.back_width = 0; + item->item.h = 1; + item->item.disabled = false; + + return (item_t *)item; +} + +struct submenu_item +{ + item_t item; + char *display_text; + char *menu; +}; + +void itemtype_submenu_render(menu_t *menu, item_t *item, int state) +{ + struct func_item *it = (struct func_item *)item; + int x,y; + x = menu->x + item->x; + y = menu->y + item->y; + + video_draw_text(x,y, state, it->display_text, item->w); +} + +void itemtype_submenu_invoke(menu_t *menu, item_t *item, int key) +{ + char *men_name; + switch(key) + { + case KEY_ACTIVATE: + case KEY_NEXT_OPTION: + case KEY_PREV_OPTION: + break; + default: + return; + } + + men_name = ((struct submenu_item *)item)->menu; + menu_form_switch_menu(menu->parent_form, men_name); +} + +item_t *itemtype_submenu_alloc(menu_t *menu, va_list args) +{ + struct submenu_item *item = (struct submenu_item *)malloc(sizeof(struct submenu_item)); + if (!item) return NULL; + menu_item_init(&item->item); + + item->display_text = va_arg(args, char *); + item->menu = va_arg(args, char *); + + item->item.f_render = itemtype_submenu_render; + item->item.f_save = NULL; + item->item.f_invoke = itemtype_submenu_invoke; + item->item.f_load = NULL; + + item->item.w = item->item.front_width = strlen(item->display_text); + item->item.back_width = 0; + item->item.h = 1; + item->item.disabled = false; + + return (item_t *)item; +} diff --git a/roms/u-boot-sam460ex/board/ACube/menu/func_items.h b/roms/u-boot-sam460ex/board/ACube/menu/func_items.h new file mode 100644 index 000000000..ae805a9e4 --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/func_items.h @@ -0,0 +1,7 @@ +#ifndef FUNC_ITEMS_H +#define FUNC_ITEMS_H + +item_t *itemtype_func_alloc(menu_t *menu, va_list args); +item_t *itemtype_submenu_alloc(menu_t *menu, va_list args); + +#endif diff --git a/roms/u-boot-sam460ex/board/ACube/menu/label_items.c b/roms/u-boot-sam460ex/board/ACube/menu/label_items.c new file mode 100644 index 000000000..a74d4c32b --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/label_items.c @@ -0,0 +1,47 @@ +#include "menu.h" +#include <stdarg.h> +#include "label_items.h" +#include "creation.h" + +struct label_item +{ + item_t item; + char *display_text; +}; + +void itemtype_label_render(menu_t *menu, item_t *item, int state) +{ + struct label_item *it = (struct label_item *)item; + int x,y; + x = menu->x + item->x; + y = menu->y + item->y; + + video_draw_text(x,y, state, it->display_text, item->w); +} + +void itemtype_label_invoke(menu_t *menu, item_t *item, int key) +{ +} + +item_t *itemtype_label_alloc(menu_t *menu, va_list args) +{ + //char *s; + struct label_item *item = (struct label_item *)malloc(sizeof(struct label_item)); + if (!item) return NULL; + menu_item_init(&item->item); + + item->display_text = va_arg(args, char *); + + item->item.f_render = itemtype_label_render; + item->item.f_save = NULL; + item->item.f_invoke = itemtype_label_invoke; + item->item.f_load = NULL; + + item->item.w = strlen(item->display_text); + item->item.front_width = item->item.w/2; + item->item.back_width = item->item.w - item->item.front_width; + item->item.h = 1; + item->item.disabled = true; + + return (item_t *)item; +} diff --git a/roms/u-boot-sam460ex/board/ACube/menu/label_items.h b/roms/u-boot-sam460ex/board/ACube/menu/label_items.h new file mode 100644 index 000000000..bdc286dbb --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/label_items.h @@ -0,0 +1,6 @@ +#ifndef LABEL_ITEMS_H +#define LABEL_ITEMS_H + +item_t *itemtype_label_alloc(menu_t *menu, va_list args); + +#endif // LABEL_ITEMS_H diff --git a/roms/u-boot-sam460ex/board/ACube/menu/layout.c b/roms/u-boot-sam460ex/board/ACube/menu/layout.c new file mode 100644 index 000000000..f2f5bd3a2 --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/layout.c @@ -0,0 +1,81 @@ +#include "menu.h" +#include "layout.h" + +#define MENU_FIRST_COLUMN 3 +#define MENU_SECOND_COLUMN 44 +#define MENU_TOP 4 +#define MENU_BOTTOM 16 + +void menu_layout(menu_t *menu) +{ + int + x=MENU_FIRST_COLUMN, + y=MENU_TOP, + + max_width = 0, + max_front_width = 0, + max_back_width = 0; + + int + height = 0, + //temp_h, + temp_l; + + item_t* + item; + + if (menu->type == MENUTYPE_POPUP) + { + x = 0; + y = 0; + } + + /* Find size maximums */ + item = (item_t *)(menu->item_list.first); + while (item) + { + if (item->w > max_width) + max_width = item->w; + if (item->front_width > max_front_width) + max_front_width = item->front_width; + if (item->back_width > max_back_width) + max_back_width = item->back_width; + + item = (item_t *)(item->link.next); + } + + /* Layout phase */ + item = (item_t *)(menu->item_list.first); + while (item) + { + item->x = x; + item->y = y; + temp_l = menu->item_spacing + item->h - 1; + y += temp_l; + if (y > MENU_BOTTOM || item->break_after == true) + { + y = MENU_TOP; + x = MENU_SECOND_COLUMN; + } + height += temp_l; + item->w = max_width; + item->front_width = max_front_width; + item->back_width = max_back_width; + item = (item_t *)(item->link.next); + } + + height -= menu->item_spacing; + + /* Set the first item to be the acrive one */ + if (menu->current_item == NULL) + { + menu->current_item = (item_t *)(menu->item_list.first); + while (menu->current_item && menu->current_item->disabled == true) + { + menu->current_item = (item_t *)(menu->current_item->link.next); + } + } + + menu->w = max_width; + menu->h = height; +} diff --git a/roms/u-boot-sam460ex/board/ACube/menu/layout.h b/roms/u-boot-sam460ex/board/ACube/menu/layout.h new file mode 100644 index 000000000..2d04f6504 --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/layout.h @@ -0,0 +1,6 @@ +#ifndef MENU_LAYOUT +#define MENU_LAYOUT + +void menu_layout(menu_t *menu); + +#endif // MENU_LAYOUT. Give me a lot of ??? for this work!! diff --git a/roms/u-boot-sam460ex/board/ACube/menu/list.c b/roms/u-boot-sam460ex/board/ACube/menu/list.c new file mode 100644 index 000000000..eb9997c8d --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/list.c @@ -0,0 +1,37 @@ +//#include "menu.h" +#include "list.h" +void list_init(mylist_t *l) +{ + l->first = NULL; + l->last = NULL; +} + +bool list_empty(mylist_t *l) +{ + if (l->first == NULL) return true; + else return false; +} + +void list_add(mylist_t *l, node_t *n) +{ + if (l->first == NULL) + { + l->first = n; + l->last = n; + n->prev = NULL; + n->next = NULL; + } + else + { + node_t *b = l->last; + l->last = n; + + n->prev = b; + n->next = 0; + + b->next = n; + } +} + + + diff --git a/roms/u-boot-sam460ex/board/ACube/menu/list.h b/roms/u-boot-sam460ex/board/ACube/menu/list.h new file mode 100644 index 000000000..d66edc830 --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/list.h @@ -0,0 +1,39 @@ +#ifndef MENU_LIST_H +#define MENU_LIST_H + +#ifndef bool_defined +#define bool_defined +typedef int bool; +#endif + +#ifndef true +#define true 1 +#endif + +#ifndef false +#define false 0 +#endif + +#ifndef NULL +#define NULL ((void *)0L) +#endif + + +/* List functions */ +typedef struct node_s +{ + struct node_s *prev; + struct node_s *next; +} node_t; + +typedef struct list_s +{ + node_t *first; + node_t *last; +} mylist_t; + +//void list_init(mylist_t *list); +//void list_add(mylist_t *list, node_t *node); +//bool list_empty(mylist_t *list); + +#endif //MENU_LIST_H diff --git a/roms/u-boot-sam460ex/board/ACube/menu/menu.c b/roms/u-boot-sam460ex/board/ACube/menu/menu.c new file mode 100644 index 000000000..35a80e871 --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/menu.c @@ -0,0 +1,374 @@ +#include "menu.h" +#include "creation.h" +#include "layout.h" +#include "list.h" + +form_t *root_form = 0; + +void menu_set_form(form_t *form) +{ + root_form = form; +} + +void menu_draw_help(item_t *item) +{ + char + buffer[80*4], + *p_text, + *p_break, + *p_start; + + int + line = 20; + + bool in_word=true; + + if (!item) return; + + video_clear_box(1,20,78,4,' ',MENUATTR_NORMAL); + + if (item->help_text) + { + /* Reformat help so that it word-wraps */ + buffer[0] = 0; + + strcpy(buffer, item->help_text); + + p_text = p_break = p_start = buffer; + in_word = true; + + for (;;) + { + if (*p_text == ' ' && in_word == true) + { + in_word = false; + p_break = p_text; + } + else if (*p_text != ' ') + { + in_word = true; + } + if ((p_text - p_start >= 72) || *p_text == 0) // flush + { + if (*p_text == '\0') p_break = p_text; + *p_break = 0; + video_draw_text(2,line++, MENUATTR_NORMAL, p_start, -1); + if (*p_text == '\0') return; + p_break++; + while (p_break < p_text && *p_break == ' ') + { + p_break++; + } + p_start = p_break; + if (*p_break == '\0') return; + } + else p_text++; + } + } +} + +void menu_draw(menu_t *menu) +{ + if (menu && menu->needs_layout) + { + menu_layout(menu); + } + if (menu) + { + item_t *item = (item_t *)(menu->item_list.first); + + if (menu->type == MENUTYPE_POPUP) + { + video_clear_box(menu->x-1, menu->y-1, menu->w, menu->h, ' ', MENUATTR_NORMAL); + } + + while (item) + { + item->f_render(menu, item, + (item->disabled==true)?MENUATTR_DISABLED: + (item == menu->current_item)?MENUATTR_HILITE : MENUATTR_ITEM); + item = (item_t *)(item->link.next); + } + if (menu->type == MENUTYPE_FORM) + { + menu_draw_help(menu->current_item); + } + else + { + video_draw_box(SINGLE_BOX, MENUATTR_NORMAL, NULL, 0, menu->x-1, menu->y-1, + menu->w+2, menu->h+3); + } + } +} + +void menu_draw_form(form_t *form) +{ + char + *title; + menu_t + *menu = form->current_menu; + + /* Prefer current menu title if set, otherwise use the form title */ + if (menu && menu->menu_title) title = menu->menu_title; + else if (form->form_title) title = form->form_title; + else title = NULL; //"Untitled"; + + video_draw_box(SINGLE_BOX, MENUATTR_NORMAL, title, 1, 0,0, 80, 19); + video_draw_box(SINGLE_BOX, MENUATTR_NORMAL, NULL, 0, 0, 19, 80, 6); + + /* If we have a menu, draw it too */ + if (menu) + { + video_clear_box(1, 3, 78, 15, ' ', MENUATTR_NORMAL); + menu_draw(menu); + } +} + +void menu_draw_current_form(void) +{ + menu_draw_form(root_form); +} + +void menu_form_switch_menu(form_t *form, char *name) +{ + menu_t *menu = menu_form_find_menu(form, name); + if (!menu) + return; + menu_form_set_menu(form, menu); +} + +void menu_form_popup(form_t *form, menu_t* menu) +{ + if (menu && MENUTYPE_POPUP == menu->type) + { + form->popup_save = form->current_menu; + form->popup_item_save = form->current_menu->current_item; + form->current_menu = menu; + menu_draw(menu); + } +} + +void menu_form_popup_name(form_t *form, char *name) +{ + menu_t *menu = menu_form_find_menu(form, name); + if (!menu) + return; + menu_form_popup(form, menu); +} + +void menu_form_popdown(form_t *form) +{ + if (form->current_menu && form->current_menu->type == MENUTYPE_POPUP) + { + form->current_menu = form->popup_save; + if (form->current_menu) + form->current_menu->current_item = form->popup_item_save; + video_clear_box(1, 3, 78, 15, ' ', MENUATTR_NORMAL); + if (form->current_menu) + menu_draw(form->current_menu); + } +} + +void menu_set_active_item(menu_t *menu, int nr) +{ + item_t + *item = (item_t *)(menu->item_list.first); + + while (item && nr > 0) + { + nr--; + item = (item_t *)(item->link.next); + } + if (nr == 0) + { + menu->current_item = item; + } +} + +static void menu_perform_save(form_t *form) +{ + menu_t + *menu; + + menu = (menu_t *)(form->menu_list.first); + while (menu) + { + item_t + *item; + + item = (item_t *)(menu->item_list.first); + while (item) + { + if (item->f_save) item->f_save(menu, item); + item = (item_t *)(item->link.next); + } + menu = (menu_t *)(menu->link.next); + } +} + +static int leave_select = -1; + +void leave_func(item_t *item, void *dummy, int arg) +{ + leave_select = arg; +} + +menu_t *make_leave_menu(form_t *form) +{ + menu_t + *menu = new_menu(MENUTYPE_POPUP, "Exit Menu", form, NULL); + + if (menu) + { + item_t + *item; + item = menu_item_create(ITEMTYPE_FUNC, menu, "Save settings and exit", leave_func, NULL, EXIT_SAVE_PERMANENT); + item = menu_item_create(ITEMTYPE_FUNC, menu, "Use settings for this session only", leave_func, NULL, EXIT_AND_SAVE); + item = menu_item_create(ITEMTYPE_FUNC, menu, "Leave without saving", leave_func, NULL, EXIT_AND_NO_SAVE); + //item = menu_item_create(ITEMTYPE_FUNC, menu, "Return to menu", leave_func, NULL, EXIT_NOT); + item = menu_item_create(ITEMTYPE_FUNC, menu, "Abort boot and enter U-Boot shell", leave_func, NULL, EXIT_TO_SHELL); + } + + menu_form_add_menu(form, menu); + + menu_set_position(menu, 6, 6); + + return menu; +} + + +bool menu_handle_single_key(form_t *form, int key) +{ + /* + Keys below 10 or so are specially mapped by us to mean one of the functions + of the menu system (like next item, prev item etc). All other keys are verbatim + keypresses that might be needed for e.g. string entry + */ + item_t + *c_item, + *n_item; + menu_t + *menu = form->current_menu; + + switch(key) + { + case KEY_NEXT_ITEM: + /* Move one item forward */ + c_item = menu->current_item; + n_item = (item_t *)(c_item->link.next); + while (n_item && n_item->disabled == true) + { + n_item = (item_t *)(n_item->link.next); + } + + if (n_item) + { + /* redraw the old item un-highlit */ + c_item->f_render(menu, c_item, MENUATTR_ITEM); + n_item->f_render(menu, n_item, MENUATTR_HILITE); + menu_draw_help(n_item); + menu->current_item = n_item; + } + break; + case KEY_PREV_ITEM: + /* Move one item backward */ + c_item = menu->current_item; + n_item = (item_t *)(c_item->link.prev); + while (n_item && n_item->disabled == true) + { + n_item = (item_t *)(n_item->link.prev); + } + if (n_item) + { + /* redraw the old item un-highlit */ + c_item->f_render(menu, c_item, MENUATTR_ITEM); + n_item->f_render(menu, n_item, MENUATTR_HILITE); + menu_draw_help(n_item); + menu->current_item = n_item; + } + break; + case KEY_ABORT: + if (menu->type == MENUTYPE_POPUP) + { + menu_form_popdown(form); + } + else + { + if (menu->parent_menu) + { + menu_form_switch_menu(menu->parent_form, menu->parent_menu); + } + else + { + /* TODO: Implement exit from menu */ + menu_form_popup_name(root_form, "Exit Menu"); + return true; + } + } + break; + default: + if (menu->current_item) + { + menu->current_item->f_invoke(menu, menu->current_item, key); + } + if (key == KEY_ACTIVATE && menu->type == MENUTYPE_POPUP) + { + menu_form_popdown(form); + /* Check if we want to exit */ + if (leave_select != -1) + { + switch(leave_select) + { + case EXIT_AND_NO_SAVE: + return false; + case EXIT_SAVE_PERMANENT: + menu_perform_save(form); +#ifndef SIM + saveenv(); +#endif + return false; + case EXIT_AND_SAVE: + menu_perform_save(form); + return false; + case EXIT_NOT: + return true; + case EXIT_TO_SHELL: + { + char *mboot = getenv("menuboot_cmd"); + if ((mboot) && (strlen(mboot)>2)) SETENV("menuboot_cmd", "noboot"); + else SETENV("menuboot_cmd", "boota"); + return false; + } + } + } + } + break; + } + + return true; +} + + +void menu_do(bool do_leave_menu) +{ + bool running=true; + int key; + + running = true; + leave_select = -1; + + if (do_leave_menu) + make_leave_menu(root_form); + + if (root_form) + { + menu_draw_form(root_form); + + while (running) + { + key = video_get_key(); + running = menu_handle_single_key(root_form, key); + } + } +} + diff --git a/roms/u-boot-sam460ex/board/ACube/menu/menu.h b/roms/u-boot-sam460ex/board/ACube/menu/menu.h new file mode 100644 index 000000000..0b5d71733 --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/menu.h @@ -0,0 +1,279 @@ +#ifndef MENU_H +#define MENU_H + +#ifdef SIM +#include <stdlib.h> +#else +#include <common.h> +#endif + +#include "list.h" + +#ifdef SIM +#define GETENV(x) getenv(x) +#define SETENV(x,y) setenv(x,y,1) +#else +#define GETENV(x) getenv(x) +#define SETENV(x,y) setenv(x,y) +#endif + +#ifndef NULL +#define NULL ((void *)0L) +#endif + +/* Menu attributes */ +#define MENUATTR_NORMAL 0 /* Attribute used by standard menus */ +#define MENUATTR_ITEM 1 /* Attribute for menu items (normal) */ +#define MENUATTR_HILITE 2 /* Attribute for highlighted menu items */ +#define MENUATTR_DISABLED 3 /* Attribute for disabled menu items */ + +#ifndef bool_defined +#define bool_defined +typedef int bool; +#endif + +#ifndef true +#define true 1 +#endif + +#ifndef false +#define false 0 +#endif + +#define MAX_MENUS 30 + +#define KEY_NONE 0 /* No or false key pressed */ +#define KEY_NEXT_OPTION 1 /* Page Down, Arrow right */ +#define KEY_PREV_OPTION 2 /* Page Up, Arrow left */ +#define KEY_NEXT_ITEM 3 /* Arrow down */ +#define KEY_PREV_ITEM 4 /* Arrow up */ +#define KEY_ABORT 5 /* ESC */ +#define KEY_ACTIVATE 6 /* Return */ +#define KEY_DELETE 7 /* Backspace */ +#define KEY_F1 8 + +#define EXIT_AND_SAVE 0 +#define EXIT_AND_NO_SAVE 1 +#define EXIT_NOT 2 +#define EXIT_SAVE_PERMANENT 3 +#define EXIT_TO_SHELL 4 + + +#define SINGLE_BOX 0 +#define DOUBLE_BOX 1 + +#ifdef SIM +#include "sim.h" +#endif + +struct item_s; +struct menu_s; + +typedef void (*load_func)(struct menu_s *menu, struct item_s *item); +typedef void (*save_func)(struct menu_s *menu, struct item_s *item); +typedef void (*render_func)(struct menu_s *menu, struct item_s *item, int state); +typedef void (*invoke_func)(struct menu_s *menu, struct item_s *item, int key); + +typedef struct item_s +{ + node_t link; /* Link for chaining */ + int x,y; /* Position */ + int w,h; /* Size */ + char *help_text; /* Help text do display */ + int front_width; /* Width of front display matter */ + int back_width; /* Width of option data or 0 */ + bool disabled; /* Wether this item is active or disabled */ + bool break_after; /* After this item break to next column */ + load_func f_load; /* Functio to load the setting */ + render_func f_render; /* Function to render contents */ + save_func f_save; /* Function to save the setting */ + invoke_func f_invoke; /* Function to handle key event */ +} item_t; + + +#define MENUTYPE_FORM 1 /* Form-integrated menu */ +#define MENUTYPE_POPUP 2 /* Popup menu (drawing differs) */ + +typedef struct menu_s +{ + node_t link; + char *menu_title; /* Title of the menu */ + int type; /* Type of menu */ + bool two_colums; /* True for two-column menus */ + int x,y,w,h; /* Coordinates and extends */ + void *user_data; /* User data of menu */ + bool needs_layout; + int item_spacing; + item_t *current_item; /* current item */ + mylist_t item_list; + + char *parent_menu; /* Where to return when ESC is pressed */ + struct form_s *parent_form; /* Form where this is currently being displayed */ +} menu_t; + +typedef struct form_s +{ + char *form_title; /* Title of the form */ + menu_t *current_menu; /* Menu that is active */ + menu_t *popup_save; /* Backup when popup is active */ + item_t *popup_item_save; /* Backup which item was active */ + + int menu_stack_ptr; /* Stack pointer */ + menu_t *menu_stack[MAX_MENUS];/* Previous menus */ + + mylist_t menu_list; +} form_t; + +void menu_draw_current_form(void); +void menu_init(void); +void menu_set_active_item(menu_t *menu, int nr); +void menu_draw_form(form_t *form); +void menu_form_switch_menu(form_t *form, char *name); +void menu_form_popup(form_t *form, menu_t* menu); + +/* Utility functions */ + + +void leave_func(item_t *item, void *dummy, int arg); +void menu_draw_help(item_t *item); +void menu_set_form(form_t *form); +void menu_do(bool do_leave_menu); + + +/* Item types */ + +/* + * Item: Boolean from a console var + * Creation args: + * (char *) display name + * (char *) variable name + * (char *) positive text ("yes", "true", "enabled", "on") + * (char *) negative text ("no", "false", "disabled", "off") + * int default if unset (0=negative, !0=positive) + */ +//#define ITEMTYPE_BOOL_CVAR 0 + +/* + * Item: Invoke-a-function item + * Creation args: + * (char *) display name + * (void *)(item_t *, void *, int) + * Function to invoke + * (void *) First parameter to be passed + * int Second parameter to be passed + */ +#define ITEMTYPE_FUNC 1 + +/* + * Item: Submenu + * Creation args: + * (char *) display name + * (char *) menu to change to + */ +#define ITEMTYPE_SUBMENU 2 + +/* + * Item: Popup Choice + * Creation args: + * (char *) display name + * int default choice + * (void *) hook user data. + * (void *) Save hook. See below + * (void *) Load hook. See below + * (popup_entry_t *) pointer to an array of popup_entry structures. + * Terminate with all entries set to NULL. + * + * Save/Load hook: + * Thes functions are called whenever the item needs to be loaded or saved. + * The prototypes are: + * + * int load(void *user_data, popup_entry_t *entries); + * void save(void *user_data, popup_entry_t *selected); + * + * Load: The function is invoked with the third creation argument (user data) and + * a pointer to the popup_entry** specified as the sixth argument. It should + * return the index of the entry that would become the selected/active entry. + * + * Save: The function is invoked with the user data and a pointer to the selected + * entry in the popup. It should save the value to an appropriate place, e.g. + * an environment variable. + * + */ +#define ITEMTYPE_POPUP 3 + +typedef struct _popup_entry +{ + char *display_text; /* What the entry should display */ + char *value_text; /* What the entry should represent. For the hooks only */ + void *user_data; /* Additional hook user data. Use as you wish */ +} popup_entry_t; + + +/* + * Item: String from a console variable + * Creation args: + * (char *) display name + * (char *) variable name + * (char *) default if unset + */ +#define ITEMTYPE_STRING_CVAR 4 + +/* + * Item: Unselectable label + * Creatation args: + * (char *) display name + */ +#define ITEMTYPE_LABEL 5 + +/* + * Item: Numerical value editor + * Creation args: + * (char *) display name + * (int) default value + * (int) stepping rate + * (int) lower bound + * (int) upper bound + * (int) 0=decimal, 1=hex + * (void *) load hook (see below) + * (void *) save hook (see below) + * (void *) param 1 for hooks + * int param 2 for hooks + * + * Hooks work similar to popup types. The prototype for the hooks is + * int load(void *param1, int param2, int default); + * void save(void *param1, int param2, int value); + * If load is unable to load, it should return default. + */ +//#define ITEMTYPE_NUMERIC 6 + +/* + * Item: Configuration register editor + * Creation args: + * (char *) Display name + * (void *) register descriptor pointer (see below) + */ +//#define ITEMTYPE_REGISTER 7 +/* +typedef struct +{ + char *register_name; + int config_offset; + int config_type; + int value_type; + int bus; + int devfn; + void *menu_page; +} articia_register_t; + +typedef struct +{ + char *title; + articia_register_t *registers; +} articia_menu_page_t; + +enum +{ + CONFIG_DWORD = 0, CONFIG_WORD = 1, CONFIG_BYTE = 2, TYPE_HEX = 0, TYPE_DEC = 1 +}; +*/ +#endif diff --git a/roms/u-boot-sam460ex/board/ACube/menu/popup_items.c b/roms/u-boot-sam460ex/board/ACube/menu/popup_items.c new file mode 100644 index 000000000..34796533c --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/popup_items.c @@ -0,0 +1,150 @@ +#include "menu.h" +#include <stdarg.h> +#include "popup_items.h" +#include "creation.h" + +#define MAX_POPUP_SIZE 12 +#define MAX_POPUP_STRING 20 + +struct popup_item +{ + item_t item; + char *display_text; + menu_t *menu_handle; + int choice; + int max_choice; + void (*save_hook)(void *, popup_entry_t *entry); + int (*load_hook)(void *, popup_entry_t *); + void *hook_user_data; + popup_entry_t *entries; +}; + +void itemtype_popup_render(menu_t *menu, item_t *item, int state) +{ + struct popup_item *it = (struct popup_item *)item; + int x,y; + x = menu->x + item->x; + y = menu->y + item->y; + + video_draw_text(x,y, MENUATTR_NORMAL, it->display_text, item->w); + video_draw_text(x+item->front_width,y, MENUATTR_NORMAL, ":", -1); + video_draw_text(x+item->front_width+1,y,state, + it->choice >= 0 ? it->entries[it->choice].display_text : "<none>", + item->back_width); +} + +void itemtype_popup_invoke(menu_t *menu, item_t *item, int key) +{ + struct popup_item + *it = (struct popup_item *)item; + + switch(key) + { + case KEY_ACTIVATE: + menu_set_active_item(it->menu_handle, it->choice); + menu_set_position(it->menu_handle, + menu->y+item->y, menu->x+item->x+item->front_width+1); + menu_form_popup(menu->parent_form, it->menu_handle); + break; + case KEY_NEXT_OPTION: + if (it->choice < it->max_choice) + { + itemtype_popup_render(menu, item, MENUATTR_HILITE); + it->choice++; + itemtype_popup_render(menu, item, MENUATTR_HILITE); + } + break; + case KEY_PREV_OPTION: + if (it->choice > 0) + { + itemtype_popup_render(menu, item, MENUATTR_HILITE); + it->choice--; + itemtype_popup_render(menu, item, MENUATTR_HILITE); + } + break; + default: + return; + } +} + +void itemtype_popup_save(menu_t *menu, item_t *item) +{ + struct popup_item *it = (struct popup_item *)item; + if (it->save_hook) + it->save_hook(it->hook_user_data, &it->entries[it->choice]); +} + +void itemtype_popup_load(menu_t *menu, item_t *item) +{ + struct popup_item *it = (struct popup_item *)item; + if (it->load_hook) + { + int i = it->load_hook(it->hook_user_data, it->entries); + if (i != -1) it->choice = i; + } + item->f_save = itemtype_popup_save; + item->f_load = 0; +} + + +static void item_func(item_t *item, void *param1, int param2) +{ + *(int *)param1 = param2; +} + +item_t *itemtype_popup_alloc(menu_t *menu, va_list args) +{ + menu_t + *popup; + item_t + *newitem; + popup_entry_t + *e; + int + i, + maximum_width = 0, + m; + + struct popup_item + *item = (struct popup_item *)malloc(sizeof(struct popup_item) + MAX_POPUP_STRING * MAX_POPUP_SIZE ); + + if (!item) return NULL; + menu_item_init(&item->item); + + item->display_text = va_arg(args, char *); + item->choice = va_arg(args, int); + item->hook_user_data = va_arg(args, void *); + item->save_hook = va_arg(args, void *); + item->load_hook = va_arg(args, void *); + item->entries = va_arg(args, popup_entry_t*); + + popup = new_menu(MENUTYPE_POPUP, NULL, menu->parent_form, NULL); + + i=0; + e = item->entries; + do + { + if (e->display_text == NULL) break; + m = strlen(e->display_text); + if (m > maximum_width) maximum_width = m; + newitem = menu_item_create(ITEMTYPE_FUNC, popup, e->display_text, item_func, &(item->choice),i); + i++; + e++; + } while (1); + + item->max_choice = i-1; + + item->menu_handle = popup; + + item->item.f_render = itemtype_popup_render; + item->item.f_save = 0; + item->item.f_invoke = itemtype_popup_invoke; + item->item.f_load = itemtype_popup_load; + + item->item.w = item->item.front_width = strlen(item->display_text); + item->item.back_width = maximum_width; + item->item.h = 1; + item->item.disabled = false; + + return (item_t *)item; +} diff --git a/roms/u-boot-sam460ex/board/ACube/menu/popup_items.h b/roms/u-boot-sam460ex/board/ACube/menu/popup_items.h new file mode 100644 index 000000000..66cb6b0cb --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/popup_items.h @@ -0,0 +1,6 @@ +#ifndef POPUP_ITEMS_H +#define POPUP_ITEMS_H + +item_t *itemtype_popup_alloc(menu_t *menu, va_list args); + +#endif diff --git a/roms/u-boot-sam460ex/board/ACube/menu/string_edit.c b/roms/u-boot-sam460ex/board/ACube/menu/string_edit.c new file mode 100644 index 000000000..64d53a019 --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/string_edit.c @@ -0,0 +1,177 @@ +#include "menu.h" +#include "string_edit.h" + +//static int num_lines = 0; +static int x_pos=0, y_pos=0; +static int width = 0, height = 0; +static int cursor_pos = 0; +static char *buffer; +static char *prompt; +static int buffer_length; +static char backup[1024]; + +#define STRINGBOX_WIDTH 70 +#define STRINGBOX_HEIGHT 4 +#define STRINGBOX_X 5 +#define STRINGBOX_Y 5 + +static void string_edit_draw(void) +{ + int + i,j, + length = buffer_length, + attr = MENUATTR_NORMAL; + + char + c; + + //int cursor_x = 0, cursor_y = 0; + + for (i=0; i<height; i++) + { + for (j=0; j<width; j++) + { + int + offset = j+i*width; + + if (offset > length) + c = ' '; + else + c = buffer[offset]; + + if (offset == cursor_pos) +#if 1 //def SIM + attr = MENUATTR_HILITE; + else + attr = MENUATTR_NORMAL; +#else + { + cursor_x = x_pos+j; + cursor_y = y_pos+i; + } +#endif + video_draw_text(x_pos + j, y_pos + i, attr, &c, 1); + } + } +#if 0 //ndef SIM + video_set_cursor(cursor_y, cursor_y); +#endif +} + +static void string_clear_frame(void) +{ + video_clear_box(STRINGBOX_X-2, STRINGBOX_Y-2, + STRINGBOX_WIDTH+4, STRINGBOX_HEIGHT+4, + ' ', MENUATTR_NORMAL); +} + +static void string_draw_frame(void) +{ + string_clear_frame(); + video_draw_box(SINGLE_BOX, MENUATTR_NORMAL, prompt, 0, + STRINGBOX_X-2, STRINGBOX_Y-2, + STRINGBOX_WIDTH+4, STRINGBOX_HEIGHT+4); +} + +static void backspace(void) +{ + int + i; + + char + *s; + + if (cursor_pos == 0) return; + if (cursor_pos == buffer_length) + { + buffer_length--; + cursor_pos--; + buffer[buffer_length] = 0; + } + else + { + s = buffer+cursor_pos-1; + for (i = 0; i < buffer_length - cursor_pos + 1; i++) + { + *s = *(s+1); + s++; + } + cursor_pos--; + buffer_length--; + } +} + +static void insert(int key) +{ + int + i; + + char + *s; + + s = buffer + buffer_length; + for (i = 0; i < buffer_length - cursor_pos + 1; i++) + { + *(s+1) = *s; + s--; + } + *(buffer + cursor_pos) = (char)key; + cursor_pos++; + buffer_length++; +} + +bool menu_string_edit(char *_prompt, char *string, int buffersize) +{ + int + key; + + prompt = _prompt; + x_pos = STRINGBOX_X; + y_pos = STRINGBOX_Y; + width = STRINGBOX_WIDTH; + height = STRINGBOX_HEIGHT; + + buffer = string; + strcpy(backup, string); + + buffer_length = cursor_pos = strlen(buffer); + + string_draw_frame(); + do + { + string_edit_draw(); + key = video_get_key(); + switch(key) + { + case KEY_ABORT: + strcpy(string, backup); + string_clear_frame(); + menu_draw_current_form(); + return false; + case KEY_ACTIVATE: + string_clear_frame(); + menu_draw_current_form(); + return true; + case KEY_NEXT_OPTION: + cursor_pos++; + if (cursor_pos > buffer_length) cursor_pos = buffer_length; + break; + case KEY_PREV_OPTION: + cursor_pos--; + if (cursor_pos < 0) cursor_pos = 0; + break; + case KEY_DELETE: + /* Backspace */ + backspace(); + break; + default: + if (key >= 32 && key <= 127) + { + insert(key); + } + break; + } + } while (1); + + return false; +} diff --git a/roms/u-boot-sam460ex/board/ACube/menu/string_edit.h b/roms/u-boot-sam460ex/board/ACube/menu/string_edit.h new file mode 100644 index 000000000..efd09b97b --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/string_edit.h @@ -0,0 +1,6 @@ +#ifndef STRING_EDIT_H +#define STRING_EDIT_H + +bool menu_string_edit(char *_prompt, char *string, int buffersize); + +#endif diff --git a/roms/u-boot-sam460ex/board/ACube/menu/string_items.c b/roms/u-boot-sam460ex/board/ACube/menu/string_items.c new file mode 100644 index 000000000..1f04cbe0c --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/string_items.c @@ -0,0 +1,133 @@ +#include "menu.h" +#include <stdarg.h> +#include "string_items.h" +#include "string_edit.h" +#include "creation.h" + +#define MAX_DISPLAY_WIDTH 40 + +void itemtype_string_cvar_save(menu_t *menu, item_t *item); +void itemtype_string_cvar_load(menu_t *menu, item_t *item); + +struct string_cvar_item +{ + item_t item; + char *display_text; + char *var_name; + char value[512]; + char *def_value; + int base; +}; + +void itemtype_string_cvar_render(menu_t *menu, item_t *item, int state) +{ + struct string_cvar_item + *it = (struct string_cvar_item *)item; + + int + x = menu->x + item->x, + y = menu->y + item->y, + difference = 0; + + char + *buffer = it->value + it->base; + + video_draw_text(x,y, MENUATTR_NORMAL, it->display_text, -1); + video_draw_text(x+item->front_width,y, MENUATTR_NORMAL, ":", -1); + + x +=item->front_width+1; + + if (it->base) + difference ++; + + if (strlen(it->value + it->base) >= MAX_DISPLAY_WIDTH) + difference ++; + + if (it->base) + { + video_draw_text(x,y,state, "<", 1); + x++; + } + + video_draw_text(x,y,state, buffer, item->back_width - difference); + x += item->back_width - difference; + + if (strlen(it->value + it->base) >= MAX_DISPLAY_WIDTH) + { + video_draw_text(x, y, state, ">", 1); + } +} + +void itemtype_string_cvar_invoke(menu_t *menu, item_t *item, int key) +{ + struct string_cvar_item *it = (struct string_cvar_item *)item; + switch(key) + { + case KEY_ACTIVATE: + menu_string_edit(it->display_text, it->value, 512); + break; + case KEY_PREV_OPTION: + if (it->base > 0) it->base--; + if (it->base == 1) it->base = 0; + itemtype_string_cvar_render(menu, item, MENUATTR_HILITE); + break; + case KEY_NEXT_OPTION: + if (strlen(it->value) < MAX_DISPLAY_WIDTH) break; + if (it->base <= (strlen(it->value) - MAX_DISPLAY_WIDTH)) + { + if (it->base == 0) it->base = 1; + it->base++; + itemtype_string_cvar_render(menu, item, MENUATTR_HILITE); + } + break; + } +} + +void itemtype_string_cvar_load(menu_t *menu, item_t *item) +{ + struct string_cvar_item *it = (struct string_cvar_item *)item; + char *s; + s = GETENV(it->var_name); + if (s) + { + strcpy(it->value, s); + } + else strcpy(it->value, it->def_value); + item->f_save = itemtype_string_cvar_save; + item->f_load = 0; +} + +void itemtype_string_cvar_save(menu_t *menu, item_t *item) +{ + struct string_cvar_item *it = (struct string_cvar_item *)item; + + SETENV(it->var_name, it->value); +} + +item_t *itemtype_string_cvar_alloc(menu_t *menu, va_list args) +{ + //int a,b; + struct string_cvar_item *item = (struct string_cvar_item *)malloc(sizeof(struct string_cvar_item)); + if (!item) return NULL; + + menu_item_init(&item->item); + + item->display_text = va_arg(args, char *); + item->var_name = va_arg(args, char *); + item->def_value = va_arg(args, char *); + item->value[0] = 0; + item->base = 0; + + item->item.f_render = itemtype_string_cvar_render; + item->item.f_save = 0; + item->item.f_invoke = itemtype_string_cvar_invoke; + item->item.f_load = itemtype_string_cvar_load; + + item->item.front_width = strlen(item->display_text); + item->item.back_width = MAX_DISPLAY_WIDTH; + + item->item.w = item->item.back_width + item->item.front_width + 1; + item->item.h = 1; + + return (item_t *)item; +} diff --git a/roms/u-boot-sam460ex/board/ACube/menu/string_items.h b/roms/u-boot-sam460ex/board/ACube/menu/string_items.h new file mode 100644 index 000000000..04695763a --- /dev/null +++ b/roms/u-boot-sam460ex/board/ACube/menu/string_items.h @@ -0,0 +1,6 @@ +#ifndef STRING_ITEMS_H +#define STRING_ITEMS_H + +item_t *itemtype_string_cvar_alloc(menu_t *menu, va_list args); + +#endif |