From f3499c2a05d8031b3b01a1b8c7baa2454521af3e Mon Sep 17 00:00:00 2001 From: Jacob Wang Date: Wed, 30 Apr 2025 17:14:10 +0800 Subject: [PATCH 1/8] [BUG]update to grub2-2.02-165 to #IC588S update to grub2-2.02-165 for bugfix Signed-off-by: Jacob Wang --- ...Add-bigtime-incompat-feature-support.patch | 156 + ...needsrepair-incompat-feature-support.patch | 81 + ...adable-filesystem-with-v4-superblock.patch | 121 + 0670-fs-Remove-trailing-whitespaces.patch | 1666 ++++++++ ...s-xfs-Fix-memory-leaks-in-XFS-module.patch | 50 + ...-short-form-directory-data-boundary-.patch | 51 + ...xfs-Fix-XFS-directory-extent-parsing.patch | 171 + ...-extent-counters-incompat-feature-su.patch | 119 + ...n-continuous-data-blocks-in-director.patch | 57 + ...-extent-counters-incompat-feature-su.patch | 48 + ...ut-of-bounds-read-for-inline-and-ext.patch | 65 + 1001-bls-make-list.patch | 119 - ...-support-and-update-interface-to-v40.patch | 3444 ----------------- ...the-password-getter-and-additional-a.patch | 173 - ...odisk-add-OS-provided-secret-support.patch | 206 - ...retrieving-the-EFI-secret-for-crypto.patch | 217 -- ...ate-patches-in-sync-with-loongarch64.patch | 2815 -------------- 20-grub.install | 2 +- grub.macros | 14 +- grub.patches | 19 +- grub2.spec | 42 +- 21 files changed, 2615 insertions(+), 7021 deletions(-) create mode 100644 0667-fs-xfs-Add-bigtime-incompat-feature-support.patch create mode 100644 0668-fs-xfs-Add-needsrepair-incompat-feature-support.patch create mode 100644 0669-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch create mode 100644 0670-fs-Remove-trailing-whitespaces.patch create mode 100644 0671-fs-xfs-Fix-memory-leaks-in-XFS-module.patch create mode 100644 0672-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch create mode 100644 0673-fs-xfs-Fix-XFS-directory-extent-parsing.patch create mode 100644 0674-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch create mode 100644 0675-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch create mode 100644 0676-fs-xfs-fix-large-extent-counters-incompat-feature-su.patch create mode 100644 0677-fs-ext2-Rework-out-of-bounds-read-for-inline-and-ext.patch delete mode 100644 1001-bls-make-list.patch delete mode 100644 1002-Add-LoongArch64-support-and-update-interface-to-v40.patch delete mode 100644 1003-cryptodisk-make-the-password-getter-and-additional-a.patch delete mode 100644 1004-cryptodisk-add-OS-provided-secret-support.patch delete mode 100644 1005-efi-Add-API-for-retrieving-the-EFI-secret-for-crypto.patch delete mode 100644 1006-Update-patches-in-sync-with-loongarch64.patch diff --git a/0667-fs-xfs-Add-bigtime-incompat-feature-support.patch b/0667-fs-xfs-Add-bigtime-incompat-feature-support.patch new file mode 100644 index 0000000..c1814eb --- /dev/null +++ b/0667-fs-xfs-Add-bigtime-incompat-feature-support.patch @@ -0,0 +1,156 @@ +From 631bfec4c070c220e86d2e2d8e6d6aa38c130ef1 Mon Sep 17 00:00:00 2001 +From: Carlos Maiolino +Date: Mon, 24 May 2021 19:40:06 +0200 +Subject: [PATCH 667/668] fs/xfs: Add bigtime incompat feature support + +The XFS filesystem supports a bigtime feature to overcome y2038 problem. +This patch makes the GRUB able to support the XFS filesystems with this +feature enabled. + +The XFS counter for the bigtime enabled timestamps starts at 0, which +translates to GRUB_INT32_MIN (Dec 31 20:45:52 UTC 1901) in the legacy +timestamps. The conversion to Unix timestamps is made before passing the +value to other GRUB functions. + +For this to work properly, GRUB requires an access to flags2 field in the +XFS ondisk inode. So, the grub_xfs_inode structure has been updated to +cover full ondisk inode. + +Signed-off-by: Carlos Maiolino +Signed-off-by: Javier Martinez Canillas +Reviewed-by: Daniel Kiper +--- + grub-core/fs/xfs.c | 49 ++++++++++++++++++++++++++++++++++++--------- + include/grub/time.h | 2 ++ + 2 files changed, 42 insertions(+), 9 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 887392c..8c23944 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -75,10 +76,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); + XFS_SB_VERSION2_PROJID32BIT | \ + XFS_SB_VERSION2_FTYPE) + ++/* Inode flags2 flags */ ++#define XFS_DIFLAG2_BIGTIME_BIT 3 ++#define XFS_DIFLAG2_BIGTIME (1 << XFS_DIFLAG2_BIGTIME_BIT) ++ + /* incompat feature flags */ + #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ + #define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ + #define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ ++#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */ + + /* + * Directory entries with ftype are explicitly handled by GRUB code. +@@ -92,7 +98,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); + #define XFS_SB_FEAT_INCOMPAT_SUPPORTED \ + (XFS_SB_FEAT_INCOMPAT_FTYPE | \ + XFS_SB_FEAT_INCOMPAT_SPINODES | \ +- XFS_SB_FEAT_INCOMPAT_META_UUID) ++ XFS_SB_FEAT_INCOMPAT_META_UUID | \ ++ XFS_SB_FEAT_INCOMPAT_BIGTIME) + + struct grub_xfs_sblock + { +@@ -177,7 +184,7 @@ struct grub_xfs_btree_root + grub_uint64_t keys[1]; + } GRUB_PACKED; + +-struct grub_xfs_time ++struct grub_xfs_time_legacy + { + grub_uint32_t sec; + grub_uint32_t nanosec; +@@ -190,20 +197,23 @@ struct grub_xfs_inode + grub_uint8_t version; + grub_uint8_t format; + grub_uint8_t unused2[26]; +- struct grub_xfs_time atime; +- struct grub_xfs_time mtime; +- struct grub_xfs_time ctime; ++ grub_uint64_t atime; ++ grub_uint64_t mtime; ++ grub_uint64_t ctime; + grub_uint64_t size; + grub_uint64_t nblocks; + grub_uint32_t extsize; + grub_uint32_t nextents; + grub_uint16_t unused3; + grub_uint8_t fork_offset; +- grub_uint8_t unused4[17]; ++ grub_uint8_t unused4[37]; ++ grub_uint64_t flags2; ++ grub_uint8_t unused5[48]; + } GRUB_PACKED; + +-#define XFS_V2_INODE_SIZE sizeof(struct grub_xfs_inode) +-#define XFS_V3_INODE_SIZE (XFS_V2_INODE_SIZE + 76) ++#define XFS_V3_INODE_SIZE sizeof(struct grub_xfs_inode) ++/* Size of struct grub_xfs_inode until fork_offset (included). */ ++#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 92) + + struct grub_xfs_dirblock_tail + { +@@ -1009,6 +1019,27 @@ struct grub_xfs_dir_ctx + void *hook_data; + }; + ++/* Bigtime inodes helpers. */ ++#define XFS_BIGTIME_EPOCH_OFFSET (-(grub_int64_t) GRUB_INT32_MIN) ++ ++static int grub_xfs_inode_has_bigtime (const struct grub_xfs_inode *inode) ++{ ++ return inode->version >= 3 && ++ (inode->flags2 & grub_cpu_to_be64_compile_time (XFS_DIFLAG2_BIGTIME)); ++} ++ ++static grub_int64_t ++grub_xfs_get_inode_time (struct grub_xfs_inode *inode) ++{ ++ struct grub_xfs_time_legacy *lts; ++ ++ if (grub_xfs_inode_has_bigtime (inode)) ++ return grub_divmod64 (grub_be_to_cpu64 (inode->mtime), NSEC_PER_SEC, NULL) - XFS_BIGTIME_EPOCH_OFFSET; ++ ++ lts = (struct grub_xfs_time_legacy *) &inode->mtime; ++ return grub_be_to_cpu32 (lts->sec); ++} ++ + /* Helper for grub_xfs_dir. */ + static int + grub_xfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, +@@ -1021,7 +1052,7 @@ grub_xfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + if (node->inode_read) + { + info.mtimeset = 1; +- info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec); ++ info.mtime = grub_xfs_get_inode_time (&node->inode); + } + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + grub_free (node); +diff --git a/include/grub/time.h b/include/grub/time.h +index c919c1f..32f0afa 100644 +--- a/include/grub/time.h ++++ b/include/grub/time.h +@@ -30,6 +30,8 @@ grub_cpu_idle(void) + } + #endif + ++#define NSEC_PER_SEC ((grub_int64_t) 1000000000) ++ + void EXPORT_FUNC(grub_millisleep) (grub_uint32_t ms); + grub_uint64_t EXPORT_FUNC(grub_get_time_ms) (void); + +-- +2.43.5 + diff --git a/0668-fs-xfs-Add-needsrepair-incompat-feature-support.patch b/0668-fs-xfs-Add-needsrepair-incompat-feature-support.patch new file mode 100644 index 0000000..57bdbb4 --- /dev/null +++ b/0668-fs-xfs-Add-needsrepair-incompat-feature-support.patch @@ -0,0 +1,81 @@ +From b03ffdb85eca0a5a632c6c5bbeea52373d2fea69 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Mon, 24 May 2021 19:40:07 +0200 +Subject: [PATCH 668/668] fs/xfs: Add needsrepair incompat feature support + +The XFS now has an incompat feature flag to indicate that a filesystem +needs to be repaired. The Linux kernel refuses to mount the filesystem +that has it set and only the xfs_repair tool is able to clear that flag. + +The GRUB doesn't have the concept of mounting filesystems and just +attempts to read the files. But it does some sanity checking before +attempting to read from the filesystem. Among the things which are tested, +is if the super block only has set of incompatible features flags that +are supported by GRUB. If it contains any flags that are not listed as +supported, reading the XFS filesystem fails. + +Since the GRUB doesn't attempt to detect if the filesystem is inconsistent +nor replays the journal, the filesystem access is a best effort. For this +reason, ignore if the filesystem needs to be repaired and just print a debug +message. That way, if reading or booting fails later, the user is able to +figure out that the failures can be related to broken XFS filesystem. + +Suggested-by: Eric Sandeen +Signed-off-by: Javier Martinez Canillas +Reviewed-by: Daniel Kiper +--- + grub-core/fs/xfs.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 8c23944..f113216 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -85,6 +85,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + #define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ + #define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ + #define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */ ++#define XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR (1 << 4) /* needs xfs_repair */ + + /* + * Directory entries with ftype are explicitly handled by GRUB code. +@@ -99,7 +100,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); + (XFS_SB_FEAT_INCOMPAT_FTYPE | \ + XFS_SB_FEAT_INCOMPAT_SPINODES | \ + XFS_SB_FEAT_INCOMPAT_META_UUID | \ +- XFS_SB_FEAT_INCOMPAT_BIGTIME) ++ XFS_SB_FEAT_INCOMPAT_BIGTIME | \ ++ XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR) + + struct grub_xfs_sblock + { +@@ -313,6 +315,16 @@ static int grub_xfs_sb_valid(struct grub_xfs_data *data) + return 0; + } + ++static int ++grub_xfs_sb_needs_repair (struct grub_xfs_data *data) ++{ ++ return ((data->sblock.version & ++ grub_cpu_to_be16_compile_time (XFS_SB_VERSION_NUMBITS)) == ++ grub_cpu_to_be16_compile_time (XFS_SB_VERSION_5) && ++ (data->sblock.sb_features_incompat & ++ grub_cpu_to_be32_compile_time (XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR))); ++} ++ + /* Filetype information as used in inodes. */ + #define FILETYPE_INO_MASK 0170000 + #define FILETYPE_INO_REG 0100000 +@@ -975,6 +987,9 @@ grub_xfs_mount (grub_disk_t disk) + if (!grub_xfs_sb_valid(data)) + goto fail; + ++ if (grub_xfs_sb_needs_repair (data)) ++ grub_dprintf ("xfs", "XFS filesystem needs repair, boot may fail\n"); ++ + if (grub_add (grub_xfs_inode_size (data), + sizeof (struct grub_xfs_data) - sizeof (struct grub_xfs_inode) + 1, &sz)) + goto fail; +-- +2.43.5 + diff --git a/0669-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch b/0669-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch new file mode 100644 index 0000000..dab9126 --- /dev/null +++ b/0669-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch @@ -0,0 +1,121 @@ +From e89ae8eac88f240d757f812bebac1b46e62222bc Mon Sep 17 00:00:00 2001 +From: Erwan Velu +Date: Wed, 25 Aug 2021 15:31:52 +0200 +Subject: [PATCH 669/676] fs/xfs: Fix unreadable filesystem with v4 superblock + +The commit 8b1e5d193 (fs/xfs: Add bigtime incompat feature support) +introduced the bigtime support by adding some features in v3 inodes. +This change extended grub_xfs_inode struct by 76 bytes but also changed +the computation of XFS_V2_INODE_SIZE and XFS_V3_INODE_SIZE. Prior this +commit, XFS_V2_INODE_SIZE was 100 bytes. After the commit it's 84 bytes +XFS_V2_INODE_SIZE becomes 16 bytes too small. + +As a result, the data structures aren't properly aligned and the GRUB +generates "attempt to read or write outside of partition" errors when +trying to read the XFS filesystem: + + GNU GRUB version 2.11 + .... + grub> set debug=efi,gpt,xfs + grub> insmod part_gpt + grub> ls (hd0,gpt1)/ + partmap/gpt.c:93: Read a valid GPT header + partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125 + fs/xfs.c:931: Reading sb + fs/xfs.c:270: Validating superblock + fs/xfs.c:295: XFS v4 superblock detected + fs/xfs.c:962: Reading root ino 128 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (739521961424144223) - 344365866970255880, 3840 + error: attempt to read or write outside of partition. + +This commit change the XFS_V2_INODE_SIZE computation by subtracting 76 +bytes instead of 92 bytes from the actual size of grub_xfs_inode struct. +This 76 bytes value comes from added members: + 20 grub_uint8_t unused5 + 1 grub_uint64_t flags2 + 48 grub_uint8_t unused6 + +This patch explicitly splits the v2 and v3 parts of the structure. +The unused4 is still ending of the v2 structures and the v3 starts +at unused5. Thanks to this we will avoid future corruptions of v2 +or v3 inodes. + +The XFS_V2_INODE_SIZE is returning to its expected size and the +filesystem is back to a readable state: + + GNU GRUB version 2.11 + .... + grub> set debug=efi,gpt,xfs + grub> insmod part_gpt + grub> ls (hd0,gpt1)/ + partmap/gpt.c:93: Read a valid GPT header + partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125 + fs/xfs.c:931: Reading sb + fs/xfs.c:270: Validating superblock + fs/xfs.c:295: XFS v4 superblock detected + fs/xfs.c:962: Reading root ino 128 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:931: Reading sb + fs/xfs.c:270: Validating superblock + fs/xfs.c:295: XFS v4 superblock detected + fs/xfs.c:962: Reading root ino 128 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (131) - 64, 768 + efi/ fs/xfs.c:515: Reading inode (3145856) - 1464904, 0 + grub2/ fs/xfs.c:515: Reading inode (132) - 64, 1024 + grub/ fs/xfs.c:515: Reading inode (139) - 64, 2816 + grub> + +Fixes: 8b1e5d193 (fs/xfs: Add bigtime incompat feature support) + +Signed-off-by: Erwan Velu +Tested-by: Carlos Maiolino +Reviewed-by: Daniel Kiper +(cherry picked from commit a4b495520e4dc41a896a8b916a64eda9970c50ea) +--- + grub-core/fs/xfs.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 7d4e632..7d15add 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -192,6 +192,11 @@ struct grub_xfs_time_legacy + grub_uint32_t nanosec; + } GRUB_PACKED; + ++/* ++ * The struct grub_xfs_inode layout was taken from the ++ * struct xfs_dinode_core which is described here: ++ * https://mirrors.edge.kernel.org/pub/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf ++ */ + struct grub_xfs_inode + { + grub_uint8_t magic[2]; +@@ -208,14 +213,15 @@ struct grub_xfs_inode + grub_uint32_t nextents; + grub_uint16_t unused3; + grub_uint8_t fork_offset; +- grub_uint8_t unused4[37]; ++ grub_uint8_t unused4[17]; /* Last member of inode v2. */ ++ grub_uint8_t unused5[20]; /* First member of inode v3. */ + grub_uint64_t flags2; +- grub_uint8_t unused5[48]; ++ grub_uint8_t unused6[48]; /* Last member of inode v3. */ + } GRUB_PACKED; + + #define XFS_V3_INODE_SIZE sizeof(struct grub_xfs_inode) +-/* Size of struct grub_xfs_inode until fork_offset (included). */ +-#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 92) ++/* Size of struct grub_xfs_inode v2, up to unused4 member included. */ ++#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 76) + + struct grub_xfs_dirblock_tail + { +-- +2.43.5 + diff --git a/0670-fs-Remove-trailing-whitespaces.patch b/0670-fs-Remove-trailing-whitespaces.patch new file mode 100644 index 0000000..802636f --- /dev/null +++ b/0670-fs-Remove-trailing-whitespaces.patch @@ -0,0 +1,1666 @@ +From a39c28f730a954bdee34b93587a4b3bc29fb1d53 Mon Sep 17 00:00:00 2001 +From: Elyes Haouas +Date: Fri, 4 Mar 2022 07:41:59 +0100 +Subject: [PATCH 670/676] fs: Remove trailing whitespaces + +Signed-off-by: Elyes Haouas +Reviewed-by: Daniel Kiper +--- + grub-core/fs/affs.c | 4 +- + grub-core/fs/archelp.c | 4 +- + grub-core/fs/bfs.c | 10 +- + grub-core/fs/cpio_common.c | 2 +- + grub-core/fs/fat.c | 6 +- + grub-core/fs/fshelp.c | 6 +- + grub-core/fs/hfs.c | 14 +- + grub-core/fs/hfsplus.c | 8 +- + grub-core/fs/hfspluscomp.c | 6 +- + grub-core/fs/iso9660.c | 12 +- + grub-core/fs/minix.c | 6 +- + grub-core/fs/nilfs2.c | 8 +- + grub-core/fs/ntfs.c | 8 +- + grub-core/fs/reiserfs.c | 2 +- + grub-core/fs/romfs.c | 8 +- + grub-core/fs/squash4.c | 26 ++-- + grub-core/fs/udf.c | 2 +- + grub-core/fs/ufs.c | 4 +- + grub-core/fs/xfs.c | 2 +- + grub-core/fs/zfs/zfs.c | 220 ++++++++++++++++---------------- + grub-core/fs/zfs/zfs_fletcher.c | 12 +- + grub-core/fs/zfs/zfs_sha256.c | 14 +- + grub-core/fs/zfs/zfscrypt.c | 14 +- + 23 files changed, 199 insertions(+), 199 deletions(-) + +diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c +index 2a85063..6ed6ee1 100644 +--- a/grub-core/fs/affs.c ++++ b/grub-core/fs/affs.c +@@ -346,7 +346,7 @@ grub_affs_create_node (grub_fshelp_node_t dir, + if (len > sizeof (fil->name)) + len = sizeof (fil->name); + *grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0'; +- ++ + (*node)->di = *fil; + for (nest = 0; nest < 8; nest++) + { +@@ -409,7 +409,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, + node = orig_node = grub_zalloc (sizeof (*node)); + if (!node) + return 1; +- ++ + *node = *dir; + if (hook (".", GRUB_FSHELP_DIR, node, hook_data)) + return 1; +diff --git a/grub-core/fs/archelp.c b/grub-core/fs/archelp.c +index 6491f74..ab63430 100644 +--- a/grub-core/fs/archelp.c ++++ b/grub-core/fs/archelp.c +@@ -77,7 +77,7 @@ handle_symlink (struct grub_archelp_data *data, + || !arcops->get_link_target) + return GRUB_ERR_NONE; + flen = grub_strlen (fn); +- if (grub_memcmp (*name, fn, flen) != 0 ++ if (grub_memcmp (*name, fn, flen) != 0 + || ((*name)[flen] != 0 && (*name)[flen] != '/')) + return GRUB_ERR_NONE; + rest = *name + flen; +@@ -258,7 +258,7 @@ grub_archelp_open (struct grub_archelp_data *data, + grub_uint32_t mode; + grub_int32_t mtime; + int restart; +- ++ + if (arcops->find_file (data, &fn, &mtime, &mode)) + goto fail; + +diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c +index e70aaa4..2de6445 100644 +--- a/grub-core/fs/bfs.c ++++ b/grub-core/fs/bfs.c +@@ -531,13 +531,13 @@ iterate_in_b_tree (grub_disk_t disk, + err = read_b_node (disk, sb, ino, + node_off, + &node, +- &key_data, ++ &key_data, + &keylen_idx, + &key_values); + + if (err) + return 0; +- ++ + for (i = 0; i < grub_bfs_to_cpu_treehead (node->count_keys); i++) + { + char c; +@@ -683,7 +683,7 @@ find_in_b_tree (grub_disk_t disk, + level--; + grub_free (node); + continue; +- } ++ } + } + else if (level != 0 + && i + 1 < grub_bfs_to_cpu_treehead (node->count_keys)) +@@ -828,7 +828,7 @@ mount (grub_disk_t disk, struct grub_bfs_superblock *sb) + grub_err_t err; + err = grub_disk_read (disk, SUPERBLOCK, 0, sizeof (*sb), sb); + if (err == GRUB_ERR_OUT_OF_RANGE) +- return grub_error (GRUB_ERR_BAD_FS, ++ return grub_error (GRUB_ERR_BAD_FS, + #ifdef MODE_AFS + "not an AFS filesystem" + #else +@@ -844,7 +844,7 @@ mount (grub_disk_t disk, struct grub_bfs_superblock *sb) + || (grub_bfs_to_cpu32 (sb->bsize) + != (1U << grub_bfs_to_cpu32 (sb->log2_bsize))) + || grub_bfs_to_cpu32 (sb->log2_bsize) < GRUB_DISK_SECTOR_BITS) +- return grub_error (GRUB_ERR_BAD_FS, ++ return grub_error (GRUB_ERR_BAD_FS, + #ifdef MODE_AFS + "not an AFS filesystem" + #else +diff --git a/grub-core/fs/cpio_common.c b/grub-core/fs/cpio_common.c +index bcb0380..b7d8aa8 100644 +--- a/grub-core/fs/cpio_common.c ++++ b/grub-core/fs/cpio_common.c +@@ -130,7 +130,7 @@ grub_cpio_get_link_target (struct grub_archelp_data *data) + if (!ret) + return NULL; + +- err = grub_disk_read (data->disk, 0, data->dofs, data->size, ++ err = grub_disk_read (data->disk, 0, data->dofs, data->size, + ret); + if (err) + { +diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c +index 72785a7..760927c 100644 +--- a/grub-core/fs/fat.c ++++ b/grub-core/fs/fat.c +@@ -245,7 +245,7 @@ grub_fat_mount (grub_disk_t disk) + #ifdef MODE_EXFAT + if (grub_memcmp ((const char *) bpb.oem_name, "EXFAT ", + sizeof (bpb.oem_name)) != 0) +- goto fail; ++ goto fail; + #endif + + /* Get the sizes of logical sectors and clusters. */ +@@ -320,7 +320,7 @@ grub_fat_mount (grub_disk_t disk) + #endif + + #ifdef MODE_EXFAT +- data->cluster_sector = (grub_le_to_cpu32 (bpb.cluster_offset) ++ data->cluster_sector = (grub_le_to_cpu32 (bpb.cluster_offset) + << data->logical_sector_bits); + data->num_clusters = (grub_le_to_cpu32 (bpb.cluster_count) + << data->logical_sector_bits); +@@ -692,7 +692,7 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node, + { + int j; + for (j = 0; j < 15; j++) +- ctxt->unibuf[slots * 15 + j] ++ ctxt->unibuf[slots * 15 + j] + = grub_le_to_cpu16 (sec.type_specific.file_name.str[j]); + slots++; + } +diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c +index a2d0d29..cb41934 100644 +--- a/grub-core/fs/fshelp.c ++++ b/grub-core/fs/fshelp.c +@@ -215,7 +215,7 @@ find_file (char *currpath, + break; + + push_node (ctx, foundnode, foundtype); +- ++ + /* Read in the symlink and follow it. */ + if (ctx->currnode->type == GRUB_FSHELP_SYMLINK) + { +@@ -326,7 +326,7 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, + enum grub_fshelp_filetype expecttype) + { + return grub_fshelp_find_file_real (path, rootnode, foundnode, +- iterate_dir, NULL, ++ iterate_dir, NULL, + read_symlink, expecttype); + + } +@@ -339,7 +339,7 @@ grub_fshelp_find_file_lookup (const char *path, grub_fshelp_node_t rootnode, + enum grub_fshelp_filetype expecttype) + { + return grub_fshelp_find_file_real (path, rootnode, foundnode, +- NULL, lookup_file, ++ NULL, lookup_file, + read_symlink, expecttype); + + } +diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c +index 66b9fca..f23d10f 100644 +--- a/grub-core/fs/hfs.c ++++ b/grub-core/fs/hfs.c +@@ -883,7 +883,7 @@ grub_hfs_iterate_dir_it_dir (struct grub_hfs_node *hnd __attribute ((unused)), + { + struct grub_hfs_catalog_key *ckey = rec->key; + struct grub_hfs_iterate_dir_node_found_ctx *ctx = hook_arg; +- ++ + /* Stop when the entries do not match anymore. */ + if (ckey->parent_dir != ctx->dir_be) + return 1; +@@ -1077,7 +1077,7 @@ macroman_to_utf8 (char *to, const grub_uint8_t *from, grub_size_t len, + { + *optr++ = ':'; + continue; +- } ++ } + if (!(*iptr & 0x80)) + { + *optr++ = *iptr; +@@ -1094,7 +1094,7 @@ utf8_to_macroman (grub_uint8_t *to, const char *from) + grub_uint8_t *end = to + 31; + grub_uint8_t *optr = to; + const char *iptr = from; +- ++ + while (*iptr && optr < end) + { + int i, clen; +@@ -1104,7 +1104,7 @@ utf8_to_macroman (grub_uint8_t *to, const char *from) + *optr++ = '/'; + iptr++; + continue; +- } ++ } + if (!(*iptr & 0x80)) + { + *optr++ = *iptr++; +@@ -1165,7 +1165,7 @@ lookup_file (grub_fshelp_node_t dir, + *foundnode = grub_malloc (sizeof (struct grub_fshelp_node)); + if (!*foundnode) + return grub_errno; +- ++ + (*foundnode)->inode = grub_be_to_cpu32 (fdrec.dir.dirid); + (*foundnode)->fdrec = fdrec; + (*foundnode)->data = dir->data; +@@ -1266,7 +1266,7 @@ grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, + .hook_data = hook_data + }; + grub_fshelp_node_t found = NULL; +- ++ + grub_dl_ref (my_mod); + + data = grub_hfs_mount (device->disk); +@@ -1295,7 +1295,7 @@ grub_hfs_open (struct grub_file *file, const char *name) + { + struct grub_hfs_data *data; + grub_fshelp_node_t found = NULL; +- ++ + grub_dl_ref (my_mod); + + data = grub_hfs_mount (file->device->disk); +diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c +index a1805ee..da829f9 100644 +--- a/grub-core/fs/hfsplus.c ++++ b/grub-core/fs/hfsplus.c +@@ -19,7 +19,7 @@ + + /* HFS+ is documented at http://developer.apple.com/technotes/tn/tn1150.html */ + +-#define grub_fshelp_node grub_hfsplus_file ++#define grub_fshelp_node grub_hfsplus_file + #include + #include + #include +@@ -146,7 +146,7 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + { + struct grub_hfsplus_btnode *nnode = 0; + grub_disk_addr_t blksleft = fileblock; +- struct grub_hfsplus_extent *extents = node->compressed ++ struct grub_hfsplus_extent *extents = node->compressed + ? &node->resource_extents[0] : &node->extents[0]; + + while (1) +@@ -476,7 +476,7 @@ grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya, + + if (extkey_a->type < extkey_b->type) + return -1; +- ++ + akey = grub_be_to_cpu32 (extkey_a->start); + if (akey > extkey_b->start) + return 1; +@@ -567,7 +567,7 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, + struct grub_hfsplus_key_internal *key, + int (*compare_keys) (struct grub_hfsplus_key *keya, + struct grub_hfsplus_key_internal *keyb), +- struct grub_hfsplus_btnode **matchnode, ++ struct grub_hfsplus_btnode **matchnode, + grub_off_t *keyoffset) + { + grub_uint64_t currnode; +diff --git a/grub-core/fs/hfspluscomp.c b/grub-core/fs/hfspluscomp.c +index 4965ef1..b3240a0 100644 +--- a/grub-core/fs/hfspluscomp.c ++++ b/grub-core/fs/hfspluscomp.c +@@ -179,7 +179,7 @@ hfsplus_read_compressed_real (struct grub_hfsplus_file *node, + return len0; + } + +-static grub_err_t ++static grub_err_t + hfsplus_open_compressed_real (struct grub_hfsplus_file *node) + { + grub_err_t err; +@@ -311,8 +311,8 @@ hfsplus_open_compressed_real (struct grub_hfsplus_file *node) + + GRUB_MOD_INIT(hfspluscomp) + { +- grub_hfsplus_open_compressed = hfsplus_open_compressed_real; +- grub_hfsplus_read_compressed = hfsplus_read_compressed_real; ++ grub_hfsplus_open_compressed = hfsplus_open_compressed_real; ++ grub_hfsplus_read_compressed = hfsplus_read_compressed_real; + } + + GRUB_MOD_FINI(hfspluscomp) +diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c +index 5765055..29ab60f 100644 +--- a/grub-core/fs/iso9660.c ++++ b/grub-core/fs/iso9660.c +@@ -181,7 +181,7 @@ static grub_err_t + iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) + { + struct grub_datetime datetime; +- ++ + if (! i->year[0] && ! i->year[1] + && ! i->year[2] && ! i->year[3] + && ! i->month[0] && ! i->month[1] +@@ -198,7 +198,7 @@ iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) + datetime.hour = (i->hour[0] - '0') * 10 + (i->hour[1] - '0'); + datetime.minute = (i->minute[0] - '0') * 10 + (i->minute[1] - '0'); + datetime.second = (i->second[0] - '0') * 10 + (i->second[1] - '0'); +- ++ + if (!grub_datetime2unixtime (&datetime, nix)) + return grub_error (GRUB_ERR_BAD_NUMBER, "incorrect date"); + *nix -= i->offset * 60 * 15; +@@ -216,7 +216,7 @@ iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix) + datetime.hour = i->hour; + datetime.minute = i->minute; + datetime.second = i->second; +- ++ + if (!grub_datetime2unixtime (&datetime, nix)) + return 0; + *nix -= i->offset * 60 * 15; +@@ -502,7 +502,7 @@ grub_iso9660_mount (grub_disk_t disk) + static char * + grub_iso9660_read_symlink (grub_fshelp_node_t node) + { +- return node->have_symlink ++ return node->have_symlink + ? grub_strdup (node->symlink + + (node->have_dirents) * sizeof (node->dirents[0]) + - sizeof (node->dirents)) : grub_strdup (""); +@@ -552,7 +552,7 @@ add_part (struct iterate_dir_ctx *ctx, + ctx->symlink = new; + + grub_memcpy (ctx->symlink + size, part, len2); +- ctx->symlink[size + len2] = 0; ++ ctx->symlink[size + len2] = 0; + } + + static grub_err_t +@@ -1119,7 +1119,7 @@ grub_iso9660_uuid (grub_device_t device, char **uuid) + } + + /* Get writing time of filesystem. */ +-static grub_err_t ++static grub_err_t + grub_iso9660_mtime (grub_device_t device, grub_int32_t *timebuf) + { + struct grub_iso9660_data *data; +diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c +index 38e6587..f31909d 100644 +--- a/grub-core/fs/minix.c ++++ b/grub-core/fs/minix.c +@@ -97,10 +97,10 @@ struct grub_minix_sblock + grub_uint32_t max_file_size; + grub_uint32_t zones; + grub_uint16_t magic; +- ++ + grub_uint16_t pad2; + grub_uint16_t block_size; +- grub_uint8_t disk_version; ++ grub_uint8_t disk_version; + }; + #else + struct grub_minix_sblock +@@ -350,7 +350,7 @@ grub_minix_read_inode (struct grub_minix_data *data, grub_minix_ino_t ino) + int offs = (ino % (GRUB_DISK_SECTOR_SIZE + / sizeof (struct grub_minix_inode)) + * sizeof (struct grub_minix_inode)); +- ++ + grub_disk_read (data->disk, block, offs, + sizeof (struct grub_minix_inode), &data->inode); + +diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c +index 6d1e25f..6aaa5b9 100644 +--- a/grub-core/fs/nilfs2.c ++++ b/grub-core/fs/nilfs2.c +@@ -1,5 +1,5 @@ +-/* +- * nilfs2.c - New Implementation of Log filesystem ++/* ++ * nilfs2.c - New Implementation of Log filesystem + * + * Written by Jiro SEKIBA + * +@@ -681,12 +681,12 @@ grub_nilfs2_read_checkpoint (struct grub_nilfs2_data *data, + grub_disk_t disk = data->disk; + unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data)); + +- /* Assume sizeof(struct grub_nilfs2_cpfile_header) < ++ /* Assume sizeof(struct grub_nilfs2_cpfile_header) < + sizeof(struct grub_nilfs2_checkpoint). + */ + blockno = grub_divmod64 (cpno, NILFS2_BLOCK_SIZE (data) / + sizeof (struct grub_nilfs2_checkpoint), &offset); +- ++ + pptr = grub_nilfs2_bmap_lookup (data, &data->sroot.sr_cpfile, blockno, 1); + if (pptr == (grub_uint64_t) - 1) + { +diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c +index e9d30f0..8c331b5 100644 +--- a/grub-core/fs/ntfs.c ++++ b/grub-core/fs/ntfs.c +@@ -17,7 +17,7 @@ + * along with this program. If not, see . + */ + +-#define grub_fshelp_node grub_ntfs_file ++#define grub_fshelp_node grub_ntfs_file + + #include + #include +@@ -33,7 +33,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + + static grub_dl_t my_mod; + +-#define grub_fshelp_node grub_ntfs_file ++#define grub_fshelp_node grub_ntfs_file + + static inline grub_uint16_t + u16at (void *ptr, grub_size_t ofs) +@@ -837,7 +837,7 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node) + && grub_isalpha (buf[4])) + { + grub_memmove (buf, buf + 6, end - buf + 1 - 6); +- end -= 6; ++ end -= 6; + } + return buf; + } +@@ -1130,7 +1130,7 @@ grub_ntfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; +- info.mtime = grub_divmod64 (node->mtime, 10000000, 0) ++ info.mtime = grub_divmod64 (node->mtime, 10000000, 0) + - 86400ULL * 365 * (1970 - 1601) + - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100); + grub_free (node); +diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c +index 72e724f..612d9ed 100644 +--- a/grub-core/fs/reiserfs.c ++++ b/grub-core/fs/reiserfs.c +@@ -776,7 +776,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, + char *entry_name; + char *entry_name_end = 0; + char c; +- ++ + if (!(entry_state & GRUB_REISERFS_VISIBLE_MASK)) + continue; + +diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c +index d7817cd..b9f2650 100644 +--- a/grub-core/fs/romfs.c ++++ b/grub-core/fs/romfs.c +@@ -113,7 +113,7 @@ grub_romfs_mount (grub_device_t dev) + { + grub_error (GRUB_ERR_BAD_FS, "not romfs"); + return NULL; +- } ++ } + err = do_checksum (&sb, sizeof (sb) < grub_be_to_cpu32 (sb.sb.total_size) ? + sizeof (sb) : grub_be_to_cpu32 (sb.sb.total_size)); + if (err) +@@ -272,7 +272,7 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, + while (1) + { + char buf[16]; +- err = grub_disk_read (dir->data->disk, ++ err = grub_disk_read (dir->data->disk, + laddr >> GRUB_DISK_SECTOR_BITS, + laddr & (GRUB_DISK_SECTOR_SIZE - 1), + 16, buf); +@@ -299,7 +299,7 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, + node->data_addr = grub_be_to_cpu32 (node->file.spec); + filetype = GRUB_FSHELP_DIR; + } +- ++ + break; + } + } +@@ -403,7 +403,7 @@ grub_romfs_read (grub_file_t file, char *buf, grub_size_t len) + data->data->disk->read_hook_data = file->read_hook_data; + grub_disk_read (data->data->disk, + (data->data_addr + file->offset) >> GRUB_DISK_SECTOR_BITS, +- (data->data_addr + file->offset) & (GRUB_DISK_SECTOR_SIZE - 1), ++ (data->data_addr + file->offset) & (GRUB_DISK_SECTOR_SIZE - 1), + len, buf); + data->data->disk->read_hook = NULL; + +diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c +index b145bb9..a09cae4 100644 +--- a/grub-core/fs/squash4.c ++++ b/grub-core/fs/squash4.c +@@ -210,7 +210,7 @@ struct grub_fshelp_node + struct grub_squash_data *data; + struct grub_squash_inode ino; + grub_size_t stsize; +- struct ++ struct + { + grub_disk_addr_t ino_chunk; + grub_uint16_t ino_offset; +@@ -243,7 +243,7 @@ read_chunk (struct grub_squash_data *data, void *buf, grub_size_t len, + csize = SQUASH_CHUNK_SIZE - offset; + if (csize > len) + csize = len; +- ++ + if (grub_le_to_cpu16 (d) & SQUASH_CHUNK_UNCOMPRESSED) + { + grub_disk_addr_t a = chunk_start + 2 + offset; +@@ -256,7 +256,7 @@ read_chunk (struct grub_squash_data *data, void *buf, grub_size_t len, + else + { + char *tmp; +- grub_size_t bsize = grub_le_to_cpu16 (d) & ~SQUASH_CHUNK_FLAGS; ++ grub_size_t bsize = grub_le_to_cpu16 (d) & ~SQUASH_CHUNK_FLAGS; + grub_disk_addr_t a = chunk_start + 2; + tmp = grub_malloc (bsize); + if (!tmp) +@@ -339,7 +339,7 @@ xz_decompress (char *inbuf, grub_size_t insize, grub_off_t off, + while (len) + { + enum xz_ret xzret; +- ++ + buf.out_pos = 0; + + xzret = xz_dec_run (data->xzdec, &buf); +@@ -399,9 +399,9 @@ squash_mount (grub_disk_t disk) + return NULL; + } + +- err = grub_disk_read (disk, ++ err = grub_disk_read (disk, + grub_le_to_cpu64 (sb.unk1offset) +- >> GRUB_DISK_SECTOR_BITS, ++ >> GRUB_DISK_SECTOR_BITS, + grub_le_to_cpu64 (sb.unk1offset) + & (GRUB_DISK_SECTOR_SIZE - 1), sizeof (frag), &frag); + if (grub_errno == GRUB_ERR_OUT_OF_RANGE) +@@ -448,7 +448,7 @@ squash_mount (grub_disk_t disk) + } + + data->blksz = grub_le_to_cpu32 (data->sb.block_size); +- for (data->log2_blksz = 0; ++ for (data->log2_blksz = 0; + (1U << data->log2_blksz) < data->blksz; + data->log2_blksz++); + +@@ -649,7 +649,7 @@ make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root) + root->stack[0].ino_chunk = grub_le_to_cpu32 (data->sb.root_ino_chunk); + root->stack[0].ino_offset = grub_cpu_to_le16 (data->sb.root_ino_offset); + return read_chunk (data, &root->ino, sizeof (root->ino), +- grub_le_to_cpu64 (data->sb.inodeoffset) ++ grub_le_to_cpu64 (data->sb.inodeoffset) + + root->stack[0].ino_chunk, + root->stack[0].ino_offset); + } +@@ -771,7 +771,7 @@ grub_squash_open (struct grub_file *file, const char *name) + } + + static grub_ssize_t +-direct_read (struct grub_squash_data *data, ++direct_read (struct grub_squash_data *data, + struct grub_squash_cache_inode *ino, + grub_off_t off, char *buf, grub_size_t len) + { +@@ -888,7 +888,7 @@ direct_read (struct grub_squash_data *data, + grub_free (block); + } + else +- err = grub_disk_read (data->disk, ++ err = grub_disk_read (data->disk, + (ino->cumulated_block_sizes[i] + a + boff) + >> GRUB_DISK_SECTOR_BITS, + (ino->cumulated_block_sizes[i] + a + boff) +@@ -952,7 +952,7 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) + } + else + off -= direct_len; +- ++ + err = read_chunk (data, &frag, sizeof (frag), + data->fragments, sizeof (frag) * fragment); + if (err) +@@ -963,7 +963,7 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) + b = grub_le_to_cpu32 (ino->ino.long_file.offset) + off; + else + b = grub_le_to_cpu32 (ino->ino.file.offset) + off; +- ++ + /* FIXME: cache uncompressed chunks. */ + if (compressed) + { +@@ -1019,7 +1019,7 @@ grub_squash_mtime (grub_device_t dev, grub_int32_t *tm) + *tm = grub_le_to_cpu32 (data->sb.creation_time); + squash_unmount (data); + return GRUB_ERR_NONE; +-} ++} + + static struct grub_fs grub_squash_fs = + { +diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c +index 4062609..734af09 100644 +--- a/grub-core/fs/udf.c ++++ b/grub-core/fs/udf.c +@@ -568,7 +568,7 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + (buf + sizeof (struct grub_udf_aed)); + continue; + } +- ++ + if (filebytes < adlen) + { + grub_uint32_t ad_block_num = ad->block.block_num; +diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c +index 844a439..df5db80 100644 +--- a/grub-core/fs/ufs.c ++++ b/grub-core/fs/ufs.c +@@ -569,7 +569,7 @@ grub_ufs_find_file (struct grub_ufs_data *data, const char *path) + { + dirino = data->ino; + grub_ufs_read_inode (data, grub_ufs_to_cpu32 (dirent.ino), 0); +- ++ + if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE) + == GRUB_UFS_ATTR_LNK) + { +@@ -614,7 +614,7 @@ grub_ufs_mount (grub_disk_t disk) + && ((data->sblock.bsize & (data->sblock.bsize - 1)) == 0) + && data->sblock.ino_per_group != 0) + { +- for (data->log2_blksz = 0; ++ for (data->log2_blksz = 0; + (1U << data->log2_blksz) < grub_ufs_to_cpu32 (data->sblock.bsize); + data->log2_blksz++); + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 7d15add..4caf29f 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -942,7 +942,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + tag, which is not used by GRUB. So it can be overwritten. */ + filename[direntry->len] = '\0'; + +- if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode), ++ if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode), + filename, &ctx)) + { + grub_free (dirblock); +diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c +index 5254e75..de6e26f 100644 +--- a/grub-core/fs/zfs/zfs.c ++++ b/grub-core/fs/zfs/zfs.c +@@ -173,7 +173,7 @@ typedef struct decomp_entry + /* + * Signature for checksum functions. + */ +-typedef void zio_checksum_t(const void *data, grub_uint64_t size, ++typedef void zio_checksum_t(const void *data, grub_uint64_t size, + grub_zfs_endian_t endian, zio_cksum_t *zcp); + + /* +@@ -294,7 +294,7 @@ check_feature(const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx) + static grub_err_t + check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data ); + +-static grub_err_t ++static grub_err_t + zlib_decompress (void *s, void *d, + grub_size_t slen, grub_size_t dlen) + { +@@ -307,7 +307,7 @@ zlib_decompress (void *s, void *d, + return grub_errno; + } + +-static grub_err_t ++static grub_err_t + zle_decompress (void *s, void *d, + grub_size_t slen, grub_size_t dlen) + { +@@ -412,7 +412,7 @@ static zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = { + */ + static grub_err_t + zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, +- grub_zfs_endian_t endian, ++ grub_zfs_endian_t endian, + char *buf, grub_size_t size) + { + zio_eck_t *zec = (zio_eck_t *) (buf + size) - 1; +@@ -422,14 +422,14 @@ zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, + if (checksum >= ZIO_CHECKSUM_FUNCTIONS || ci->ci_func == NULL) + { + grub_dprintf ("zfs", "unknown checksum function %d\n", checksum); +- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unknown checksum function %d", checksum); + } + + if (ci->ci_eck) + { +- expected_cksum = zec->zec_cksum; +- zec->zec_cksum = zc; ++ expected_cksum = zec->zec_cksum; ++ zec->zec_cksum = zc; + ci->ci_func (buf, size, endian, &actual_cksum); + zec->zec_cksum = expected_cksum; + zc = expected_cksum; +@@ -442,14 +442,14 @@ zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, + { + grub_dprintf ("zfs", "checksum %s verification failed\n", ci->ci_name); + grub_dprintf ("zfs", "actual checksum %016llx %016llx %016llx %016llx\n", +- (unsigned long long) actual_cksum.zc_word[0], ++ (unsigned long long) actual_cksum.zc_word[0], + (unsigned long long) actual_cksum.zc_word[1], +- (unsigned long long) actual_cksum.zc_word[2], ++ (unsigned long long) actual_cksum.zc_word[2], + (unsigned long long) actual_cksum.zc_word[3]); + grub_dprintf ("zfs", "expected checksum %016llx %016llx %016llx %016llx\n", +- (unsigned long long) zc.zc_word[0], ++ (unsigned long long) zc.zc_word[0], + (unsigned long long) zc.zc_word[1], +- (unsigned long long) zc.zc_word[2], ++ (unsigned long long) zc.zc_word[2], + (unsigned long long) zc.zc_word[3]); + return grub_error (GRUB_ERR_BAD_FS, N_("checksum verification failed")); + } +@@ -482,17 +482,17 @@ vdev_uberblock_compare (uberblock_t * ub1, uberblock_t * ub2) + else + ub2_endian = GRUB_ZFS_BIG_ENDIAN; + +- if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) ++ if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) + < grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian)) + return -1; +- if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) ++ if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) + > grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian)) + return 1; + +- if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) ++ if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) + < grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian)) + return -1; +- if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) ++ if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) + > grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian)) + return 1; + +@@ -570,7 +570,7 @@ find_bestub (uberblock_phys_t * ub_array, + grub_errno = GRUB_ERR_NONE; + continue; + } +- if (ubbest == NULL ++ if (ubbest == NULL + || vdev_uberblock_compare (&(ubptr->ubp_uberblock), + &(ubbest->ubp_uberblock)) > 0) + ubbest = ubptr; +@@ -591,10 +591,10 @@ get_psize (blkptr_t * bp, grub_zfs_endian_t endian) + static grub_uint64_t + dva_get_offset (const dva_t *dva, grub_zfs_endian_t endian) + { +- grub_dprintf ("zfs", "dva=%llx, %llx\n", +- (unsigned long long) dva->dva_word[0], ++ grub_dprintf ("zfs", "dva=%llx, %llx\n", ++ (unsigned long long) dva->dva_word[0], + (unsigned long long) dva->dva_word[1]); +- return grub_zfs_to_cpu64 ((dva)->dva_word[1], ++ return grub_zfs_to_cpu64 ((dva)->dva_word[1], + endian) << SPA_MINBLOCKSHIFT; + } + +@@ -843,7 +843,7 @@ nvlist_next_nvpair (const char *nvl, const char *nvpair) + { + /* skip over header, nvl_version and nvl_nvflag */ + nvpair = nvl + 4 * 3; +- } ++ } + else + { + /* skip to the next nvpair */ +@@ -877,10 +877,10 @@ nvlist_next_nvpair (const char *nvl, const char *nvpair) + name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + nvp += 4; + +- nvp = nvp + ((name_len + 3) & ~3); // align +- if (nvp + 4 >= nvl + VDEV_PHYS_SIZE ++ nvp = nvp + ((name_len + 3) & ~3); // align ++ if (nvp + 4 >= nvl + VDEV_PHYS_SIZE + || encode_size < 0 +- || nvp + 4 + encode_size > nvl + VDEV_PHYS_SIZE) ++ || nvp + 4 + encode_size > nvl + VDEV_PHYS_SIZE) + { + grub_dprintf ("zfs", "nvlist overflow\n"); + grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); +@@ -900,7 +900,7 @@ nvpair_name (const char *nvp, char **buf, grub_size_t *buflen) + { + /* skip over encode/decode size */ + nvp += 4 * 2; +- ++ + *buf = (char *) (nvp + 4); + *buflen = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + +@@ -947,7 +947,7 @@ nvpair_value (const char *nvp,char **val, + + /* skip over name */ + nvp = nvp + ((name_len + 3) & ~3); /* align */ +- ++ + /* skip over type */ + nvp += 4; + nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); +@@ -961,7 +961,7 @@ nvpair_value (const char *nvp,char **val, + *size_out = encode_size; + if (nelm_out) + *nelm_out = nelm; +- ++ + return 1; + } + +@@ -1187,7 +1187,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, + desc.vdev_phys_sector + = label * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT) + + ((VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT) +- + (label < VDEV_LABELS / 2 ? 0 : ++ + (label < VDEV_LABELS / 2 ? 0 : + ALIGN_DOWN (grub_disk_get_size (dev->disk), sizeof (vdev_label_t)) + - VDEV_LABELS * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT)); + +@@ -1233,7 +1233,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, + grub_free (bh); + return GRUB_ERR_NONE; + } +- ++ + grub_free (ub_array); + grub_free (bh); + +@@ -1273,7 +1273,7 @@ scan_devices_iter (const char *name, void *hook_data) + + if (!inserted) + grub_device_close (dev); +- ++ + return 0; + } + +@@ -1390,7 +1390,7 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, + for (i = 0; i < nbufs; i++) + { + grub_uint8_t mul; +- for (j = i; j < nbufs; j++) ++ for (j = i; j < nbufs; j++) + if (matrix1[i][j]) + break; + if (j == nbufs) +@@ -1457,7 +1457,7 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, + } + default: + return grub_error (GRUB_ERR_BUG, "too big matrix"); +- } ++ } + } + + static grub_err_t +@@ -1514,7 +1514,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, + int idx, orig_idx; + + if (desc->nparity < 1 || desc->nparity > 3) +- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "raidz%d is not supported", desc->nparity); + + if (desc->n_children <= desc->nparity || desc->n_children < 1) +@@ -1663,7 +1663,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, + len -= csize; + idx--; + } +- for (i = 0; i < failed_devices ++ for (i = 0; i < failed_devices + && recovery_len[i] == recovery_len[0]; + i++); + /* Since the chunks have variable length handle the last block +@@ -1786,7 +1786,7 @@ zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf, + * Read in a block of raw data to buf. + */ + static grub_err_t +-zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf, ++zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf, + struct grub_zfs_data *data) + { + int i, psize; +@@ -1854,7 +1854,7 @@ decode_embedded_bp_compressed(const blkptr_t *bp, void *buf) + * and put the uncompressed data in buf. + */ + static grub_err_t +-zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, ++zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, + grub_size_t *size, struct grub_zfs_data *data) + { + grub_size_t lsize, psize; +@@ -1940,7 +1940,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, + if (encrypted) + { + if (!grub_zfs_decrypt) +- err = grub_error (GRUB_ERR_BAD_FS, ++ err = grub_error (GRUB_ERR_BAD_FS, + N_("module `%s' isn't loaded"), + "zfscrypt"); + else +@@ -1964,7 +1964,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, + endian)); + return grub_error (GRUB_ERR_BAD_FS, "no key found in keychain"); + } +- grub_dprintf ("zfs", "using key %u (%" PRIxGRUB_UINT64_T ++ grub_dprintf ("zfs", "using key %u (%" PRIxGRUB_UINT64_T + ", %p) for txg %" PRIxGRUB_UINT64_T "\n", + besti, data->subvol.keyring[besti].txg, + data->subvol.keyring[besti].cipher, +@@ -2012,7 +2012,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, + * + */ + static grub_err_t +-dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, ++dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, + grub_zfs_endian_t *endian_out, struct grub_zfs_data *data) + { + int level; +@@ -2042,8 +2042,8 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, + + if (BP_IS_HOLE (bp)) + { +- grub_size_t size = grub_zfs_to_cpu16 (dn->dn.dn_datablkszsec, +- dn->endian) ++ grub_size_t size = grub_zfs_to_cpu16 (dn->dn.dn_datablkszsec, ++ dn->endian) + << SPA_MINBLOCKSHIFT; + *buf = grub_malloc (size); + if (!*buf) +@@ -2107,7 +2107,7 @@ mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, + } + + static int +-mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, ++mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, + int (*hook) (const char *name, grub_uint64_t val, + struct grub_zfs_dir_ctx *ctx), + struct grub_zfs_dir_ctx *ctx) +@@ -2121,7 +2121,7 @@ mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, + grub_dprintf ("zfs", "zap: name = %s, value = %llx, cd = %x\n", + mzap_ent[i].mze_name, (long long)mzap_ent[i].mze_value, + (int)mzap_ent[i].mze_cd); +- if (hook (mzap_ent[i].mze_name, ++ if (hook (mzap_ent[i].mze_name, + grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian), ctx)) + return 1; + } +@@ -2182,12 +2182,12 @@ name_cmp (const char *s1, const char *s2, grub_size_t n, + + if (!case_insensitive) + return grub_memcmp (t1, t2, n); +- ++ + while (n--) + { + if (grub_toupper (*t1) != grub_toupper (*t2)) + return (int) grub_toupper (*t1) - (int) grub_toupper (*t2); +- ++ + t1++; + t2++; + } +@@ -2225,7 +2225,7 @@ zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian, + + /* XXX */ + static grub_err_t +-zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, ++zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, + int chunk, grub_size_t array_len, char *buf) + { + grub_size_t bseen = 0; +@@ -2289,7 +2289,7 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, + + grub_dprintf ("zfs", "fzap: length %d\n", (int) le->le_name_length); + +- if (zap_leaf_array_equal (l, endian, blksft, ++ if (zap_leaf_array_equal (l, endian, blksft, + grub_zfs_to_cpu16 (le->le_name_chunk,endian), + grub_zfs_to_cpu16 (le->le_name_length, endian), + name, case_insensitive)) +@@ -2338,7 +2338,7 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, + { + void *l; + grub_uint64_t hash, idx, blkid; +- int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, ++ int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, + zap_dnode->endian) << DNODE_SHIFT); + grub_err_t err; + grub_zfs_endian_t leafendian; +@@ -2351,7 +2351,7 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, + + /* get block id from index */ + if (zap->zap_ptrtbl.zt_numblks != 0) +- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "external pointer tables not supported"); + idx = ZAP_HASH_IDX (hash, zap->zap_ptrtbl.zt_shift); + blkid = grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))], zap_dnode->endian); +@@ -2383,7 +2383,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, + void *l_in; + grub_uint64_t idx, idx2, blkid; + grub_uint16_t chunk; +- int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, ++ int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, + zap_dnode->endian) << DNODE_SHIFT); + grub_err_t err; + grub_zfs_endian_t endian; +@@ -2395,7 +2395,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, + /* get block id from index */ + if (zap->zap_ptrtbl.zt_numblks != 0) + { +- grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "external pointer tables not supported"); + return 0; + } +@@ -2539,7 +2539,7 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, + grub_dprintf ("zfs", "micro zap\n"); + err = mzap_lookup (zapbuf, endian, size, name, val, + case_insensitive); +- grub_dprintf ("zfs", "returned %d\n", err); ++ grub_dprintf ("zfs", "returned %d\n", err); + grub_free (zapbuf); + return err; + } +@@ -2549,7 +2549,7 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, + /* this is a fat zap */ + err = fzap_lookup (zap_dnode, zapbuf, name, val, data, + case_insensitive); +- grub_dprintf ("zfs", "returned %d\n", err); ++ grub_dprintf ("zfs", "returned %d\n", err); + grub_free (zapbuf); + return err; + } +@@ -2582,7 +2582,7 @@ zap_iterate_u64_transform (const void *name, + } + + static int +-zap_iterate_u64 (dnode_end_t * zap_dnode, ++zap_iterate_u64 (dnode_end_t * zap_dnode, + int (*hook) (const char *name, grub_uint64_t val, + struct grub_zfs_dir_ctx *ctx), + struct grub_zfs_data *data, struct grub_zfs_dir_ctx *ctx) +@@ -2629,7 +2629,7 @@ zap_iterate_u64 (dnode_end_t * zap_dnode, + } + + static int +-zap_iterate (dnode_end_t * zap_dnode, ++zap_iterate (dnode_end_t * zap_dnode, + grub_size_t nameelemlen, + int (*hook) (const void *name, grub_size_t namelen, + const void *val_in, +@@ -2689,7 +2689,7 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, + grub_err_t err; + grub_zfs_endian_t endian; + +- blksz = grub_zfs_to_cpu16 (mdn->dn.dn_datablkszsec, ++ blksz = grub_zfs_to_cpu16 (mdn->dn.dn_datablkszsec, + mdn->endian) << SPA_MINBLOCKSHIFT; + epbs = zfs_log2 (blksz) - DNODE_SHIFT; + +@@ -2700,18 +2700,18 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, + blkid = objnum >> epbs; + idx = objnum & ((1 << epbs) - 1); + +- if (data->dnode_buf != NULL && grub_memcmp (data->dnode_mdn, mdn, +- sizeof (*mdn)) == 0 ++ if (data->dnode_buf != NULL && grub_memcmp (data->dnode_mdn, mdn, ++ sizeof (*mdn)) == 0 + && objnum >= data->dnode_start && objnum < data->dnode_end) + { + grub_memmove (&(buf->dn), &(data->dnode_buf)[idx], DNODE_SIZE); + buf->endian = data->dnode_endian; +- if (type && buf->dn.dn_type != type) +- return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); ++ if (type && buf->dn.dn_type != type) ++ return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); + return GRUB_ERR_NONE; + } + +- grub_dprintf ("zfs", "endian = %d, blkid=%llx\n", mdn->endian, ++ grub_dprintf ("zfs", "endian = %d, blkid=%llx\n", mdn->endian, + (unsigned long long) blkid); + err = dmu_read (mdn, blkid, &dnbuf, &endian, data); + if (err) +@@ -2737,8 +2737,8 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, + + grub_memmove (&(buf->dn), (dnode_phys_t *) dnbuf + idx, DNODE_SIZE); + buf->endian = endian; +- if (type && buf->dn.dn_type != type) +- return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); ++ if (type && buf->dn.dn_type != type) ++ return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); + + return GRUB_ERR_NONE; + } +@@ -2762,7 +2762,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + struct dnode_chain + { + struct dnode_chain *next; +- dnode_end_t dn; ++ dnode_end_t dn; + }; + struct dnode_chain *dnode_path = 0, *dn_new, *root; + +@@ -2772,7 +2772,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + dn_new->next = 0; + dnode_path = root = dn_new; + +- err = dnode_get (&subvol->mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, ++ err = dnode_get (&subvol->mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, + &(dnode_path->dn), data); + if (err) + { +@@ -2823,7 +2823,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + grub_free (dn_new); + return grub_errno; + } +- ++ + while (1) + { + /* skip leading slashes */ +@@ -2849,7 +2849,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + } + else + { +- err = grub_error (GRUB_ERR_FILE_NOT_FOUND, ++ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, + "can't resolve .."); + break; + } +@@ -2900,7 +2900,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + { + grub_size_t block; + grub_size_t blksz; +- blksz = (grub_zfs_to_cpu16 (dnode_path->dn.dn.dn_datablkszsec, ++ blksz = (grub_zfs_to_cpu16 (dnode_path->dn.dn.dn_datablkszsec, + dnode_path->dn.endian) + << SPA_MINBLOCKSHIFT); + +@@ -2939,7 +2939,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + if (err) + break; + free_symval = 1; +- } ++ } + if (grub_add (sym_sz, grub_strlen (oldpath), &sz) || + grub_add (sz, 1, &sz)) + { +@@ -2963,9 +2963,9 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + if (free_symval) + grub_free (sym_value); + path [sym_sz] = 0; +- grub_memcpy (path + grub_strlen (path), oldpath, ++ grub_memcpy (path + grub_strlen (path), oldpath, + grub_strlen (oldpath) + 1); +- ++ + grub_free (oldpathbuf); + if (path[0] != '/') + { +@@ -2993,7 +2993,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + else if (dnode_path->dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) + { + blkptr_t *bp = &dnode_path->dn.dn.dn_spill; +- ++ + err = zio_read (bp, dnode_path->dn.endian, &sahdrp, NULL, data); + if (err) + break; +@@ -3012,7 +3012,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + dnode_path->dn.endian) >> 12) & 0xf) == 0xa) + { + char *sym_value = (char *) sahdrp + hdrsize + SA_SYMLINK_OFFSET; +- grub_size_t sym_sz = ++ grub_size_t sym_sz = + grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + + hdrsize + + SA_SIZE_OFFSET), +@@ -3035,9 +3035,9 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + } + grub_memcpy (path, sym_value, sym_sz); + path [sym_sz] = 0; +- grub_memcpy (path + grub_strlen (path), oldpath, ++ grub_memcpy (path + grub_strlen (path), oldpath, + grub_strlen (oldpath) + 1); +- ++ + grub_free (oldpathbuf); + if (path[0] != '/') + { +@@ -3138,7 +3138,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, + + grub_dprintf ("zfs", "endian = %d\n", mosmdn->endian); + +- err = dnode_get (mosmdn, DMU_POOL_DIRECTORY_OBJECT, ++ err = dnode_get (mosmdn, DMU_POOL_DIRECTORY_OBJECT, + DMU_OT_OBJECT_DIRECTORY, mdn, data); + if (err) + return err; +@@ -3161,7 +3161,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, + { + grub_uint64_t childobj; + char *cname, ch; +- ++ + while (*fsname == '/') + fsname++; + +@@ -3323,7 +3323,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, + filename = ptr_slash; + else + filename = "/"; +- grub_dprintf ("zfs", "fsname = '%s' snapname='%s' filename = '%s'\n", ++ grub_dprintf ("zfs", "fsname = '%s' snapname='%s' filename = '%s'\n", + fsname, snapname, filename); + } + grub_dprintf ("zfs", "alive\n"); +@@ -3409,7 +3409,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, + + snapobj = grub_zfs_to_cpu64 (((dsl_dataset_phys_t *) DN_BONUS (&subvol->mdn.dn))->ds_snapnames_zapobj, subvol->mdn.endian); + +- err = dnode_get (&(data->mos), snapobj, ++ err = dnode_get (&(data->mos), snapobj, + DMU_OT_DSL_DS_SNAP_MAP, &subvol->mdn, data); + if (!err) + err = zap_lookup (&subvol->mdn, snapname, &headobj, data, 0); +@@ -3427,13 +3427,13 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, + subvol->obj = headobj; + + make_mdn (&subvol->mdn, data); +- ++ + grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian); + + if (*isfs) + { + grub_free (fsname); +- grub_free (snapname); ++ grub_free (snapname); + return GRUB_ERR_NONE; + } + err = dnode_get_path (subvol, filename, dn, data); +@@ -3453,9 +3453,9 @@ nvlist_find_value (const char *nvlist_in, const char *name, + char *nvp_name; + + /* Verify if the 1st and 2nd byte in the nvlist are valid. */ +- /* NOTE: independently of what endianness header announces all ++ /* NOTE: independently of what endianness header announces all + subsequent values are big-endian. */ +- if (nvlist[0] != NV_ENCODE_XDR || (nvlist[1] != NV_LITTLE_ENDIAN ++ if (nvlist[0] != NV_ENCODE_XDR || (nvlist[1] != NV_LITTLE_ENDIAN + && nvlist[1] != NV_BIG_ENDIAN)) + { + grub_dprintf ("zfs", "incorrect nvlist header\n"); +@@ -3576,13 +3576,13 @@ get_nvlist_size (const char *beg, const char *limit) + { + const char *ptr; + grub_uint32_t encode_size; +- ++ + ptr = beg + 8; + + while (ptr < limit + && (encode_size = grub_be_to_cpu32 (grub_get_unaligned32 (ptr)))) + ptr += encode_size; /* goto the next nvpair */ +- ptr += 8; ++ ptr += 8; + return (ptr > limit) ? -1 : (ptr - beg); + } + +@@ -3729,8 +3729,8 @@ zfs_mount (grub_device_t dev) + } + + ub = &(data->current_uberblock); +- ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, +- GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC ++ ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, ++ GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC + ? GRUB_ZFS_LITTLE_ENDIAN : GRUB_ZFS_BIG_ENDIAN); + + err = zio_read (&ub->ub_rootbp, ub_endian, +@@ -3783,7 +3783,7 @@ grub_zfs_fetch_nvlist (grub_device_t dev, char **nvlist) + return err; + } + +-static grub_err_t ++static grub_err_t + zfs_label (grub_device_t device, char **label) + { + char *nvlist; +@@ -3795,7 +3795,7 @@ zfs_label (grub_device_t device, char **label) + return grub_errno; + + err = zfs_fetch_nvlist (data->device_original, &nvlist); +- if (err) ++ if (err) + { + zfs_unmount (data); + return err; +@@ -3807,7 +3807,7 @@ zfs_label (grub_device_t device, char **label) + return grub_errno; + } + +-static grub_err_t ++static grub_err_t + zfs_uuid (grub_device_t device, char **uuid) + { + struct grub_zfs_data *data; +@@ -3825,7 +3825,7 @@ zfs_uuid (grub_device_t device, char **uuid) + return GRUB_ERR_NONE; + } + +-static grub_err_t ++static grub_err_t + zfs_mtime (grub_device_t device, grub_int32_t *mt) + { + struct grub_zfs_data *data; +@@ -3839,8 +3839,8 @@ zfs_mtime (grub_device_t device, grub_int32_t *mt) + return grub_errno; + + ub = &(data->current_uberblock); +- ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, +- GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC ++ ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, ++ GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC + ? GRUB_ZFS_LITTLE_ENDIAN : GRUB_ZFS_BIG_ENDIAN); + + *mt = grub_zfs_to_cpu64 (ub->ub_timestamp, ub_endian); +@@ -3878,7 +3878,7 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) + } + + /* We found the dnode for this file. Verify if it is a plain file. */ +- if (data->dnode.dn.dn_type != DMU_OT_PLAIN_FILE_CONTENTS) ++ if (data->dnode.dn.dn_type != DMU_OT_PLAIN_FILE_CONTENTS) + { + zfs_unmount (data); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); +@@ -3953,7 +3953,7 @@ grub_zfs_read (grub_file_t file, char *buf, grub_size_t len) + return len; + } + +- blksz = grub_zfs_to_cpu16 (data->dnode.dn.dn_datablkszsec, ++ blksz = grub_zfs_to_cpu16 (data->dnode.dn.dn_datablkszsec, + data->dnode.endian) << SPA_MINBLOCKSHIFT; + + if (blksz == 0) +@@ -4046,11 +4046,11 @@ fill_fs_info (struct grub_dirhook_info *info, + dnode_end_t dn; + grub_uint64_t objnum; + grub_uint64_t headobj; +- ++ + grub_memset (info, 0, sizeof (*info)); +- ++ + info->dir = 1; +- ++ + if (mdn.dn.dn_type == DMU_OT_DSL_DIR) + { + headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&mdn.dn))->dd_head_dataset_obj, mdn.endian); +@@ -4065,28 +4065,28 @@ fill_fs_info (struct grub_dirhook_info *info, + err = make_mdn (&mdn, data); + if (err) + return err; +- err = dnode_get (&mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, ++ err = dnode_get (&mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, + &dn, data); + if (err) + { + grub_dprintf ("zfs", "failed here\n"); + return err; + } +- ++ + err = zap_lookup (&dn, ZFS_ROOT_OBJ, &objnum, data, 0); + if (err) + { + grub_dprintf ("zfs", "failed here\n"); + return err; + } +- ++ + err = dnode_get (&mdn, objnum, 0, &dn, data); + if (err) + { + grub_dprintf ("zfs", "failed here\n"); + return err; + } +- ++ + if (dn.dn.dn_bonustype == DMU_OT_SA) + { + void *sahdrp; +@@ -4172,15 +4172,15 @@ iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx) + info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); + info.case_insensitive = ctx->data->subvol.case_insensitive; + } +- ++ + if (dn.dn.dn_bonustype == DMU_OT_ZNODE) +- { ++ { + info.mtimeset = 1; + info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], + dn.endian); + } + info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS); +- grub_dprintf ("zfs", "type=%d, name=%s\n", ++ grub_dprintf ("zfs", "type=%d, name=%s\n", + (int)dn.dn.dn_type, (char *)name); + return ctx->hook (name, &info, ctx->hook_data); + } +@@ -4281,7 +4281,7 @@ grub_zfs_dir (grub_device_t device, const char *path, + + if (isfs) + { +- grub_uint64_t childobj, headobj; ++ grub_uint64_t childobj, headobj; + grub_uint64_t snapobj; + dnode_end_t dn; + struct grub_dirhook_info info; +@@ -4309,7 +4309,7 @@ grub_zfs_dir (grub_device_t device, const char *path, + } + + zap_iterate_u64 (&dn, iterate_zap_fs, data, &ctx); +- ++ + err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &dn, data); + if (err) + { +@@ -4351,8 +4351,8 @@ check_feature (const char *name, grub_uint64_t val, + return 0; + if (name[0] == 0) + return 0; +- for (i = 0; spa_feature_names[i] != NULL; i++) +- if (grub_strcmp (name, spa_feature_names[i]) == 0) ++ for (i = 0; spa_feature_names[i] != NULL; i++) ++ if (grub_strcmp (name, spa_feature_names[i]) == 0) + return 0; + return 1; + } +@@ -4365,7 +4365,7 @@ check_feature (const char *name, grub_uint64_t val, + * 0: Success. + * errnum: Failure. + */ +- ++ + static grub_err_t + check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data ) + { +@@ -4390,7 +4390,7 @@ check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct gru + errnum = zap_lookup(&dn, DMU_POOL_FEATURES_FOR_READ, &objnum, data,0); + if (errnum != 0) + return errnum; +- ++ + errnum = dnode_get(&mosmdn, objnum, DMU_OTN_ZAP_METADATA, &dn, data); + if (errnum != 0) + return errnum; +diff --git a/grub-core/fs/zfs/zfs_fletcher.c b/grub-core/fs/zfs/zfs_fletcher.c +index 7d27b05..ad3be67 100644 +--- a/grub-core/fs/zfs/zfs_fletcher.c ++++ b/grub-core/fs/zfs/zfs_fletcher.c +@@ -39,14 +39,14 @@ + #include + + void +-fletcher_2(const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, ++fletcher_2(const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, + zio_cksum_t *zcp) + { + const grub_uint64_t *ip = buf; + const grub_uint64_t *ipend = ip + (size / sizeof (grub_uint64_t)); + grub_uint64_t a0, b0, a1, b1; +- +- for (a0 = b0 = a1 = b1 = 0; ip < ipend; ip += 2) ++ ++ for (a0 = b0 = a1 = b1 = 0; ip < ipend; ip += 2) + { + a0 += grub_zfs_to_cpu64 (ip[0], endian); + a1 += grub_zfs_to_cpu64 (ip[1], endian); +@@ -61,14 +61,14 @@ fletcher_2(const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, + } + + void +-fletcher_4 (const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, ++fletcher_4 (const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, + zio_cksum_t *zcp) + { + const grub_uint32_t *ip = buf; + const grub_uint32_t *ipend = ip + (size / sizeof (grub_uint32_t)); + grub_uint64_t a, b, c, d; +- +- for (a = b = c = d = 0; ip < ipend; ip++) ++ ++ for (a = b = c = d = 0; ip < ipend; ip++) + { + a += grub_zfs_to_cpu32 (ip[0], endian);; + b += a; +diff --git a/grub-core/fs/zfs/zfs_sha256.c b/grub-core/fs/zfs/zfs_sha256.c +index a181f07..f042fa6 100644 +--- a/grub-core/fs/zfs/zfs_sha256.c ++++ b/grub-core/fs/zfs/zfs_sha256.c +@@ -116,23 +116,23 @@ zio_checksum_SHA256(const void *buf, grub_uint64_t size, + grub_uint8_t pad[128]; + unsigned padsize = size & 63; + unsigned i; +- ++ + for (i = 0; i < size - padsize; i += 64) + SHA256Transform(H, (grub_uint8_t *)buf + i); +- ++ + for (i = 0; i < padsize; i++) + pad[i] = ((grub_uint8_t *)buf)[i]; +- ++ + for (pad[padsize++] = 0x80; (padsize & 63) != 56; padsize++) + pad[padsize] = 0; +- ++ + for (i = 0; i < 8; i++) + pad[padsize++] = (size << 3) >> (56 - 8 * i); +- ++ + for (i = 0; i < padsize && i <= 64; i += 64) + SHA256Transform(H, pad + i); +- +- zcp->zc_word[0] = grub_cpu_to_zfs64 ((grub_uint64_t)H[0] << 32 | H[1], ++ ++ zcp->zc_word[0] = grub_cpu_to_zfs64 ((grub_uint64_t)H[0] << 32 | H[1], + endian); + zcp->zc_word[1] = grub_cpu_to_zfs64 ((grub_uint64_t)H[2] << 32 | H[3], + endian); +diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c +index de3b015..da30e9a 100644 +--- a/grub-core/fs/zfs/zfscrypt.c ++++ b/grub-core/fs/zfs/zfscrypt.c +@@ -46,7 +46,7 @@ + GRUB_MOD_LICENSE ("GPLv3+"); + + /* +- Mostly based on following article: ++ Mostly based on following article: + https://blogs.oracle.com/darren/entry/zfs_encryption_what_is_on + */ + +@@ -179,7 +179,7 @@ grub_gcm_mul (grub_uint8_t *a, const grub_uint8_t *b) + grub_crypto_xor (res, res, bs, 16); + grub_gcm_mul_x (bs); + } +- ++ + grub_memcpy (a, res, 16); + } + +@@ -275,7 +275,7 @@ algo_decrypt (grub_crypto_cipher_handle_t cipher, grub_uint64_t algo, + } + + static grub_err_t +-grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, ++grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, + grub_uint64_t algo, + void *nonce, + char *buf, grub_size_t size, +@@ -286,7 +286,7 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, + unsigned i; + grub_uint32_t sw[4]; + gcry_err_code_t err; +- ++ + grub_memcpy (sw, nonce, 16); + if (endian != GRUB_ZFS_BIG_ENDIAN) + for (i = 0; i < 4; i++) +@@ -302,7 +302,7 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, + sw + 1, 3, 12); + if (err) + return grub_crypto_gcry_error (err); +- ++ + for (i = 0; i < 3; i++) + if (grub_zfs_to_cpu32 (expected_mac[i], endian) + != grub_be_to_cpu32 (mac[i])) +@@ -362,7 +362,7 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, + grub_crypto_cipher_close (cipher); + continue; + } +- ++ + err = grub_crypto_cipher_set_key (cipher, wrap_key_real, + keylen); + if (err) +@@ -371,7 +371,7 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, + grub_crypto_cipher_close (cipher); + continue; + } +- ++ + err = algo_decrypt (cipher, algo, decrypted, key->unknown_purpose_key, 32, + mac, key->unknown_purpose_nonce, 2, 16); + if (err || (grub_crypto_memcmp (mac, key->unknown_purpose_key + 32, 16) +-- +2.43.5 + diff --git a/0671-fs-xfs-Fix-memory-leaks-in-XFS-module.patch b/0671-fs-xfs-Fix-memory-leaks-in-XFS-module.patch new file mode 100644 index 0000000..dc718c7 --- /dev/null +++ b/0671-fs-xfs-Fix-memory-leaks-in-XFS-module.patch @@ -0,0 +1,50 @@ +From a6405bff7be8359a790f536a3fe2b84b96cfeccd Mon Sep 17 00:00:00 2001 +From: "t.feng" +Date: Tue, 29 Nov 2022 17:14:15 +0800 +Subject: [PATCH 671/676] fs/xfs: Fix memory leaks in XFS module + +Signed-off-by: t.feng +Reviewed-by: Daniel Kiper +--- + grub-core/fs/xfs.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 4caf29f..171417d 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -598,7 +598,10 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + if (grub_disk_read (node->data->disk, + GRUB_XFS_FSB_TO_BLOCK (node->data, get_fsb (keys, i - 1 + recoffset)) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS), + 0, node->data->bsize, leaf)) +- return 0; ++ { ++ grub_free (leaf); ++ return 0; ++ } + + if ((!node->data->hascrc && + grub_strncmp ((char *) leaf->magic, "BMAP", 4)) || +@@ -789,6 +792,7 @@ static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename, + if (err) + { + grub_print_error (); ++ grub_free (fdiro); + return 0; + } + +@@ -906,7 +910,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + blk << dirblk_log2, + dirblk_size, dirblock, 0); + if (numread != dirblk_size) +- return 0; ++ { ++ grub_free (dirblock); ++ return 0; ++ } + + entries = (grub_be_to_cpu32 (tail->leaf_count) + - grub_be_to_cpu32 (tail->leaf_stale)); +-- +2.43.5 + diff --git a/0672-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch b/0672-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch new file mode 100644 index 0000000..56f1a0e --- /dev/null +++ b/0672-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch @@ -0,0 +1,51 @@ +From df644ea62c0c0c029ee05d298dc1c61b967bc9c9 Mon Sep 17 00:00:00 2001 +From: Lidong Chen +Date: Thu, 28 Sep 2023 22:33:44 +0000 +Subject: [PATCH 672/676] fs/xfs: Incorrect short form directory data boundary + check + +After parsing of the current entry, the entry pointer is advanced +to the next entry at the end of the "for" loop. In case where the +last entry is at the end of the data boundary, the advanced entry +pointer can point off the data boundary. The subsequent boundary +check for the advanced entry pointer can cause a failure. + +The fix is to include the boundary check into the "for" loop +condition. + +Signed-off-by: Lidong Chen +Reviewed-by: Daniel Kiper +Tested-by: Sebastian Andrzej Siewior +Tested-by: Marta Lewandowska +--- + grub-core/fs/xfs.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 171417d..a79d805 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -835,7 +835,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + if (iterate_dir_call_hook (parent, "..", &ctx)) + return 1; + +- for (i = 0; i < head->count; i++) ++ for (i = 0; i < head->count && ++ (grub_uint8_t *) de < ((grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data)); i++) + { + grub_uint64_t ino; + grub_uint8_t *inopos = grub_xfs_inline_de_inopos(dir->data, de); +@@ -870,10 +871,6 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + de->name[de->len] = c; + + de = grub_xfs_inline_next_de(dir->data, head, de); +- +- if ((grub_uint8_t *) de >= (grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data)) +- return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry"); +- + } + break; + } +-- +2.43.5 + diff --git a/0673-fs-xfs-Fix-XFS-directory-extent-parsing.patch b/0673-fs-xfs-Fix-XFS-directory-extent-parsing.patch new file mode 100644 index 0000000..793d6f9 --- /dev/null +++ b/0673-fs-xfs-Fix-XFS-directory-extent-parsing.patch @@ -0,0 +1,171 @@ +From e6845e0ad12d7f0a584e2a34da47a9d836efb0ad Mon Sep 17 00:00:00 2001 +From: Jon DeVree +Date: Tue, 17 Oct 2023 23:03:47 -0400 +Subject: [PATCH 673/676] fs/xfs: Fix XFS directory extent parsing + +The XFS directory entry parsing code has never been completely correct +for extent based directories. The parser correctly handles the case +where the directory is contained in a single extent, but then mistakenly +assumes the data blocks for the multiple extent case are each identical +to the single extent case. The difference in the format of the data +blocks between the two cases is tiny enough that its gone unnoticed for +a very long time. + +A recent change introduced some additional bounds checking into the XFS +parser. Like GRUB's existing parser, it is correct for the single extent +case but incorrect for the multiple extent case. When parsing a directory +with multiple extents, this new bounds checking is sometimes (but not +always) tripped and triggers an "invalid XFS directory entry" error. This +probably would have continued to go unnoticed but the /boot/grub/ +directory is large enough that it often has multiple extents. + +The difference between the two cases is that when there are multiple +extents, the data blocks do not contain a trailer nor do they contain +any leaf information. That information is stored in a separate set of +extents dedicated to just the leaf information. These extents come after +the directory entry extents and are not included in the inode size. So +the existing parser already ignores the leaf extents. + +The only reason to read the trailer/leaf information at all is so that +the parser can avoid misinterpreting that data as directory entries. So +this updates the parser as follows: + +For the single extent case the parser doesn't change much: +1. Read the size of the leaf information from the trailer +2. Set the end pointer for the parser to the start of the leaf + information. (The previous bounds checking set the end pointer to the + start of the trailer, so this is actually a small improvement.) +3. Set the entries variable to the expected number of directory entries. + +For the multiple extent case: +1. Set the end pointer to the end of the block. +2. Do not set up the entries variable. Figuring out how many entries are + in each individual block is complex and does not seem worth it when + it appears to be safe to just iterate over the entire block. + +The bounds check itself was also dependent upon the faulty XFS parser +because it accidentally used "filename + length - 1". Presumably this +was able to pass the fuzzer because in the old parser there was always +8 bytes of slack space between the tail pointer and the actual end of +the block. Since this is no longer the case the bounds check needs to be +updated to "filename + length + 1" in order to prevent a regression in +the handling of corrupt fliesystems. + +Notes: +* When there is only one extent there will only ever be one block. If + more than one block is required then XFS will always switch to holding + leaf information in a separate extent. +* B-tree based directories seems to be parsed properly by the same code + that handles multiple extents. This is unlikely to ever occur within + /boot though because its only used when there are an extremely large + number of directory entries. + +Fixes: ef7850c75 (fs/xfs: Fix issues found while fuzzing the XFS filesystem) +Fixes: b2499b29c (Adds support for the XFS filesystem.) +Fixes: https://savannah.gnu.org/bugs/?64376 + +Signed-off-by: Jon DeVree +Reviewed-by: Daniel Kiper +Tested-by: Sebastian Andrzej Siewior +Tested-by: Marta Lewandowska +--- + grub-core/fs/xfs.c | 52 +++++++++++++++++++++++++++++++++------------- + 1 file changed, 38 insertions(+), 14 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index a79d805..5beda40 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -223,6 +223,12 @@ struct grub_xfs_inode + /* Size of struct grub_xfs_inode v2, up to unused4 member included. */ + #define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 76) + ++struct grub_xfs_dir_leaf_entry ++{ ++ grub_uint32_t hashval; ++ grub_uint32_t address; ++} GRUB_PACKED; ++ + struct grub_xfs_dirblock_tail + { + grub_uint32_t leaf_count; +@@ -899,9 +905,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + { + struct grub_xfs_dir2_entry *direntry = + grub_xfs_first_de(dir->data, dirblock); +- int entries; +- struct grub_xfs_dirblock_tail *tail = +- grub_xfs_dir_tail(dir->data, dirblock); ++ int entries = -1; ++ char *end = dirblock + dirblk_size; + + numread = grub_xfs_read_file (dir, 0, 0, + blk << dirblk_log2, +@@ -912,14 +917,27 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + return 0; + } + +- entries = (grub_be_to_cpu32 (tail->leaf_count) +- - grub_be_to_cpu32 (tail->leaf_stale)); ++ /* ++ * Leaf and tail information are only in the data block if the number ++ * of extents is 1. ++ */ ++ if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1)) ++ { ++ struct grub_xfs_dirblock_tail *tail = grub_xfs_dir_tail (dir->data, dirblock); ++ ++ end = (char *) tail; ++ ++ /* Subtract the space used by leaf nodes. */ ++ end -= grub_be_to_cpu32 (tail->leaf_count) * sizeof (struct grub_xfs_dir_leaf_entry); + +- if (!entries) +- continue; ++ entries = grub_be_to_cpu32 (tail->leaf_count) - grub_be_to_cpu32 (tail->leaf_stale); ++ ++ if (!entries) ++ continue; ++ } + + /* Iterate over all entries within this block. */ +- while ((char *)direntry < (char *)tail) ++ while ((char *) direntry < (char *) end) + { + grub_uint8_t *freetag; + char *filename; +@@ -939,7 +957,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + } + + filename = (char *)(direntry + 1); +- if (filename + direntry->len - 1 > (char *) tail) ++ if (filename + direntry->len + 1 > (char *) end) + return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry"); + + /* The byte after the filename is for the filetype, padding, or +@@ -953,11 +971,17 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + return 1; + } + +- /* Check if last direntry in this block is +- reached. */ +- entries--; +- if (!entries) +- break; ++ /* ++ * The expected number of directory entries is only tracked for the ++ * single extent case. ++ */ ++ if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1)) ++ { ++ /* Check if last direntry in this block is reached. */ ++ entries--; ++ if (!entries) ++ break; ++ } + + /* Select the next directory entry. */ + direntry = grub_xfs_next_de(dir->data, direntry); +-- +2.43.5 + diff --git a/0674-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch b/0674-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch new file mode 100644 index 0000000..9f9bfda --- /dev/null +++ b/0674-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch @@ -0,0 +1,119 @@ +From 8aa1ebc1a094c7ae8eb6d2b11412bff99eda66b0 Mon Sep 17 00:00:00 2001 +From: Anthony Iliopoulos +Date: Thu, 26 Oct 2023 11:53:39 +0200 +Subject: [PATCH 674/676] fs/xfs: Add large extent counters incompat feature + support + +XFS introduced 64-bit extent counters for inodes via a series of +upstream commits and the feature was marked as stable in v6.5 via +commit 61d7e8274cd8 (xfs: drop EXPERIMENTAL tag for large extent +counts). + +Further, xfsprogs release v6.5.0 switched this feature on by default +in mkfs.xfs via commit e5b18d7d1d96 (mkfs: enable large extent counts +by default). + +Filesystems formatted with large extent count support, nrext64=1, are +thus currently not recognizable by GRUB, since this is an incompat +feature. Add the required support so that those filesystems and inodes +with large extent counters can be read by GRUB. + +Signed-off-by: Anthony Iliopoulos +Reviewed-by: Andrey Albershteyn +Reviewed-by: Daniel Kiper +Tested-by: Marta Lewandowska +Tested-by: Sebastian Andrzej Siewior +--- + grub-core/fs/xfs.c | 30 +++++++++++++++++++++++++----- + 1 file changed, 25 insertions(+), 5 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 5beda40..f74b316 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -79,6 +79,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); + /* Inode flags2 flags */ + #define XFS_DIFLAG2_BIGTIME_BIT 3 + #define XFS_DIFLAG2_BIGTIME (1 << XFS_DIFLAG2_BIGTIME_BIT) ++#define XFS_DIFLAG2_NREXT64_BIT 4 ++#define XFS_DIFLAG2_NREXT64 (1 << XFS_DIFLAG2_NREXT64_BIT) + + /* incompat feature flags */ + #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ +@@ -86,6 +88,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + #define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ + #define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */ + #define XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR (1 << 4) /* needs xfs_repair */ ++#define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 5) /* large extent counters */ + + /* + * Directory entries with ftype are explicitly handled by GRUB code. +@@ -101,7 +104,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); + XFS_SB_FEAT_INCOMPAT_SPINODES | \ + XFS_SB_FEAT_INCOMPAT_META_UUID | \ + XFS_SB_FEAT_INCOMPAT_BIGTIME | \ +- XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR) ++ XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR | \ ++ XFS_SB_FEAT_INCOMPAT_NREXT64) + + struct grub_xfs_sblock + { +@@ -203,7 +207,8 @@ struct grub_xfs_inode + grub_uint16_t mode; + grub_uint8_t version; + grub_uint8_t format; +- grub_uint8_t unused2[26]; ++ grub_uint8_t unused2[18]; ++ grub_uint64_t nextents_big; + grub_uint64_t atime; + grub_uint64_t mtime; + grub_uint64_t ctime; +@@ -547,11 +552,26 @@ get_fsb (const void *keys, int idx) + return grub_be_to_cpu64 (grub_get_unaligned64 (p)); + } + ++static int ++grub_xfs_inode_has_large_extent_counts (const struct grub_xfs_inode *inode) ++{ ++ return inode->version >= 3 && ++ (inode->flags2 & grub_cpu_to_be64_compile_time (XFS_DIFLAG2_NREXT64)); ++} ++ ++static grub_uint64_t ++grub_xfs_get_inode_nextents (struct grub_xfs_inode *inode) ++{ ++ return (grub_xfs_inode_has_large_extent_counts (inode)) ? ++ grub_be_to_cpu64 (inode->nextents_big) : ++ grub_be_to_cpu32 (inode->nextents); ++} ++ + static grub_disk_addr_t + grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + { + struct grub_xfs_btree_node *leaf = 0; +- int ex, nrec; ++ grub_uint64_t ex, nrec; + struct grub_xfs_extent *exts; + grub_uint64_t ret = 0; + +@@ -576,7 +596,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + / (2 * sizeof (grub_uint64_t)); + do + { +- int i; ++ grub_uint64_t i; + grub_addr_t keys_end, data_end; + if (grub_mul (sizeof (grub_uint64_t), nrec, &keys_end) || + grub_add ((grub_addr_t) keys, keys_end, &keys_end) || +@@ -633,7 +653,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + grub_addr_t exts_end = 0; + grub_addr_t data_end = 0; + +- nrec = grub_be_to_cpu32 (node->inode.nextents); ++ nrec = grub_xfs_get_inode_nextents (&node->inode); + exts = (struct grub_xfs_extent *) grub_xfs_inode_data(&node->inode); + + if (grub_mul (sizeof (struct grub_xfs_extent), nrec, &exts_end) || +-- +2.43.5 + diff --git a/0675-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch b/0675-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch new file mode 100644 index 0000000..2938e8d --- /dev/null +++ b/0675-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch @@ -0,0 +1,57 @@ +From 4011de1eec2ccd61246cffe7bb96822ed97942eb Mon Sep 17 00:00:00 2001 +From: Jon DeVree +Date: Sun, 11 Feb 2024 10:34:58 -0500 +Subject: [PATCH 675/676] fs/xfs: Handle non-continuous data blocks in + directory extents + +The directory extent list does not have to be a continuous list of data +blocks. When GRUB tries to read a non-existant member of the list, +grub_xfs_read_file() will return a block of zero'ed memory. Checking for +a zero'ed magic number is sufficient to skip this non-existant data block. + +Prior to commit 07318ee7e (fs/xfs: Fix XFS directory extent parsing) +this was handled as a subtle side effect of reading the (non-existant) +tail data structure. Since the block was zero'ed the computation of the +number of directory entries in the block would return 0 as well. + +Fixes: 07318ee7e (fs/xfs: Fix XFS directory extent parsing) +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2254370 + +Signed-off-by: Jon DeVree +Reviewed-By: Vladimir Serbinenko +Reviewed-by: Daniel Kiper +--- + grub-core/fs/xfs.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index f74b316..a5ab311 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -927,6 +927,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + grub_xfs_first_de(dir->data, dirblock); + int entries = -1; + char *end = dirblock + dirblk_size; ++ grub_uint32_t magic; + + numread = grub_xfs_read_file (dir, 0, 0, + blk << dirblk_log2, +@@ -937,6 +938,15 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + return 0; + } + ++ /* ++ * If this data block isn't actually part of the extent list then ++ * grub_xfs_read_file() returns a block of zeros. So, if the magic ++ * number field is all zeros then this block should be skipped. ++ */ ++ magic = *(grub_uint32_t *)(void *) dirblock; ++ if (!magic) ++ continue; ++ + /* + * Leaf and tail information are only in the data block if the number + * of extents is 1. +-- +2.43.5 + diff --git a/0676-fs-xfs-fix-large-extent-counters-incompat-feature-su.patch b/0676-fs-xfs-fix-large-extent-counters-incompat-feature-su.patch new file mode 100644 index 0000000..daea017 --- /dev/null +++ b/0676-fs-xfs-fix-large-extent-counters-incompat-feature-su.patch @@ -0,0 +1,48 @@ +From dd6867d45ecc3ca9bb5026ee5197a9d88f5d2888 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Wed, 4 Dec 2024 07:50:28 -0600 +Subject: [PATCH 676/676] fs/xfs: fix large extent counters incompat feature + support + +When large extent counter / NREXT64 support was added to grub, it missed +a couple of direct reads of nextents which need to be changed to the new +NREXT64-aware helper as well. Without this, we'll have mis-reads of some +directories with this feature enabled. + +(The large extent counter fix likely raced on merge with +07318ee7e ("fs/xfs: Fix XFS directory extent parsing") which added the new +direct nextents reads just prior, causing this issue.) + +Fixes: aa7c1322671e ("fs/xfs: Add large extent counters incompat feature support") +Signed-off-by: Eric Sandeen +Reviewed-by: Anthony Iliopoulos +Reviewed-by: Jon DeVree +--- + grub-core/fs/xfs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index a5ab311..148a0e5 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -951,7 +951,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + * Leaf and tail information are only in the data block if the number + * of extents is 1. + */ +- if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1)) ++ if (grub_xfs_get_inode_nextents(&dir->inode) == 1) + { + struct grub_xfs_dirblock_tail *tail = grub_xfs_dir_tail (dir->data, dirblock); + +@@ -1005,7 +1005,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + * The expected number of directory entries is only tracked for the + * single extent case. + */ +- if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1)) ++ if (grub_xfs_get_inode_nextents(&dir->inode) == 1) + { + /* Check if last direntry in this block is reached. */ + entries--; +-- +2.43.5 + diff --git a/0677-fs-ext2-Rework-out-of-bounds-read-for-inline-and-ext.patch b/0677-fs-ext2-Rework-out-of-bounds-read-for-inline-and-ext.patch new file mode 100644 index 0000000..162ee8f --- /dev/null +++ b/0677-fs-ext2-Rework-out-of-bounds-read-for-inline-and-ext.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Fri, 21 Feb 2025 09:06:12 +0800 +Subject: [PATCH] fs/ext2: Rework out-of-bounds read for inline and external + extents + +Previously, the number of extent entries was not properly capped based +on the actual available space. This could lead to insufficient reads for +external extents since the computation was based solely on the inline +extent layout. + +In this patch, when processing the extent header we determine whether +the header is stored inline, i.e. at inode->blocks.dir_blocks, or in an +external extent block. We then clamp the number of entries accordingly +(using max_inline_ext for inline extents and max_external_ext for +external extent blocks). + +This change ensures that only the valid number of extent entries is +processed preventing out-of-bound reads and potential filesystem +corruption. + +Fixes: 7e2f750f0a (fs/ext2: Fix out-of-bounds read for inline extents) + +Signed-off-by: Michael Chang +Tested-by: Christian Hesse +Reviewed-by: Daniel Kiper +--- + grub-core/fs/ext2.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c +index dc62a6c..b144549 100644 +--- a/grub-core/fs/ext2.c ++++ b/grub-core/fs/ext2.c +@@ -474,7 +474,10 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + int i; + grub_disk_addr_t ret; + grub_uint16_t nent; ++ /* Maximum number of extent entries in the inode's inline extent area. */ + const grub_uint16_t max_inline_ext = sizeof (inode->blocks) / sizeof (*ext) - 1; /* Minus 1 extent header. */ ++ /* Maximum number of extent entries in the external extent block. */ ++ const grub_uint16_t max_external_ext = EXT2_BLOCK_SIZE (data) / sizeof (*ext) - 1; /* Minus 1 extent header. */ + + leaf = grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, fileblock); + if (! leaf) +@@ -487,8 +490,18 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + + nent = grub_le_to_cpu16 (leaf->entries); + +- if (leaf->depth == 0) ++ /* ++ * Determine the effective number of extent entries (nent) to process. ++ * If the extent header (leaf) is stored inline in the inode’s block ++ * area, i.e. at inode->blocks.dir_blocks, then only max_inline_ext ++ * entries can fit. Otherwise, if the header was read from an external ++ * extent block use the larger limit, max_external_ext, based on the ++ * full block size. ++ */ ++ if (leaf == (struct grub_ext4_extent_header *) inode->blocks.dir_blocks) + nent = grub_min (nent, max_inline_ext); ++ else ++ nent = grub_min (nent, max_external_ext); + + for (i = 0; i < nent; i++) + { diff --git a/1001-bls-make-list.patch b/1001-bls-make-list.patch deleted file mode 100644 index ac39162..0000000 --- a/1001-bls-make-list.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhongling He -Date: Tue, 29 Mar 2022 17:27:13 +0800 -Subject: [PATCH] Fix a bug in bls_make_list, blscfg - -We have encountered a bug while running LifseaOS aarch64 version without -initrd. This commit fixes this bug. It may have fixed some potential -bugs as well. - -There are 4 partitions in a LifseaOS disk image: -- The 1st partition is for BIOS bootloader -- The 2nd partition is for UEFI booting, which contains grub binary - compiled from this source code, grubaa64.efi -- The 3rd partition contains grub.cfg files and - loader/entries/ostree-1-LifseaOS.conf -- The 4th partition contains rootfs - -Since x86_64 supports both BIOS and UEFI booting and we employ BIOS -booting for x86_64 (w/o initrd) image, we don't put the grub2 binary -compiled into the 2nd partition. As a result, this bug was not observed. -However, aarch64 only supports UEFI booting. In other words, we are -using this grub2 to boot LifseaOS (w/o initrd). - -grubaa64.efi from the 2nd partition will read `/grub2/grub.cfg` in the -3rd partition. - -``` -... - set ignition_firstboot="ignition.firstboot -${ignition_network_kcmdline}" -fi - -blscfg -``` - -`blscfg` is a command to convert `loader/entries/ostree-1-LifseaOS.conf` -into a typical grub.cfg. However, here comes the bug. While booting, an -error message will appear. - -``` -error: ../../grub-core/loader/arm64/linux.c:292:filename expected. -Press any key to continue. -``` - -This is because the bug in `blscfg` unexpectedly add a line, `initrd`, -into the generated grub.cfg file. Grub2 will expect an initrd file path -after `initrd`. As a result, the error occurs. - -In grub-core/command/blscfg.c:676, if `initrds` is a non-NULL pointer, -then `src` will contain a `initrd` line. - -``` -static void create_entry (struct bls_entry *entry){ - ... - initrds = bls_make_list (entry, "initrd", NULL); // - ... - if (initrds){ - ... - tmp = grub_stpcpy(initrd, "initrd "); - ... - } - ... - src = grub_xasprintf ("load_video\n" - "set gfx_payload=keep\n" - "insmod gzio\n" - "linux %s%s%s%s\n" - "%s", - GRUB_BOOT_DEVICE, clinux, options ? " " : "", options ? options -: "", - initrd ? initrd : ""); -``` - -In grub-core/command/blscfg.c:562, `bls_make_list` will always return a -non-NULL pointer except for a `grub_malloc` error. - -``` -static char **bls_make_list (struct bls_entry *entry, const char *key, -int *num) -{ - ... - list = grub_malloc (sizeof (char *)); - if (!list) - return NULL; - list[0] = NULL; - ... - return list; -} -``` - -Therefore, `initrd` like will be appended into the auto-generated -grub.cfg if `grub_malloc` succeed, regardless of whether initrd is -stated in config file. Our bug fix, same as upstream, modifies the -behaviour of `bls_make_list`. `bls_make_list` will now return a non-NULL -pointer only if the required field actually exists. - ---- - grub-core/commands/blscfg.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c -index 795a9f9..bf18270 100644 ---- a/grub-core/commands/blscfg.c -+++ b/grub-core/commands/blscfg.c -@@ -589,6 +589,12 @@ static char **bls_make_list (struct bls_entry *entry, const char *key, int *num) - list[nlist] = NULL; - } - -+ if (!nlist) -+ { -+ grub_free (list); -+ return NULL; -+ } -+ - if (num) - *num = nlist; - --- -2.27.0 - diff --git a/1002-Add-LoongArch64-support-and-update-interface-to-v40.patch b/1002-Add-LoongArch64-support-and-update-interface-to-v40.patch deleted file mode 100644 index 36750c1..0000000 --- a/1002-Add-LoongArch64-support-and-update-interface-to-v40.patch +++ /dev/null @@ -1,3444 +0,0 @@ -From 478205a88ea71b0c546987602cd879027819125e Mon Sep 17 00:00:00 2001 -From: yangqiming -Date: Thu, 7 Jul 2022 11:25:02 +0800 -Subject: [PATCH] Add LoongArch64 support and update interface to V40 - - -diff --git a/conf/Makefile.common b/conf/Makefile.common -index 521cdda..d9f058b 100644 ---- a/conf/Makefile.common -+++ b/conf/Makefile.common -@@ -20,6 +20,10 @@ endif - if COND_powerpc_ieee1275 - CFLAGS_PLATFORM += -mcpu=powerpc - endif -+if COND_loongarch64 -+ CFLAGS_PLATFORM += -fno-strict-aliasing -march=loongarch64 -mabi=lp64 -fno-plt -Wa,-mla-global-with-abs -mcmodel=large -+ CPPFLAGS_PLATFORM = -fno-strict-aliasing -march=loongarch64 -mabi=lp64 -fno-plt -Wa,-mla-global-with-abs -mcmodel=large -+endif - - # Other options - -diff --git a/configure.ac b/configure.ac -index f59a7b8..4715d17 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -116,6 +116,10 @@ case "$target_cpu" in - i[[3456]]86) target_cpu=i386 ;; - amd64) target_cpu=x86_64 ;; - sparc) target_cpu=sparc64 ;; -+ loongarch64) -+ target_cpu=loongarch64 -+ machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_LOONGARCH64=1" -+ ;; - mipsel|mips64el) - target_cpu=mipsel - machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPSEL=1" -@@ -148,6 +152,7 @@ if test "x$with_platform" = x; then - powerpc64-*) platform=ieee1275 ;; - powerpc64le-*) platform=ieee1275 ;; - sparc64-*) platform=ieee1275 ;; -+ loongarch64-*) platform=efi;; - mipsel-*) platform=loongson ;; - mips-*) platform=arc ;; - ia64-*) platform=efi ;; -@@ -196,6 +201,7 @@ case "$target_cpu"-"$platform" in - mipsel-yeeloong) platform=loongson ;; - mipsel-fuloong) platform=loongson ;; - mipsel-loongson) ;; -+ loongarch64-efi) ;; - arm-uboot) ;; - arm-coreboot) ;; - arm-efi) ;; -@@ -251,6 +257,7 @@ case "$platform" in - pc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_PCBIOS=1" ;; - emu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EMU=1" ;; - loongson) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_LOONGSON=1" ;; -+ loongson64) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_LOONARCH64=1" ;; - qemu_mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_QEMU_MIPS=1" ;; - arc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_ARC=1" ;; - esac -@@ -2098,6 +2105,8 @@ AM_CONDITIONAL([COND_mips_arc], [test "(" x$target_cpu = xmips -o x$target_cpu = - AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275]) - AM_CONDITIONAL([COND_sparc64_emu], [test x$target_cpu = xsparc64 -a x$platform = xemu]) - AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275]) -+AM_CONDITIONAL([COND_loongarch64_efi], [test x$target_cpu = xloongarch64 -a x$platform = xefi]) -+AM_CONDITIONAL([COND_loongarch64], [test x$target_cpu = xloongarch64]) - AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips -o x$target_cpu = xmipsel]) - AM_CONDITIONAL([COND_mipsel], [test x$target_cpu = xmipsel]) - AM_CONDITIONAL([COND_mipseb], [test x$target_cpu = xmips]) -diff --git a/gentpl.py b/gentpl.py -index d662c30..3afd642 100644 ---- a/gentpl.py -+++ b/gentpl.py -@@ -32,7 +32,7 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", - "mips_loongson", "sparc64_ieee1275", - "powerpc_ieee1275", "mips_arc", "ia64_efi", - "mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi", -- "arm_coreboot"] -+ "arm_coreboot", "loongarch64_efi"] - - GROUPS = {} - -@@ -44,13 +44,14 @@ GROUPS["x86_64"] = [ "x86_64_efi" ] - GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"] - GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ] - GROUPS["sparc64"] = [ "sparc64_ieee1275" ] -+GROUPS["loongarch64"] = [ "loongarch64_efi" ] - GROUPS["powerpc"] = [ "powerpc_ieee1275" ] - GROUPS["arm"] = [ "arm_uboot", "arm_efi", "arm_coreboot" ] - GROUPS["arm64"] = [ "arm64_efi" ] - - # Groups based on firmware - GROUPS["pc"] = [ "i386_pc" ] --GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi" ] -+GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi", "loongarch64_efi"] - GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ] - GROUPS["uboot"] = [ "arm_uboot" ] - GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ] -diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am -index 308ad88..a976fad 100644 ---- a/grub-core/Makefile.am -+++ b/grub-core/Makefile.am -@@ -222,6 +222,14 @@ KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h - KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h - endif - -+if COND_loongarch64_efi -+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h -+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h -+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h -+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdt.h -+KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loongson.h -+endif -+ - if COND_powerpc_ieee1275 - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index ef06f8c..54f6bf0 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -95,6 +95,9 @@ kernel = { - arm_coreboot_ldflags = '-Wl,-r,-d'; - arm_coreboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; - -+ loongarch64_efi_ldflags = '-Wl,-r,-d'; -+ loongarch64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; -+ - i386_pc_startup = kern/i386/pc/startup.S; - i386_efi_startup = kern/i386/efi/startup.S; - x86_64_efi_startup = kern/x86_64/efi/startup.S; -@@ -105,6 +108,7 @@ kernel = { - i386_coreboot_startup = kern/i386/coreboot/startup.S; - i386_multiboot_startup = kern/i386/coreboot/startup.S; - mips_startup = kern/mips/startup.S; -+ loongarch64_efi_startup = kern/loongarch64/efi/startup.S; - sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S; - powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; - arm_uboot_startup = kern/arm/startup.S; -@@ -295,6 +299,15 @@ kernel = { - extra_dist = video/sis315_init.c; - mips_loongson = commands/keylayouts.c; - -+ loongarch64 = kern/loongarch64/init.c; -+ loongarch64 = kern/loongarch64/dl.c; -+ loongarch64 = kern/loongarch64/cache.S; -+ loongarch64 = kern/generic/rtc_get_time_ms.c; -+ loongarch64 = kern/efi/fdt.c; -+ loongarch64 = lib/fdt.c; -+ loongarch64_efi = kern/loongarch64/efi/init.c; -+ loongarch64_efi = lib/loongarch64/efi/loongson.c; -+ - powerpc_ieee1275 = kern/powerpc/cache.S; - powerpc_ieee1275 = kern/powerpc/dl.c; - powerpc_ieee1275 = kern/powerpc/compiler-rt.S; -@@ -810,6 +823,7 @@ module = { - enable = sparc64_ieee1275; - enable = powerpc_ieee1275; - enable = mips_arc; -+ enable = loongarch64_efi; - enable = ia64_efi; - enable = arm_efi; - enable = arm64_efi; -@@ -896,6 +910,7 @@ module = { - i386_qemu = lib/i386/halt.c; - xen = lib/xen/halt.c; - efi = lib/efi/halt.c; -+ loongarch64_efi = commands/acpihalt.c; - ieee1275 = lib/ieee1275/halt.c; - emu = lib/emu/halt.c; - uboot = lib/dummy/halt.c; -@@ -911,6 +926,7 @@ module = { - mips_arc = lib/mips/arc/reboot.c; - mips_loongson = lib/mips/loongson/reboot.c; - mips_qemu_mips = lib/mips/qemu_mips/reboot.c; -+ loongarch64_efi = lib/loongson/reboot.c; - xen = lib/xen/reboot.c; - uboot = lib/uboot/reboot.c; - arm_coreboot = lib/dummy/reboot.c; -@@ -1608,6 +1624,8 @@ module = { - efi = lib/efi/relocator.c; - mips = lib/mips/relocator_asm.S; - mips = lib/mips/relocator.c; -+ loongarch64 = lib/loongarch64/relocator_asm.S; -+ loongarch64 = lib/loongarch64/relocator.c; - powerpc = lib/powerpc/relocator_asm.S; - powerpc = lib/powerpc/relocator.c; - xen = lib/xen/relocator.c; -@@ -1620,6 +1638,7 @@ module = { - extra_dist = kern/powerpc/cache_flush.S; - - enable = mips; -+ enable = loongarch64; - enable = powerpc; - enable = x86; - enable = xen; -@@ -1737,6 +1756,7 @@ module = { - xen = loader/i386/xen.c; - i386_pc = lib/i386/pc/vesa_modes_table.c; - mips = loader/mips/linux.c; -+ loongarch64 = loader/loongarch64/linux.c; - powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c; - sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c; - ia64_efi = loader/ia64/efi/linux.c; -@@ -1838,6 +1858,7 @@ module = { - enable = arm_efi; - enable = arm64_efi; - enable = mips; -+ enable = loongarch64_efi; - }; - - module = { -diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index 8a89614..0b5f158 100644 ---- a/grub-core/kern/efi/mm.c -+++ b/grub-core/kern/efi/mm.c -@@ -122,7 +122,11 @@ grub_efi_allocate_pages_max (grub_efi_physical_address_t max, - grub_efi_boot_services_t *b; - grub_efi_physical_address_t address = max; - -+#ifdef GRUB_CPU_LOONGARCH64 -+ if (max > grub_efi_max_usable_address()) -+#else - if (max > GRUB_EFI_MAX_USABLE_ADDRESS) -+#endif - return 0; - - b = grub_efi_system_table->boot_services; -@@ -157,11 +161,19 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, - grub_efi_physical_address_t ret = address; - - /* Limit the memory access to less than 4GB for 32-bit platforms. */ -+#ifdef GRUB_CPU_LOONGARCH64 -+ if (address > grub_efi_max_usable_address()) -+ { -+ grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("invalid memory address 0x%llx"), -+ address); -+#else - if (address > GRUB_EFI_MAX_USABLE_ADDRESS) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, - N_("invalid memory address (0x%llx > 0x%llx)"), - address, GRUB_EFI_MAX_USABLE_ADDRESS); -+#endif - return NULL; - } - -@@ -177,7 +189,11 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, - { - /* Uggh, the address 0 was allocated... This is too annoying, - so reallocate another one. */ -+#ifdef GRUB_CPU_LOONGARCH64 -+ ret = grub_efi_max_usable_address(); -+#else - ret = address; -+#endif - status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &ret); - grub_efi_free_pages (0, pages); - if (status != GRUB_EFI_SUCCESS) -@@ -195,9 +211,15 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, - void * - grub_efi_allocate_any_pages (grub_efi_uintn_t pages) - { -+#ifdef GRUB_CPU_LOONGARCH64 -+ return grub_efi_allocate_pages_real (grub_efi_max_usable_address(), -+ pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, -+ GRUB_EFI_LOADER_DATA); -+#else - return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS, - pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, - GRUB_EFI_LOADER_DATA); -+#endif - } - - void * -@@ -471,7 +493,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, - desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) - { - if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY --#if 1 -+#ifdef GRUB_CPU_LOONGARCH64 -+ && desc->physical_start <= grub_efi_max_usable_address() -+#else - && desc->physical_start <= GRUB_EFI_MAX_ALLOCATION_ADDRESS - #endif - && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000 -@@ -487,7 +511,14 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, - desc->physical_start = 0x100000; - } - --#if 1 -+#ifdef GRUB_CPU_LOONGARCH64 -+ if (BYTES_TO_PAGES (filtered_desc->physical_start) -+ + filtered_desc->num_pages -+ > BYTES_TO_PAGES_DOWN (grub_efi_max_usable_address())) -+ filtered_desc->num_pages -+ = (BYTES_TO_PAGES_DOWN (grub_efi_max_usable_address()) -+ - BYTES_TO_PAGES (filtered_desc->physical_start)); -+#else - if (BYTES_TO_PAGES (filtered_desc->physical_start) - + filtered_desc->num_pages - > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS)) -@@ -765,7 +796,7 @@ grub_efi_mm_init (void) - 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); - } - --#if defined (__aarch64__) || defined (__arm__) -+#if defined (__aarch64__) || defined (__arm__) || defined (__loongarch__) - grub_err_t - grub_efi_get_ram_base(grub_addr_t *base_addr) - { -@@ -784,9 +815,15 @@ grub_efi_get_ram_base(grub_addr_t *base_addr) - if (ret < 1) - return GRUB_ERR_BUG; - -+#ifdef GRUB_CPU_LOONGARCH64 -+ for (desc = memory_map, *base_addr = grub_efi_max_usable_address(); -+ (grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size); -+ desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) -+#else - for (desc = memory_map, *base_addr = GRUB_EFI_MAX_USABLE_ADDRESS; - (grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size); - desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) -+#endif - { - if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY && - (desc->attribute & GRUB_EFI_MEMORY_WB)) -@@ -800,7 +837,11 @@ grub_efi_get_ram_base(grub_addr_t *base_addr) - } - } - -+#ifdef GRUB_CPU_LOONGARCH64 -+ if (*base_addr == grub_efi_max_usable_address()) -+#else - if (*base_addr == GRUB_EFI_MAX_USABLE_ADDRESS) -+#endif - grub_dprintf ("efi", "base_addr 0x%016lx is probably wrong.\n", *base_addr); - - grub_free(memory_map); -diff --git a/grub-core/kern/loongarch64/cache.S b/grub-core/kern/loongarch64/cache.S -new file mode 100644 -index 0000000..d291c67 ---- /dev/null -+++ b/grub-core/kern/loongarch64/cache.S -@@ -0,0 +1,26 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2009,2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+ -+FUNCTION (grub_arch_sync_caches) -+ jr $ra -+ -+FUNCTION (grub_arch_sync_dma_caches) -+ jr $ra -+ -diff --git a/grub-core/kern/loongarch64/dl.c b/grub-core/kern/loongarch64/dl.c -new file mode 100644 -index 0000000..7d9e2a1 ---- /dev/null -+++ b/grub-core/kern/loongarch64/dl.c -@@ -0,0 +1,266 @@ -+/* loongarch64/dl.c - arch-dependent part of loadable module support */ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2002,2005,2007,2009,2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Check if EHDR is a valid ELF header. */ -+grub_err_t -+grub_arch_dl_check_header (void *ehdr) -+{ -+ Elf_Ehdr *e = ehdr; -+ -+ /* Check the magic numbers. */ -+ if (e->e_ident[EI_CLASS] != ELFCLASS64 -+ || e->e_ident[EI_DATA] != ELFDATA2LSB -+ || e->e_machine != EM_LOONGARCH64) -+ return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic")); -+ -+ return GRUB_ERR_NONE; -+} -+ -+#pragma GCC diagnostic ignored "-Wcast-align" -+ -+grub_err_t -+grub_arch_dl_get_tramp_got_size (const void *ehdr __attribute__ ((unused)), -+ grub_size_t *tramp, grub_size_t *got) -+{ -+ *tramp = 0; -+ *got = 0; -+ return GRUB_ERR_NONE; -+} -+ -+/* Relocate symbols. */ -+grub_err_t -+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, -+ Elf_Shdr *s, grub_dl_segment_t seg) -+{ -+ Elf_Ehdr *e = ehdr; -+ Elf_Rel *rel, *max; -+ grub_uint64_t oprs[10240]={0}; -+ int opri=-1; -+ grub_uint32_t la_abs = 0; -+ -+ for (rel = (Elf_Rel *) ((char *) e + s->sh_offset), -+ max = (Elf_Rel *) ((char *) rel + s->sh_size); -+ rel < max; -+ rel = (Elf_Rel *) ((char *) rel + s->sh_entsize)) -+ { -+ grub_uint8_t *addr; -+ Elf_Sym *sym; -+ Elf_Addr r_info; -+ grub_uint64_t sym_value; -+ -+ if (seg->size < rel->r_offset) -+ return grub_error (GRUB_ERR_BAD_MODULE, -+ "reloc offset is out of the segment"); -+ -+ r_info = (grub_uint64_t) (rel->r_info); -+ -+ addr = (grub_uint8_t *) ((char*)seg->addr + rel->r_offset); -+ sym = (Elf_Sym *) ((char*)mod->symtab -+ + mod->symsize * ELF_R_SYM (r_info)); -+ sym_value = sym->st_value; -+ if (s->sh_type == SHT_RELA) -+ { -+ sym_value += ((Elf_Rela *) rel)->r_addend; -+ } -+ switch (ELF_R_TYPE (r_info)) -+ { -+ case R_LARCH_64: -+ { -+ *(grub_uint64_t *)addr=(grub_uint64_t)sym_value; -+ } -+ break; -+ case R_LARCH_MARK_LA: -+ { -+ la_abs=1; -+ } -+ break; -+ case R_LARCH_SOP_PUSH_PCREL: -+ { -+ opri++; -+ oprs[opri]=(grub_uint64_t)(sym_value-(grub_uint64_t)addr); -+ } -+ break; -+ case R_LARCH_SOP_PUSH_ABSOLUTE: -+ { -+ opri++; -+ oprs[opri]=(grub_uint64_t)sym_value; -+ } -+ break; -+ case R_LARCH_SOP_PUSH_PLT_PCREL: -+ { -+ opri++; -+ oprs[opri]=(grub_uint64_t)(sym_value-(grub_uint64_t)addr); -+ } -+ break; -+ case R_LARCH_SOP_SUB: -+ { -+ grub_uint64_t opr2=oprs[opri]; -+ opri--; -+ grub_uint64_t opr1=oprs[opri]; -+ opri--; -+ opri++; -+ oprs[opri]=opr1 - opr2; -+ } -+ break; -+ case R_LARCH_SOP_SL: -+ { -+ grub_uint64_t opr2=oprs[opri]; -+ opri--; -+ grub_uint64_t opr1=oprs[opri]; -+ opri--; -+ opri++; -+ oprs[opri]=opr1 << opr2; -+ } -+ break; -+ case R_LARCH_SOP_SR: -+ { -+ grub_uint64_t opr2=oprs[opri]; -+ opri--; -+ grub_uint64_t opr1=oprs[opri]; -+ opri--; -+ opri++; -+ oprs[opri]=opr1 >> opr2; -+ } -+ break; -+ case R_LARCH_SOP_ADD: -+ { -+ grub_uint64_t opr2=oprs[opri]; -+ opri--; -+ grub_uint64_t opr1=oprs[opri]; -+ opri--; -+ opri++; -+ oprs[opri]=opr1 + opr2; -+ } -+ break; -+ case R_LARCH_SOP_AND: -+ { -+ grub_uint64_t opr2=oprs[opri]; -+ opri--; -+ grub_uint64_t opr1=oprs[opri]; -+ opri--; -+ opri++; -+ oprs[opri]=opr1 & opr2; -+ } -+ break; -+ case R_LARCH_SOP_IF_ELSE: -+ { -+ grub_uint64_t opr3=oprs[opri]; -+ opri--; -+ grub_uint64_t opr2=oprs[opri]; -+ opri--; -+ grub_uint64_t opr1=oprs[opri]; -+ opri--; -+ if(opr1){ -+ opri++; -+ oprs[opri]=opr2; -+ } else { -+ opri++; -+ oprs[opri]=opr3; -+ } -+ } -+ break; -+ case R_LARCH_SOP_POP_32_S_10_5: -+ { -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | ((opr1 & 0x1f) << 10); -+ } -+ break; -+ case R_LARCH_SOP_POP_32_U_10_12: -+ { -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | ((opr1 & 0xfff) << 10); -+ } -+ break; -+ case R_LARCH_SOP_POP_32_S_10_12: -+ { -+ if(la_abs==1) -+ la_abs=0; -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *(grub_uint64_t *)addr= (*(grub_uint64_t *)addr) | ((opr1 & 0xfff) << 10); -+ } -+ break; -+ case R_LARCH_SOP_POP_32_S_10_16: -+ { -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *(grub_uint64_t *)addr= (*(grub_uint64_t *)addr) | ((opr1 & 0xffff) << 10); -+ } -+ break; -+ case R_LARCH_SOP_POP_32_S_10_16_S2: -+ { -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *(grub_uint64_t *)addr= (*(grub_uint64_t *)addr) | (((opr1 >> 2) & 0xffff) << 10); -+ } -+ break; -+ case R_LARCH_SOP_POP_32_S_5_20: -+ { -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *(grub_uint64_t *)addr= (*(grub_uint64_t *)addr) | ((opr1 & 0xfffff)<<5) ; -+ } -+ break; -+ case R_LARCH_SOP_POP_32_S_0_5_10_16_S2: -+ { -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | (((opr1 >> 2) & 0xffff) << 10); -+ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | ((opr1 >> 18) & 0x1f); -+ } -+ break; -+ case R_LARCH_SOP_POP_32_S_0_10_10_16_S2: -+ { -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | (((opr1 >> 2) & 0xffff) << 10); -+ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | ((opr1 >> 18) & 0x3ff); -+ } -+ break; -+ default: -+ { -+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, -+ N_("relocation 0x%x is not implemented yet"), -+ ELF_R_TYPE (r_info)); -+ } -+ break; -+ } -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+ return 1; -+} -diff --git a/grub-core/kern/loongarch64/efi/init.c b/grub-core/kern/loongarch64/efi/init.c -new file mode 100644 -index 0000000..632c39a ---- /dev/null -+++ b/grub-core/kern/loongarch64/efi/init.c -@@ -0,0 +1,74 @@ -+/* init.c - initialize an arm-based EFI system */ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2013 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static grub_uint64_t tmr; -+static grub_efi_event_t tmr_evt; -+ -+static grub_uint64_t -+grub_efi_get_time_ms (void) -+{ -+ return tmr; -+} -+ -+static void -+grub_loongson_increment_timer (grub_efi_event_t event __attribute__ ((unused)), -+ void *context __attribute__ ((unused))) -+{ -+ tmr += 10; -+} -+ -+void -+grub_machine_init (void) -+{ -+ grub_efi_boot_services_t *b; -+ -+ grub_efi_init (); -+ -+ b = grub_efi_system_table->boot_services; -+ efi_call_5 (b->create_event, GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL, -+ GRUB_EFI_TPL_CALLBACK, grub_loongson_increment_timer, NULL, &tmr_evt); -+ efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 100000); -+ -+ grub_install_get_time_ms (grub_efi_get_time_ms); -+} -+ -+void -+grub_machine_fini (int flags) -+{ -+ grub_efi_boot_services_t *b; -+ -+ if (!(flags & GRUB_LOADER_FLAG_NORETURN)) -+ return; -+ -+ b = grub_efi_system_table->boot_services; -+ -+ efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_CANCEL, 0); -+ efi_call_1 (b->close_event, tmr_evt); -+ -+ grub_efi_fini (); -+} -diff --git a/grub-core/kern/loongarch64/efi/startup.S b/grub-core/kern/loongarch64/efi/startup.S -new file mode 100644 -index 0000000..1ffff08 ---- /dev/null -+++ b/grub-core/kern/loongarch64/efi/startup.S -@@ -0,0 +1,45 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2013 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+ -+ .file "startup.S" -+ .text -+ .globl start, _start -+ .align 4 -+ -+FUNCTION(start) -+FUNCTION(_start) -+ /* -+ * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in a1/a0. -+ */ -+ addi.d $sp, $sp, -16 -+ st.d $ra, $sp, 0 -+ -+ la $a2, grub_efi_image_handle -+ st.d $a0, $a2, 0 -+ la $a2, grub_efi_system_table -+ st.d $a1, $a2, 0 -+ -+ bl grub_main -+ -+1: -+ ld.d $ra, $sp, 0 -+ addi.d $sp, $sp, 16 -+ jr $ra -+ -diff --git a/grub-core/kern/loongarch64/init.c b/grub-core/kern/loongarch64/init.c -new file mode 100644 -index 0000000..b2de930 ---- /dev/null -+++ b/grub-core/kern/loongarch64/init.c -@@ -0,0 +1,47 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2009,2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+ -+grub_uint32_t grub_arch_cpuclock; -+ -+/* FIXME: use interrupt to count high. */ -+grub_uint64_t -+grub_get_rtc (void) -+{ -+ static grub_uint32_t high = 0; -+ static grub_uint32_t last = 0; -+ grub_uint32_t low; -+ -+ asm volatile ("csrrd %0, " GRUB_CPU_LOONGARCH_COP0_TIMER_COUNT : "=r" (low)); -+ if (low < last) -+ high++; -+ last = low; -+ -+ return (((grub_uint64_t) high) << 32) | low; -+} -+ -+void -+grub_timer_init (grub_uint32_t cpuclock) -+{ -+ grub_arch_cpuclock = cpuclock; -+ grub_install_get_time_ms (grub_rtc_get_time_ms); -+} -diff --git a/grub-core/lib/loongarch64/efi/loongson.c b/grub-core/lib/loongarch64/efi/loongson.c -new file mode 100644 -index 0000000..eda1e1c ---- /dev/null -+++ b/grub-core/lib/loongarch64/efi/loongson.c -@@ -0,0 +1,119 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+unsigned long -+grub_efi_get_bpi_version (const char *str) -+{ -+ unsigned long version = GRUB_EFI_BPI_VER_NONE; -+ -+ version = grub_strtoul (str + 4, 0, 0); -+ -+ return version; -+} -+ -+void * -+grub_efi_loongson_get_boot_params (void) -+{ -+ static void * boot_params = NULL; -+ grub_efi_configuration_table_t *tables; -+ grub_efi_guid_t loongson_bpi_guid = GRUB_EFI_LOONGSON_BPI_TABLE_GUID; -+ unsigned int i; -+ -+ if (boot_params) -+ return boot_params; -+ -+ /* Look for Loongson boot params interface in UEFI config tables. */ -+ tables = grub_efi_system_table->configuration_table; -+ -+ for (i = 0; i < grub_efi_system_table->num_table_entries; i++) -+ if (grub_memcmp (&tables[i].vendor_guid, &loongson_bpi_guid, sizeof (loongson_bpi_guid)) == 0) -+ { -+ boot_params= tables[i].vendor_table; -+ grub_dprintf ("loongson", "found registered BPI @ %p\n", boot_params); -+ break; -+ } -+ return boot_params; -+} -+ -+grub_uint8_t -+grub_efi_loongson_calculatesum8 (const grub_uint8_t *buffer, grub_efi_uintn_t length) -+{ -+ grub_uint8_t sum; -+ grub_efi_uintn_t count; -+ -+ for (sum = 0, count = 0; count < length; count++) -+ { -+ sum = (grub_uint8_t) (sum + *(buffer + count)); -+ } -+ return sum; -+} -+ -+grub_uint8_t -+grub_efi_loongson_grub_calculatechecksum8 (const grub_uint8_t *buffer, grub_efi_uintn_t length) -+{ -+ grub_uint8_t checksum; -+ -+ checksum = grub_efi_loongson_calculatesum8(buffer, length); -+ -+ return (grub_uint8_t) (0x100 - checksum); -+} -+ -+ -+grub_uint32_t -+grub_efi_loongson_memmap_v1_sort(struct memmap_v1 array[], grub_uint32_t length, -+ mem_map_v1 * bpmem, grub_uint32_t index, grub_uint32_t memtype) -+{ -+ grub_uint64_t tempmemsize = 0; -+ grub_uint32_t j = 0; -+ grub_uint32_t t = 0; -+ -+ for(j = 0; j < length;) -+ { -+ tempmemsize = array[j].memsize; -+ for(t = j + 1; t < length; t++) -+ { -+ if(array[j].memstart + tempmemsize == array[t].memstart) -+ { -+ tempmemsize += array[t].memsize; -+ } -+ else -+ { -+ break; -+ } -+ } -+ bpmem->map[index].memtype = memtype; -+ bpmem->map[index].memstart = array[j].memstart; -+ bpmem->map[index].memsize = tempmemsize; -+ grub_dprintf("loongson", "v1 map[%d]:type %x, start 0x%lx, end 0x%lx\n", -+ index, -+ bpmem->map[index].memtype, -+ bpmem->map[index].memstart, -+ bpmem->map[index].memstart+ bpmem->map[index].memsize -+ ); -+ j = t; -+ index++; -+ } -+ return index; -+} -diff --git a/grub-core/lib/loongarch64/relocator.c b/grub-core/lib/loongarch64/relocator.c -new file mode 100644 -index 0000000..4b253ca ---- /dev/null -+++ b/grub-core/lib/loongarch64/relocator.c -@@ -0,0 +1,163 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+extern grub_uint8_t grub_relocator_forward_start; -+extern grub_uint8_t grub_relocator_forward_end; -+extern grub_uint8_t grub_relocator_backward_start; -+extern grub_uint8_t grub_relocator_backward_end; -+ -+#define REGW_SIZEOF (4 * sizeof (grub_uint32_t)) -+#define JUMP_SIZEOF (2 * sizeof (grub_uint32_t)) -+ -+#define RELOCATOR_SRC_SIZEOF(x) (&grub_relocator_##x##_end \ -+ - &grub_relocator_##x##_start) -+#define RELOCATOR_SIZEOF(x) (RELOCATOR_SRC_SIZEOF(x) \ -+ + REGW_SIZEOF * 3) -+grub_size_t grub_relocator_align = sizeof (grub_uint64_t); -+grub_size_t grub_relocator_forward_size; -+grub_size_t grub_relocator_backward_size; -+grub_size_t grub_relocator_jumper_size = JUMP_SIZEOF + REGW_SIZEOF; -+ -+void -+grub_cpu_relocator_init (void) -+{ -+ grub_relocator_forward_size = RELOCATOR_SIZEOF(forward); -+ grub_relocator_backward_size = RELOCATOR_SIZEOF(backward); -+} -+ -+static void -+write_reg (int regn, grub_uint64_t val, void **target) -+{ -+ grub_uint32_t lu12iw=0x14000000; -+ grub_uint32_t ori=0x03800000; -+ grub_uint32_t lu32id=0x16000000; -+ grub_uint32_t lu52id=0x03000000; -+ -+ *(grub_uint32_t *) *target = (lu12iw | (grub_uint32_t)((val & 0xfffff000)>>12<<5) | (grub_uint32_t)regn);; -+ *target = ((grub_uint32_t *) *target) + 1; -+ *(grub_uint32_t *) *target = (ori | (grub_uint32_t)((val & 0xfff)<<10) | (grub_uint32_t)(regn | regn<<5)); -+ *target = ((grub_uint32_t *) *target) + 1; -+ *(grub_uint32_t *) *target = (lu32id | (grub_uint32_t)((val & 0xfffff00000000)>>32<<5) | (grub_uint32_t)regn);; -+ *target = ((grub_uint32_t *) *target) + 1; -+ *(grub_uint32_t *) *target = (lu52id | (grub_uint32_t)((val & 0xfff0000000000000)>>52<<10) | (grub_uint32_t)(regn | regn<<5));; -+ *target = ((grub_uint32_t *) *target) + 1; -+} -+ -+static void -+write_jump (int regn, void **target) -+{ -+ grub_uint32_t jirl=0x4c000000; -+ -+ *(grub_uint32_t *) *target = (jirl | (grub_uint32_t)(regn<<5)); -+ *target = ((grub_uint32_t *) *target) + 1; -+} -+ -+void -+grub_cpu_relocator_jumper (void *rels, grub_addr_t addr) -+{ -+ write_reg (1, addr, &rels); -+ write_jump (1, &rels); -+} -+ -+void -+grub_cpu_relocator_backward (void *ptr0, void *src, void *dest, -+ grub_size_t size) -+{ -+ void *ptr = ptr0; -+ write_reg (8, (grub_uint64_t) src, &ptr); -+ write_reg (9, (grub_uint64_t) dest, &ptr); -+ write_reg (10, (grub_uint64_t) size, &ptr); -+ grub_memcpy (ptr, &grub_relocator_backward_start, -+ RELOCATOR_SRC_SIZEOF (backward)); -+} -+ -+void -+grub_cpu_relocator_forward (void *ptr0, void *src, void *dest, -+ grub_size_t size) -+{ -+ void *ptr = ptr0; -+ write_reg (8, (grub_uint64_t) src, &ptr); -+ write_reg (9, (grub_uint64_t) dest, &ptr); -+ write_reg (10, (grub_uint64_t) size, &ptr); -+ grub_memcpy (ptr, &grub_relocator_forward_start, -+ RELOCATOR_SRC_SIZEOF (forward)); -+} -+ -+grub_err_t -+grub_relocator64_boot (struct grub_relocator *rel, -+ struct grub_relocator64_state state) -+{ -+ grub_relocator_chunk_t ch; -+ void *ptr; -+ grub_err_t err; -+ void *relst; -+ grub_size_t relsize; -+ grub_size_t stateset_size = 31 * REGW_SIZEOF + JUMP_SIZEOF; -+ unsigned i; -+ grub_addr_t vtarget; -+ -+ err = grub_relocator_alloc_chunk_align (rel, &ch, 0, -+ (0xffffffff - stateset_size) -+ + 1, stateset_size, -+ grub_relocator_align, -+ GRUB_RELOCATOR_PREFERENCE_NONE, 0); -+ if (err) -+ return err; -+ -+ ptr = get_virtual_current_address (ch); -+ for (i = 1; i < 32; i++) -+ write_reg (i, state.gpr[i], &ptr); -+ write_jump (state.jumpreg, &ptr); -+ -+ vtarget = (grub_addr_t) grub_map_memory (get_physical_target_address (ch), -+ stateset_size); -+ -+ err = grub_relocator_prepare_relocs (rel, vtarget, &relst, &relsize); -+ if (err) -+ return err; -+ -+ grub_arch_sync_caches ((void *) relst, relsize); -+ -+ asm volatile ( -+ "ibar 0 \n"); -+ -+ grub_uint64_t val; -+ __asm__ __volatile__( -+ "li.w %0, 0x4\n\t" -+ "csrxchg $r0, %0, 0x0\n\t" -+ : "=r"(val) -+ : -+ : -+ ); -+ -+ ((void (*) (void)) relst) (); -+ -+ /* Not reached. */ -+ return GRUB_ERR_NONE; -+} -diff --git a/grub-core/lib/loongarch64/relocator_asm.S b/grub-core/lib/loongarch64/relocator_asm.S -new file mode 100644 -index 0000000..cf1724d ---- /dev/null -+++ b/grub-core/lib/loongarch64/relocator_asm.S -@@ -0,0 +1,51 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+ -+ .p2align 4 /* force 16-byte alignment */ -+ -+VARIABLE (grub_relocator_forward_start) -+ -+copycont1: -+ ld.d $r11,$r8,0 -+ st.d $r11,$r9,0 -+ addi.d $r8, $r8, 8 -+ addi.d $r10, $r10, -8 -+ addi.d $r9, $r9, 8 -+ bne $r10, $r0, copycont1 -+ -+VARIABLE (grub_relocator_forward_end) -+ -+VARIABLE (grub_relocator_backward_start) -+ -+ add.d $r9, $r9, $r10 -+ add.d $r8, $r8, $r10 -+ /* Backward movsl is implicitly off-by-one. compensate that. */ -+ addi.d $r9, $r9, -8 -+ addi.d $r8, $r8, -8 -+copycont2: -+ ld.w $r11,$r8,0 -+ st.w $r11,$r9,0 -+ addi.d $r8, $r8, -8 -+ addi.d $r10, $r10, -8 -+ addi.d $r9, $r9, -8 -+ bne $r10, $r0, copycont2 -+ -+VARIABLE (grub_relocator_backward_end) -+ -diff --git a/grub-core/lib/loongarch64/setjmp.S b/grub-core/lib/loongarch64/setjmp.S -new file mode 100644 -index 0000000..47db814 ---- /dev/null -+++ b/grub-core/lib/loongarch64/setjmp.S -@@ -0,0 +1,74 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2003,2007,2009 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+ -+ .file "setjmp.S" -+ -+GRUB_MOD_LICENSE "GPLv3+" -+ -+ .text -+ -+/* -+ * int grub_setjmp (grub_jmp_buf env) -+ */ -+FUNCTION(grub_setjmp) -+ GRUB_ASM_REG_S $s0, $a0,0 -+ GRUB_ASM_REG_S $s1, $a0,8 -+ GRUB_ASM_REG_S $s2, $a0,16 -+ GRUB_ASM_REG_S $s3, $a0,24 -+ GRUB_ASM_REG_S $s4, $a0,32 -+ GRUB_ASM_REG_S $s5, $a0,40 -+ GRUB_ASM_REG_S $s6, $a0,48 -+ GRUB_ASM_REG_S $s7, $a0,56 -+ GRUB_ASM_REG_S $s8, $a0,64 -+ GRUB_ASM_REG_S $fp, $a0,72 -+ GRUB_ASM_REG_S $sp, $a0,80 -+ GRUB_ASM_REG_S $ra, $a0,88 -+ move $v0, $zero -+ move $v1, $zero -+ jr $ra -+ nop -+/* -+ * int grub_longjmp (grub_jmp_buf env, int val) -+ */ -+FUNCTION(grub_longjmp) -+ GRUB_ASM_REG_L $s0, $a0,0 -+ GRUB_ASM_REG_L $s1, $a0,8 -+ GRUB_ASM_REG_L $s2, $a0,16 -+ GRUB_ASM_REG_L $s3, $a0,24 -+ GRUB_ASM_REG_L $s4, $a0,32 -+ GRUB_ASM_REG_L $s5, $a0,40 -+ GRUB_ASM_REG_L $s6, $a0,48 -+ GRUB_ASM_REG_L $s7, $a0,56 -+ GRUB_ASM_REG_L $s8, $a0,64 -+ GRUB_ASM_REG_L $fp, $a0,72 -+ GRUB_ASM_REG_L $sp, $a0,80 -+ GRUB_ASM_REG_L $ra, $a0,88 -+ addi.w $v0, $zero, 1 -+ /* -+ * replace: movn $v0, $a1, $a1 -+ */ -+ bnez $a1, .ZW0 -+ addi.d $v0, $a1, 0 -+.ZW0: -+ addi.d $v1,$zero,0 -+ jr $ra -+ nop -diff --git a/grub-core/lib/loongson/reboot.c b/grub-core/lib/loongson/reboot.c -new file mode 100644 -index 0000000..107787a ---- /dev/null -+++ b/grub-core/lib/loongson/reboot.c -@@ -0,0 +1,33 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2011 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+void -+grub_la_reboot (void) -+{ -+ grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); -+ efi_call_4 (grub_efi_system_table->runtime_services->reset_system, -+ GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL); -+ for (;;) ; -+} -diff --git a/grub-core/lib/setjmp.S b/grub-core/lib/setjmp.S -index f6e4905..023dc90 100644 ---- a/grub-core/lib/setjmp.S -+++ b/grub-core/lib/setjmp.S -@@ -15,6 +15,8 @@ - #include "./arm/setjmp.S" - #elif defined(__aarch64__) - #include "./arm64/setjmp.S" -+#elif defined(__loongarch64) -+#include "./loongarch64/setjmp.S" - #else - #error "Unknown target cpu type" - #endif -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index b72e6bd..f4066b5 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -343,6 +343,8 @@ static const grub_uint16_t machine_type __attribute__((__unused__)) = - GRUB_PE32_MACHINE_I386; - #elif defined(__ia64__) - GRUB_PE32_MACHINE_IA64; -+#elif defined(__loongarch64) -+ GRUB_PE32_MACHINE_LOONGARCH64; - #else - #error this architecture is not supported by grub2 - #endif -diff --git a/grub-core/loader/loongarch64/linux.c b/grub-core/loader/loongarch64/linux.c -new file mode 100644 -index 0000000..7594ca2 ---- /dev/null -+++ b/grub-core/loader/loongarch64/linux.c -@@ -0,0 +1,690 @@ -+/* linux.c - boot Linux */ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2003,2004,2005,2007,2009,2010,2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+#pragma GCC diagnostic ignored "-Wcast-align" -+ -+typedef unsigned long size_t; -+ -+#define FDT_ADDR_CELLS_STRING "#address-cells" -+#define FDT_SIZE_CELLS_STRING "#size-cells" -+#define FDT_ADDR_SIZE_EXTRA ((2 * grub_fdt_prop_entry_size (sizeof(grub_uint32_t))) + \ -+ sizeof (FDT_ADDR_CELLS_STRING) + \ -+ sizeof (FDT_SIZE_CELLS_STRING)) -+ -+static grub_dl_t my_mod; -+static int loaded; -+static int initrd_loaded = 0; -+static grub_size_t linux_size; -+ -+static struct grub_relocator *relocator; -+static grub_addr_t target_addr, entry_addr; -+static int linux_argc; -+static grub_uint8_t *linux_args_addr; -+static grub_off_t rd_addr_arg_off, rd_size_arg_off, initrd_addr_arg_off; -+ -+static void *fdt; -+static int is_fdt_boot; -+static grub_addr_t initrd_start, initrd_end; -+static char *fdt_linux_args; -+ -+static grub_err_t -+allocate_fdt_and_exit_boot (void) -+{ -+ int node, retval; -+ grub_err_t err; -+ unsigned int size; -+ grub_efi_uintn_t mmap_size; -+ grub_efi_uintn_t desc_size; -+ grub_efi_uint32_t desc_version; -+ grub_efi_memory_descriptor_t *mmap_buf; -+ -+ size = GRUB_FDT_EMPTY_TREE_SZ + FDT_ADDR_SIZE_EXTRA + GRUB_EFI_LINUX_FDT_EXTRA_SPACE; -+ -+ fdt = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (size)); -+ if (!fdt) -+ return GRUB_ERR_OUT_OF_MEMORY; -+ -+ grub_fdt_create_empty_tree (fdt, size); -+ grub_fdt_set_prop32 (fdt, 0, FDT_ADDR_CELLS_STRING, 2); -+ grub_fdt_set_prop32 (fdt, 0, FDT_SIZE_CELLS_STRING, 2); -+ -+ node = grub_fdt_find_subnode (fdt, 0, "chosen"); -+ if (node < 0) -+ node = grub_fdt_add_subnode (fdt, 0, "chosen"); -+ if (node < 1) -+ goto failure; -+ -+ grub_dprintf ("loongson", "command_line %s, len %ld\n", -+ fdt_linux_args, grub_strlen(fdt_linux_args) + 1); -+ if ((fdt_linux_args != NULL) && (grub_strlen(fdt_linux_args) > 0)) { -+ retval = grub_fdt_set_prop (fdt, node, "bootargs", fdt_linux_args, -+ grub_strlen(fdt_linux_args) + 1); -+ if (retval) -+ goto failure; -+ } -+ -+ /* Set initrd info */ -+ if (initrd_start && initrd_end > initrd_start) -+ { -+ grub_dprintf ("linux", "Initrd @ %p-%p\n", -+ (void *) initrd_start, (void *) initrd_end); -+ -+ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start", -+ initrd_start); -+ if (retval) -+ goto failure; -+ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end", -+ initrd_end); -+ if (retval) -+ goto failure; -+ } -+ -+ node = grub_fdt_find_subnode (fdt, 0, "chosen"); -+ retval = grub_fdt_set_prop64 (fdt, node, "linux,uefi-system-table", -+ (grub_uint64_t)grub_efi_system_table); -+ if (retval) -+ goto failure; -+ -+ mmap_size = grub_efi_find_mmap_size (); -+ if (! mmap_size) -+ return grub_errno; -+ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); -+ if (! mmap_buf) -+ return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); -+ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, -+ &desc_size, &desc_version); -+ if (err) -+ return err; -+ -+ if (!mmap_buf || !mmap_size || !desc_size) -+ return GRUB_ERR_BAD_ARGUMENT; -+ -+ retval = grub_fdt_set_prop64 (fdt, node, "linux,uefi-mmap-start", -+ (grub_uint64_t)mmap_buf); -+ if (retval) -+ goto failure; -+ -+ retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-size", -+ mmap_size); -+ if (retval) -+ goto failure; -+ -+ retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-desc-size", -+ desc_size); -+ if (retval) -+ goto failure; -+ -+ retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-desc-ver", -+ desc_version); -+ if (retval) -+ goto failure; -+ -+ return GRUB_ERR_NONE; -+ -+failure: -+ if (!fdt) { -+ return GRUB_ERR_BAD_OS; -+ } -+ grub_efi_free_pages ((grub_addr_t) fdt, -+ GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt))); -+ fdt = NULL; -+ return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); -+} -+ -+static grub_err_t -+allocate_boot_params_and_exit_boot (void) -+{ -+ grub_efi_uintn_t mmap_size; -+ grub_efi_uintn_t desc_size; -+ grub_efi_uint32_t desc_version; -+ grub_efi_memory_descriptor_t *mmap_buf; -+ grub_efi_memory_descriptor_t * lsdesc = NULL; -+ grub_err_t err; -+ struct boot_params_interface * boot_params; -+ mem_map_v1 * mem_map_v1_table = NULL; -+ unsigned long bpi_version = 0; -+ grub_int8_t checksum = 0; -+ grub_uint32_t tmp_index = 0; -+ grub_uint32_t free_index = 0; -+ grub_uint32_t reserve_index = 0; -+ grub_uint32_t acpi_table_index = 0; -+ grub_uint32_t acpi_nvs_index = 0; -+ -+ struct memmap_v1 reserve_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; -+ struct memmap_v1 free_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; -+ struct memmap_v1 acpi_table_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; -+ struct memmap_v1 acpi_nvs_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; -+ -+ grub_memset(reserve_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); -+ grub_memset(free_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); -+ grub_memset(acpi_table_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); -+ grub_memset(acpi_nvs_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); -+ -+ boot_params = (struct boot_params_interface *)grub_efi_loongson_get_boot_params(); -+ -+ ext_list * listpointer = NULL; -+ /* Check extlist headers */ -+ listpointer = boot_params->extlist; -+ for( ;listpointer != NULL; listpointer = listpointer->next) -+ { -+ char *pl= (char *)&(listpointer->signature); -+ if(grub_strncmp(pl, "MEM", 3) == 0) -+ { -+ mem_map_v1_table = (mem_map_v1 *)listpointer; -+ break; -+ } -+ } -+ -+ mmap_size = grub_efi_find_mmap_size (); -+ if (! mmap_size) -+ return grub_errno; -+ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); -+ if (! mmap_buf) -+ return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); -+ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, -+ &desc_size, &desc_version); -+ if (err) -+ return err; -+ -+ if (!mmap_buf || !mmap_size || !desc_size) -+ return GRUB_ERR_BAD_ARGUMENT; -+ -+ char *p = (char *)&(boot_params->signature); -+ bpi_version = grub_efi_get_bpi_version(p); -+ grub_dprintf("loongson", "get bpi version:%ld\n", bpi_version); -+ -+ if (bpi_version <= GRUB_EFI_BPI_VER_V2) -+ { -+ /* -+ According to UEFI SPEC,mmap_buf is the accurate Memory Map array \ -+ now we can fill platform specific memory structure. -+ */ -+ for(lsdesc = mmap_buf; lsdesc < (grub_efi_memory_descriptor_t *)((char *)mmap_buf + mmap_size); -+ lsdesc = (grub_efi_memory_descriptor_t *)((char *)lsdesc + desc_size)) -+ { -+ grub_dprintf("loongson", "type:%d, phy_start:0x%lx, phy_end:0x%lx\n", lsdesc->type, -+ lsdesc->physical_start, lsdesc->physical_start + lsdesc->num_pages * GRUB_EFI_PAGE_SIZE); -+ -+ /* System RAM */ -+ if ((lsdesc->type != GRUB_EFI_ACPI_RECLAIM_MEMORY) && \ -+ (lsdesc->type != GRUB_EFI_ACPI_MEMORY_NVS) && \ -+ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_DATA) && \ -+ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_CODE) && \ -+ (lsdesc->type != GRUB_EFI_RESERVED_MEMORY_TYPE) && \ -+ (lsdesc->type != GRUB_EFI_PAL_CODE)) -+ { -+ free_mem_v1[free_index].memtype = GRUB_EFI_LOONGSON_SYSTEM_RAM; -+ free_mem_v1[free_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; -+ free_mem_v1[free_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; -+ free_index++; -+ -+ /*ACPI*/ -+ } else if ((lsdesc->type == GRUB_EFI_ACPI_RECLAIM_MEMORY)){ -+ acpi_table_mem_v1[acpi_table_index].memtype = GRUB_EFI_LOONGSON_ACPI_TABLE; -+ acpi_table_mem_v1[acpi_table_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; -+ acpi_table_mem_v1[acpi_table_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; -+ acpi_table_index++; -+ } else if ((lsdesc->type == GRUB_EFI_ACPI_MEMORY_NVS)){ -+ acpi_nvs_mem_v1[acpi_nvs_index].memtype = GRUB_EFI_LOONGSON_ACPI_NVS; -+ acpi_nvs_mem_v1[acpi_nvs_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; -+ acpi_nvs_mem_v1[acpi_nvs_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; -+ acpi_nvs_index++; -+ -+ /* Reserve */ -+ } else { -+ reserve_mem_v1[reserve_index].memtype = GRUB_EFI_LOONGSON_MEMORY_RESERVED; -+ reserve_mem_v1[reserve_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; -+ reserve_mem_v1[reserve_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; -+ reserve_index++; -+ } -+ } -+ -+ tmp_index = mem_map_v1_table->mapcount; -+ /*System RAM Sort*/ -+ tmp_index = grub_efi_loongson_memmap_v1_sort(free_mem_v1, free_index, mem_map_v1_table, -+ tmp_index, GRUB_EFI_LOONGSON_SYSTEM_RAM); -+ /*ACPI Sort*/ -+ tmp_index = grub_efi_loongson_memmap_v1_sort(acpi_table_mem_v1, acpi_table_index, -+ mem_map_v1_table, tmp_index, GRUB_EFI_LOONGSON_ACPI_TABLE); -+ tmp_index = grub_efi_loongson_memmap_v1_sort(acpi_nvs_mem_v1, acpi_nvs_index, -+ mem_map_v1_table, tmp_index, GRUB_EFI_LOONGSON_ACPI_NVS); -+ /*Reserve Sort*/ -+ { -+ grub_uint64_t loongarch_addr; -+ asm volatile ("csrrd %0, 0x181" : "=r" (loongarch_addr)); -+ if ((loongarch_addr & 0xff00000000000000) == 0x9000000000000000) -+ tmp_index = grub_efi_loongson_memmap_v1_sort(reserve_mem_v1, reserve_index, -+ mem_map_v1_table, tmp_index, -+ GRUB_EFI_LOONGSON_MEMORY_RESERVED); -+ else -+ tmp_index = grub_efi_loongson_memmap_v1_sort(reserve_mem_v1, reserve_index, -+ mem_map_v1_table, tmp_index, -+ GRUB_EFI_LOONGSON_MEMORY_RESERVED + 1); -+ } -+ mem_map_v1_table->mapcount = tmp_index; -+ mem_map_v1_table->header.checksum = 0; -+ -+ checksum = grub_efi_loongson_grub_calculatechecksum8((grub_uint8_t *)mem_map_v1_table, -+ mem_map_v1_table->header.length); -+ mem_map_v1_table->header.checksum = checksum; -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_linux_boot (void) -+{ -+ struct grub_relocator64_state state; -+ -+ grub_memset (&state, 0, sizeof (state)); -+ -+ /* Boot the kernel. */ -+ state.gpr[1] = entry_addr; -+ grub_dprintf("loongson", "entry_addr is 0x%lx\n", state.gpr[1]); -+ -+ if (is_fdt_boot == 1) -+ { -+ if (allocate_fdt_and_exit_boot () != GRUB_ERR_NONE) -+ return grub_errno; -+ -+ state.gpr[4] = 1 << FLAGS_EFI_SUPPORT_BIT; -+ state.gpr[5] = (grub_uint64_t)fdt; -+ state.gpr[6] = 0; -+ } else { -+ state.gpr[4] = linux_argc; -+ state.gpr[5] = (grub_addr_t) linux_args_addr; -+ state.gpr[6] = (grub_uint64_t)grub_efi_loongson_get_boot_params(); -+ -+ if (allocate_boot_params_and_exit_boot () != GRUB_ERR_NONE) -+ return grub_errno; -+ } -+ grub_dprintf("loongson", "gpr[4]:%ld, gpr[5]:0x%lx, gpr[6]:0x%lx\n", -+ state.gpr[4], state.gpr[5], state.gpr[6]); -+ -+ state.jumpreg = 1; -+ grub_relocator64_boot (relocator, state); -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_linux_unload (void) -+{ -+ grub_relocator_unload (relocator); -+ grub_dl_unref (my_mod); -+ loaded = 0; -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_linux_load64 (grub_elf_t elf, const char *filename) -+{ -+ Elf64_Addr base; -+ grub_err_t err; -+ grub_uint8_t *playground; -+ grub_uint64_t addr; -+ int flag; -+ -+ /* Linux's entry point incorrectly contains a virtual address. */ -+ entry_addr = elf->ehdr.ehdr64.e_entry; -+ grub_dprintf("loongson", "entry address = 0x%lx\n", entry_addr); -+ -+ linux_size = grub_elf64_size (elf, &base, 0); -+ grub_dprintf("loongson", "base = 0x%lx\n", base); -+ -+ if (linux_size == 0) -+ return grub_errno; -+ target_addr = base; -+ linux_size = ALIGN_UP (base + linux_size - base, 8); -+ -+ asm volatile ("csrrd %0, 0x181" : "=r" (addr)); -+ if (addr & 0x1) { -+ flag = GRUB_ELF_LOAD_FLAGS_NONE; -+ } else { -+ flag = GRUB_ELF_LOAD_FLAGS_30BITS; -+ base &= ~ELF64_LOADMASK; -+ entry_addr &= ~ELF64_LOADMASK; -+ } -+ -+ relocator = grub_relocator_new (); -+ if (!relocator) -+ return grub_errno; -+ -+ { -+ grub_relocator_chunk_t ch; -+ err = grub_relocator_alloc_chunk_addr (relocator, &ch, -+ grub_vtop ((void *) target_addr), -+ linux_size); -+ if (err) -+ return err; -+ playground = get_virtual_current_address (ch); -+ } -+ -+ /* Now load the segments into the area we claimed. */ -+ return grub_elf64_load (elf, filename, playground - base, flag, 0, 0); -+} -+ -+static grub_err_t -+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), -+ int argc, char *argv[]) -+{ -+ grub_elf_t elf = 0; -+ grub_err_t err; -+ int args_size = 0; -+ -+ grub_dl_ref (my_mod); -+ -+ if (argc == 0) -+ { -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -+ } -+ -+ elf = grub_elf_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL); -+ if (! elf) -+ return grub_errno; -+ -+ if (elf->ehdr.ehdr64.e_type != ET_EXEC) -+ { -+ grub_elf_close (elf); -+ return grub_error (GRUB_ERR_UNKNOWN_OS, -+ N_("this ELF file is not of the right type")); -+ } -+ -+ /* Release the previously used memory. */ -+ grub_loader_unset (); -+ loaded = 0; -+ -+ if (grub_elf_is_elf64 (elf)) -+ err = grub_linux_load64 (elf, argv[0]); -+ else -+ err = grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic")); -+ -+ grub_elf_close (elf); -+ -+ if (err) -+ return err; -+ -+ if (grub_efi_loongson_get_boot_params() == NULL) { -+ grub_size_t cmdline_size; -+ -+ is_fdt_boot = 1; -+ cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); -+ fdt_linux_args = grub_malloc (cmdline_size); -+ if (!fdt_linux_args) -+ { -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); -+ goto fail; -+ } -+ grub_memcpy (fdt_linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); -+ err = grub_create_loader_cmdline (argc, argv, -+ fdt_linux_args + sizeof (LINUX_IMAGE) - 1, -+ cmdline_size, -+ GRUB_VERIFY_KERNEL_CMDLINE); -+ if (err) -+ goto fail; -+ grub_dprintf("loongson", "fdt linux args:%s\n", -+ fdt_linux_args + sizeof (LINUX_IMAGE) - 1); -+ -+ } else { -+ int i; -+ grub_uint64_t *linux_argv; -+ char *linux_args; -+ -+ is_fdt_boot = 0; -+ /* For arguments. */ -+ linux_argc = argc; -+ /* Main arguments. */ -+ args_size = (linux_argc) * sizeof (grub_uint64_t); -+ /* Initrd address/size and initrd */ -+ args_size += 3 * sizeof (grub_uint64_t); -+ /* NULL terminator. */ -+ args_size += sizeof (grub_uint64_t); -+ /* First argument is always "a0". */ -+ args_size += ALIGN_UP (sizeof ("a0"), 4); -+ /* Normal arguments. */ -+ for (i = 1; i < argc; i++) -+ args_size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); -+ -+ /* rd arguments. */ -+ args_size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); -+ args_size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); -+ args_size += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); -+ -+ args_size = ALIGN_UP (args_size, 8); -+ -+ linux_args_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (args_size)); -+ grub_dprintf ("linux", "linux args numpages: %lld\n", -+ (long long) GRUB_EFI_BYTES_TO_PAGES (args_size)); -+ if (!linux_args_addr) -+ { -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); -+ goto fail; -+ } -+ linux_argv = (grub_uint64_t *) linux_args_addr; -+ linux_args = (char *) (linux_argv + (linux_argc + 1 + 3)); -+ -+ grub_memcpy (linux_args, "a0", sizeof ("a0")); -+ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; -+ linux_argv++; -+ linux_args += ALIGN_UP (sizeof ("a0"), 4); -+ -+ for (i = 1; i < argc; i++) -+ { -+ grub_memcpy (linux_args, argv[i], grub_strlen (argv[i]) + 1); -+ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; -+ linux_argv++; -+ linux_args += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); -+ } -+ -+ /* Reserve space for rd arguments. */ -+ rd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; -+ linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); -+ *linux_argv = 0; -+ linux_argv++; -+ -+ rd_size_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; -+ linux_args += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); -+ *linux_argv = 0; -+ linux_argv++; -+ -+ /* Reserve space for initrd arguments. */ -+ initrd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; -+ linux_args += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); -+ *linux_argv = 0; -+ linux_argv++; -+ -+ *linux_argv = 0; -+ } -+ -+ if (grub_errno == GRUB_ERR_NONE) -+ { -+ grub_loader_set (grub_linux_boot, grub_linux_unload, 0); -+ loaded = 1; -+ } -+ -+ initrd_loaded = 0; -+ -+fail: -+ if (grub_errno != GRUB_ERR_NONE) -+ { -+ grub_dl_unref (my_mod); -+ loaded = 0; -+ } -+ -+ if (fdt_linux_args && !loaded) -+ grub_free (fdt_linux_args); -+ -+ if (linux_args_addr && !loaded) -+ grub_efi_free_pages ((grub_addr_t) linux_args_addr, -+ GRUB_EFI_BYTES_TO_PAGES (args_size)); -+ -+ return grub_errno; -+} -+ -+#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024) -+ -+/* -+ * This function returns a pointer to a legally allocated initrd buffer, -+ * or NULL if unsuccessful -+ */ -+static void * -+allocate_initrd_mem (int initrd_pages) -+{ -+ grub_addr_t max_addr; -+ -+ if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE) -+ return NULL; -+ -+ max_addr += INITRD_MAX_ADDRESS_OFFSET - 1; -+ -+ return grub_efi_allocate_pages_real (max_addr, initrd_pages, -+ GRUB_EFI_ALLOCATE_MAX_ADDRESS, -+ GRUB_EFI_LOADER_DATA); -+} -+ -+ -+static grub_err_t -+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), -+ int argc, char *argv[]) -+{ -+ grub_size_t initrd_size, initrd_pages; -+ grub_err_t err; -+ void *initrd_mem = NULL; -+ struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 }; -+ -+ if (argc == 0) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -+ -+ if (!loaded) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); -+ -+ if (initrd_loaded) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "only one initrd command can be issued."); -+ -+ if (grub_initrd_init (argc, argv, &initrd_ctx)) -+ goto fail; -+ -+ initrd_size = grub_get_initrd_size (&initrd_ctx); -+ -+ if (is_fdt_boot == 1) //fdt -+ { -+ initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size)); -+ initrd_mem = allocate_initrd_mem (initrd_pages); -+ if (!initrd_mem) -+ { -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); -+ goto fail; -+ } -+ } else { -+ grub_relocator_chunk_t ch; -+ err = grub_relocator_alloc_chunk_align (relocator, &ch, -+ 0, (0xffffffff - initrd_size) + 1, -+ initrd_size, 0x10000, -+ GRUB_RELOCATOR_PREFERENCE_HIGH, 0); -+ -+ if (err) -+ return err; -+ initrd_mem = get_virtual_current_address (ch); -+ } -+ -+ if (grub_initrd_load (&initrd_ctx, argv, initrd_mem)) -+ goto fail; -+ -+ initrd_start = (grub_addr_t) initrd_mem; -+ initrd_end = initrd_start + initrd_size; -+ grub_dprintf ("linux", "[addr=%p, size=0x%lx]\n", -+ (void *) initrd_start, initrd_size); -+ -+ if (is_fdt_boot == 0) //bpi -+ { -+ grub_snprintf ((char *) linux_args_addr + rd_addr_arg_off, -+ sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), -+ "rd_start=0x%lx", -+ (grub_uint64_t) initrd_mem); -+ ((grub_uint64_t *) linux_args_addr)[linux_argc] -+ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_addr_arg_off); -+ linux_argc++; -+ -+ grub_snprintf ((char *) linux_args_addr + rd_size_arg_off, -+ sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%lx", -+ (grub_uint64_t) initrd_size); -+ ((grub_uint64_t *) linux_args_addr)[linux_argc] -+ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_size_arg_off); -+ linux_argc++; -+ -+ grub_snprintf ((char *) linux_args_addr + initrd_addr_arg_off, -+ sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), -+ "initrd=0x%lx,0x%lx", -+ ((grub_uint64_t) initrd_mem & GRUB_EFI_MAX_PHY_ADDRESS), -+ (grub_uint64_t) initrd_size); -+ ((grub_uint64_t *) linux_args_addr)[linux_argc] -+ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + initrd_addr_arg_off); -+ linux_argc++; -+ } -+ -+ initrd_loaded = 1; -+ -+ fail: -+ grub_initrd_close (&initrd_ctx); -+ if (is_fdt_boot == 1) -+ if (initrd_mem && !initrd_start) -+ grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages); -+ -+ return grub_errno; -+} -+ -+static grub_command_t cmd_linux, cmd_initrd; -+ -+GRUB_MOD_INIT(linux) -+{ -+ cmd_linux = grub_register_command ("linux", grub_cmd_linux, -+ 0, N_("Load Linux.")); -+ cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, -+ 0, N_("Load initrd.")); -+ my_mod = mod; -+} -+ -+GRUB_MOD_FINI(linux) -+{ -+ grub_unregister_command (cmd_linux); -+ grub_unregister_command (cmd_initrd); -+} -diff --git a/include/grub/dl.h b/include/grub/dl.h -index 6f46b7e..50e04ac 100644 ---- a/include/grub/dl.h -+++ b/include/grub/dl.h -@@ -360,7 +360,7 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, - #define GRUB_ARCH_DL_GOT_ALIGN 4 - #endif - --#if defined (__aarch64__) || defined (__sparc__) -+#if defined (__aarch64__) || defined (__sparc__) || defined (__loongarch64) - #define GRUB_ARCH_DL_TRAMP_ALIGN 8 - #define GRUB_ARCH_DL_GOT_ALIGN 8 - #endif -diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h -index 510a403..a57187f 100644 ---- a/include/grub/efi/api.h -+++ b/include/grub/efi/api.h -@@ -2117,7 +2117,8 @@ struct grub_efi_memory_attribute_protocol - typedef struct grub_efi_memory_attribute_protocol grub_efi_memory_attribute_protocol_t; - - #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ -- || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) -+ || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \ -+ || defined (__loongarch64) - - #define efi_call_0(func) func() - #define efi_call_1(func, a) func(a) -diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h -index 8ca8c38..fe1df9d 100644 ---- a/include/grub/efi/efi.h -+++ b/include/grub/efi/efi.h -@@ -138,7 +138,7 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, - extern grub_addr_t EXPORT_VAR(grub_stack_addr); - extern grub_size_t EXPORT_VAR(grub_stack_size); - --#if defined(__arm__) || defined(__aarch64__) -+#if defined(__arm__) || defined(__aarch64__) || defined (__loongarch__) - void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void); - grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *); - #include -diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h -index 45c9f8b..f612a55 100644 ---- a/include/grub/efi/pe32.h -+++ b/include/grub/efi/pe32.h -@@ -89,6 +89,7 @@ struct grub_pe32_coff_header - }; - - #define GRUB_PE32_MACHINE_I386 0x14c -+#define GRUB_PE32_MACHINE_LOONGARCH64 0x6264 - #define GRUB_PE32_MACHINE_IA64 0x200 - #define GRUB_PE32_MACHINE_X86_64 0x8664 - #define GRUB_PE32_MACHINE_ARMTHUMB_MIXED 0x01c2 -@@ -355,6 +356,7 @@ struct grub_pe32_fixup_block - #define GRUB_PE32_REL_BASED_IA64_IMM64 9 - #define GRUB_PE32_REL_BASED_DIR64 10 - #define GRUB_PE32_REL_BASED_HIGH3ADJ 11 -+#define GRUB_PE32_REL_BASED_LOONGARCH64 8 - - struct grub_pe32_symbol - { -diff --git a/include/grub/elf.h b/include/grub/elf.h -index c8492f9..2c0b163 100644 ---- a/include/grub/elf.h -+++ b/include/grub/elf.h -@@ -247,6 +247,7 @@ typedef struct - #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ - #define EM_NUM 95 - #define EM_AARCH64 183 /* ARM 64-bit architecture */ -+#define EM_LOONGARCH64 258 /* LoongArch64 architecture */ - - /* If it is necessary to assign new unofficial EM_* values, please - pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the -@@ -1448,6 +1449,60 @@ typedef struct - #define OHWA0_R4KEOP_CHECKED 0x00000001 - #define OHWA1_R4KEOP_CLEAN 0x00000002 - -+/* LOONGARCH64 relocs. */ -+#define R_LARCH_NONE 0 -+#define R_LARCH_32 1 -+#define R_LARCH_64 2 -+#define R_LARCH_RELATIVE 3 -+#define R_LARCH_COPY 4 -+#define R_LARCH_JUMP_SLOT 5 -+#define R_LARCH_TLS_DTPMOD32 6 -+#define R_LARCH_TLS_DTPMOD64 7 -+#define R_LARCH_TLS_DTPREL32 8 -+#define R_LARCH_TLS_DTPREL64 9 -+#define R_LARCH_TLS_TPREL32 10 -+#define R_LARCH_TLS_TPREL64 11 -+#define R_LARCH_IRELATIVE 12 -+#define R_LARCH_MARK_LA 20 -+#define R_LARCH_MARK_PCREL 21 -+#define R_LARCH_SOP_PUSH_PCREL 22 -+#define R_LARCH_SOP_PUSH_ABSOLUTE 23 -+#define R_LARCH_SOP_PUSH_DUP 24 -+#define R_LARCH_SOP_PUSH_GPREL 25 -+#define R_LARCH_SOP_PUSH_TLS_TPREL 26 -+#define R_LARCH_SOP_PUSH_TLS_GOT 27 -+#define R_LARCH_SOP_PUSH_TLS_GD 28 -+#define R_LARCH_SOP_PUSH_PLT_PCREL 29 -+#define R_LARCH_SOP_ASSERT 30 -+#define R_LARCH_SOP_NOT 31 -+#define R_LARCH_SOP_SUB 32 -+#define R_LARCH_SOP_SL 33 -+#define R_LARCH_SOP_SR 34 -+#define R_LARCH_SOP_ADD 35 -+#define R_LARCH_SOP_AND 36 -+#define R_LARCH_SOP_IF_ELSE 37 -+#define R_LARCH_SOP_POP_32_S_10_5 38 -+#define R_LARCH_SOP_POP_32_U_10_12 39 -+#define R_LARCH_SOP_POP_32_S_10_12 40 -+#define R_LARCH_SOP_POP_32_S_10_16 41 -+#define R_LARCH_SOP_POP_32_S_10_16_S2 42 -+#define R_LARCH_SOP_POP_32_S_5_20 43 -+#define R_LARCH_SOP_POP_32_S_0_5_10_16_S2 44 -+#define R_LARCH_SOP_POP_32_S_0_10_10_16_S2 45 -+#define R_LARCH_SOP_POP_32_U 46 -+#define R_LARCH_ADD8 47 -+#define R_LARCH_ADD16 48 -+#define R_LARCH_ADD24 49 -+#define R_LARCH_ADD32 50 -+#define R_LARCH_ADD64 51 -+#define R_LARCH_SUB8 52 -+#define R_LARCH_SUB16 53 -+#define R_LARCH_SUB24 54 -+#define R_LARCH_SUB32 55 -+#define R_LARCH_SUB64 56 -+#define R_LARCH_GNU_VTINHERIT 57 -+#define R_LARCH_GNU_VTENTRY 58 -+ - /* MIPS relocs. */ - - #define R_MIPS_NONE 0 /* No reloc */ -diff --git a/include/grub/fdt.h b/include/grub/fdt.h -index 6ee57e1..a0710ab 100644 ---- a/include/grub/fdt.h -+++ b/include/grub/fdt.h -@@ -19,11 +19,14 @@ - #ifndef GRUB_FDT_HEADER - #define GRUB_FDT_HEADER 1 - --#if defined(__arm__) || defined(__aarch64__) -+#if defined(__arm__) || defined(__aarch64__) || defined (__loongarch__) - - #include - #include - -+/* Space required when preparing the /chosen node after boot has been called. */ -+#define GRUB_EFI_LINUX_FDT_EXTRA_SPACE 0x400 -+ - #define FDT_MAGIC 0xD00DFEED - - typedef struct { -diff --git a/include/grub/loongarch64/asm.h b/include/grub/loongarch64/asm.h -new file mode 100644 -index 0000000..c3e77e9 ---- /dev/null -+++ b/include/grub/loongarch64/asm.h -@@ -0,0 +1,10 @@ -+#ifndef GRUB_LOONGARCH64_ASM_HEADER -+#define GRUB_LOONGARCH64_ASM_HEADER 1 -+ -+#define GRUB_ASM_T4 $a4 -+#define GRUB_ASM_T5 $a5 -+#define GRUB_ASM_SZREG 8 -+#define GRUB_ASM_REG_S st.d -+#define GRUB_ASM_REG_L ld.d -+ -+#endif -diff --git a/include/grub/loongarch64/efi/loongson.h b/include/grub/loongarch64/efi/loongson.h -new file mode 100644 -index 0000000..7a9ccb4 ---- /dev/null -+++ b/include/grub/loongarch64/efi/loongson.h -@@ -0,0 +1,113 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_EFI_LOONGSON_HEADER -+#define GRUB_EFI_LOONGSON_HEADER 1 -+ -+#include -+ -+#include -+ -+#define GRUB_EFI_LOONGSON_BPI_TABLE_GUID \ -+ { 0x4660f721, 0x2ec5, 0x416a, \ -+ { 0x89, 0x9a, 0x43, 0x18, 0x02, 0x50, 0xa0, 0xc9 } \ -+ } -+ -+#define GRUB_EFI_MAX_PHY_ADDRESS 0xffffffffffffULL -+#define ELF32_LOADMASK (0xf0000000UL) -+#define ELF64_LOADMASK (0xf000000000000000ULL) -+#define FLAGS_EFI_SUPPORT_BIT 0 -+#define GRUB_EFI_LOONGSON_MMAP_MAX 128 -+ -+typedef enum -+ { -+ GRUB_EFI_LOONGSON_SYSTEM_RAM = 1, -+ GRUB_EFI_LOONGSON_MEMORY_RESERVED, -+ GRUB_EFI_LOONGSON_ACPI_TABLE, -+ GRUB_EFI_LOONGSON_ACPI_NVS, -+ GRUB_EFI_LOONGSON_MAX_MEMORY_TYPE -+ } -+grub_efi_loongson_memory_type; -+ -+typedef enum -+ { -+ GRUB_EFI_BPI_VER_NONE = 0, -+ GRUB_EFI_BPI_VER_V1 = 1000, -+ GRUB_EFI_BPI_VER_V2 = 1001, -+ } -+ grub_efi_loongson_bpi_version; -+ -+grub_uint8_t -+EXPORT_FUNC(grub_efi_loongson_calculatesum8) (const grub_uint8_t *Buffer, -+ grub_efi_uintn_t Length); -+ -+grub_uint8_t -+EXPORT_FUNC(grub_efi_loongson_grub_calculatechecksum8) (const grub_uint8_t *Buffer, -+ grub_efi_uintn_t Length); -+ -+unsigned long -+EXPORT_FUNC(grub_efi_get_bpi_version) (const char *str); -+ -+void * -+EXPORT_FUNC(grub_efi_loongson_get_boot_params) (void); -+ -+typedef struct _extention_list_hdr { -+ grub_uint64_t signature; -+ grub_uint32_t length; -+ grub_uint8_t revision; -+ grub_uint8_t checksum; -+ union { -+ struct _extention_list_hdr *next; -+ grub_uint64_t next_offset; -+ }; -+}GRUB_PACKED -+ext_list; -+ -+typedef struct boot_params_interface { -+ grub_uint64_t signature; //{'B', 'P', 'I', 'x', 'x', 'x', 'x', 'x'} -+ grub_efi_system_table_t *systemtable; -+ union { -+ ext_list *extlist; -+ grub_uint64_t extlist_offset; -+ }; -+ grub_uint64_t flags; -+}GRUB_PACKED -+boot_params_interface; -+ -+typedef struct { -+ ext_list header; //{MEM} -+ grub_uint8_t mapcount; -+ struct GRUB_PACKED memmap_v1 { -+ grub_uint32_t memtype; -+ grub_uint64_t memstart; -+ grub_uint64_t memsize; -+ } map[GRUB_EFI_LOONGSON_MMAP_MAX]; -+}GRUB_PACKED -+mem_map_v1; -+ -+typedef struct { -+ ext_list header; //{VBIOS} -+ grub_uint64_t vbiosaddr; -+}GRUB_PACKED -+vbios; -+ -+grub_uint32_t -+EXPORT_FUNC (grub_efi_loongson_memmap_v1_sort) (struct memmap_v1 array[], -+ grub_uint32_t length, mem_map_v1 * mem, -+ grub_uint32_t index, grub_uint32_t memtype); -+#endif /* ! GRUB_EFI_LOONGSON_HEADER */ -diff --git a/include/grub/loongarch64/efi/memory.h b/include/grub/loongarch64/efi/memory.h -new file mode 100644 -index 0000000..73641a1 ---- /dev/null -+++ b/include/grub/loongarch64/efi/memory.h -@@ -0,0 +1,12 @@ -+#ifndef GRUB_MEMORY_CPU_HEADER -+#include -+ -+static inline grub_uint64_t -+grub_efi_max_usable_address(void) -+{ -+ grub_uint64_t addr; -+ asm volatile ("csrrd %0, 0x181" : "=r" (addr)); -+ return addr |= 0xffffffffffUL; -+} -+ -+#endif /* ! GRUB_MEMORY_CPU_HEADER */ -diff --git a/include/grub/loongarch64/efi/time.h b/include/grub/loongarch64/efi/time.h -new file mode 100644 -index 0000000..e69de29 -diff --git a/include/grub/loongarch64/io.h b/include/grub/loongarch64/io.h -new file mode 100644 -index 0000000..5f34103 ---- /dev/null -+++ b/include/grub/loongarch64/io.h -@@ -0,0 +1,62 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2009,2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_IO_H -+#define GRUB_IO_H 1 -+ -+#include -+ -+typedef grub_addr_t grub_port_t; -+ -+static __inline unsigned char -+grub_inb (grub_port_t port) -+{ -+ return *(volatile grub_uint8_t *) port; -+} -+ -+static __inline unsigned short int -+grub_inw (grub_port_t port) -+{ -+ return *(volatile grub_uint16_t *) port; -+} -+ -+static __inline unsigned int -+grub_inl (grub_port_t port) -+{ -+ return *(volatile grub_uint32_t *) port; -+} -+ -+static __inline void -+grub_outb (unsigned char value, grub_port_t port) -+{ -+ *(volatile grub_uint8_t *) port = value; -+} -+ -+static __inline void -+grub_outw (unsigned short int value, grub_port_t port) -+{ -+ *(volatile grub_uint16_t *) port = value; -+} -+ -+static __inline void -+grub_outl (unsigned int value, grub_port_t port) -+{ -+ *(volatile grub_uint32_t *) port = value; -+} -+ -+#endif /* _SYS_IO_H */ -diff --git a/include/grub/loongarch64/linux.h b/include/grub/loongarch64/linux.h -new file mode 100644 -index 0000000..3c6cf65 ---- /dev/null -+++ b/include/grub/loongarch64/linux.h -@@ -0,0 +1,74 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2021 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_LOONGARCH64_LINUX_HEADER -+#define GRUB_LOONGARCH64_LINUX_HEADER 1 -+ -+#include -+ -+/* LoongArch linux kernel type */ -+#define GRUB_LOONGARCH_LINUX_BAD 0 -+#define GRUB_LOONGARCH_LINUX_ELF 1 -+#define GRUB_LOONGARCH_LINUX_EFI 2 -+ -+#define GRUB_LOONGSON3_BOOT_MEM_MAP_MAX 128 -+ -+#define GRUB_LINUX_LOONGARCH_MAGIC_SIGNATURE 0x4C6F6F6E67417263 /* 'LoongArc' */ -+#define GRUB_LINUX_LOONGARCH_MAGIC_SIGNATURE2 0x68 /* 'h' */ -+#define linux_arch_kernel_header linux_loongarch64_kernel_header -+ -+/* From linux/Documentation/loongarch/booting.txt -+ * -+ * 0-1: MZ -+ * 0x28: LoongArch\0 -+ * 0x3c: PE/COFF头偏移 -+ * 0x20e:内核版本号偏移-512 -+ * riscv的version字段在0x20偏移处,现在LoongArch没有使用,是0 -+ */ -+struct linux_loongarch64_kernel_header -+{ -+ grub_uint32_t code0; /* Executable code */ -+ grub_uint32_t code1; /* Executable code */ -+ grub_uint64_t text_offset; /* Image load offset */ -+ grub_uint64_t res0; /* reserved */ -+ grub_uint64_t res1; /* reserved */ -+ grub_uint64_t res2; /* reserved */ -+ grub_uint64_t magic; /* Magic number, little endian, "LoongArc" */ -+ grub_uint32_t magic1; /* Magic number, little endian, "h" */ -+ grub_uint64_t res3; /* reserved */ -+ grub_uint32_t hdr_offset; /* Offset of PE/COFF header */ -+}; -+ -+struct linux_loongarch64_kernel_params -+{ -+ grub_addr_t kernel_addr; /* kernel entry address */ -+ grub_size_t kernel_size; /* kernel size */ -+ grub_addr_t ramdisk_addr; /* initrd load address */ -+ grub_size_t ramdisk_size; /* initrd size */ -+ int linux_argc; -+ grub_addr_t linux_argv; -+ void* linux_args; -+}; -+ -+#include -+#include -+ -+#define ELF32_LOADMASK (0xf0000000UL) -+#define ELF64_LOADMASK (0xf000000000000000ULL) -+ -+#endif /* ! GRUB_LOONGARCH64_LINUX_HEADER */ -diff --git a/include/grub/loongarch64/loongarch64.h b/include/grub/loongarch64/loongarch64.h -new file mode 100644 -index 0000000..ea3be3d ---- /dev/null -+++ b/include/grub/loongarch64/loongarch64.h -@@ -0,0 +1,30 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2010,2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_REGISTERS_CPU_HEADER -+#define GRUB_REGISTERS_CPU_HEADER 1 -+ -+#ifdef ASM_FILE -+#define GRUB_CPU_REGISTER_WRAP(x) x -+#else -+#define GRUB_CPU_REGISTER_WRAP(x) #x -+#endif -+ -+#define GRUB_CPU_LOONGARCH_COP0_TIMER_COUNT GRUB_CPU_REGISTER_WRAP(9) -+ -+#endif -diff --git a/include/grub/loongarch64/memory.h b/include/grub/loongarch64/memory.h -new file mode 100644 -index 0000000..8281dab ---- /dev/null -+++ b/include/grub/loongarch64/memory.h -@@ -0,0 +1,60 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_MEMORY_CPU_HEADER -+#define GRUB_MEMORY_CPU_HEADER 1 -+ -+#ifndef ASM_FILE -+#include -+#include -+#include -+#endif -+ -+#ifndef ASM_FILE -+ -+typedef grub_addr_t grub_phys_addr_t; -+ -+static inline grub_phys_addr_t -+grub_vtop (void *a) -+{ -+ if (-1 == ((grub_int64_t) a >> 32)) -+ return ((grub_phys_addr_t) a) & 0x1fffffffUL; -+ return ((grub_phys_addr_t) a) & 0xffffffffffffUL; -+} -+ -+static inline void * -+grub_map_memory (grub_phys_addr_t a, -+ grub_size_t size __attribute__ ((unused))) -+{ -+ grub_uint64_t addr; -+ asm volatile ("csrrd %0, 0x181" : "=r" (addr)); -+ if (addr & 0x1) -+ return (void *) (a | (addr & 0xffffffffffffff00UL)); -+ else -+ return (void *) a; -+} -+ -+static inline void -+grub_unmap_memory (void *a __attribute__ ((unused)), -+ grub_size_t size __attribute__ ((unused))) -+{ -+} -+ -+#endif -+ -+#endif -diff --git a/include/grub/loongarch64/relocator.h b/include/grub/loongarch64/relocator.h -new file mode 100644 -index 0000000..8815314 ---- /dev/null -+++ b/include/grub/loongarch64/relocator.h -@@ -0,0 +1,38 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_RELOCATOR_CPU_HEADER -+#define GRUB_RELOCATOR_CPU_HEADER 1 -+ -+#include -+#include -+#include -+ -+struct grub_relocator64_state -+{ -+ /* gpr[0] is ignored since it's hardwired to 0. */ -+ grub_uint64_t gpr[32]; -+ /* Register holding target $pc. */ -+ int jumpreg; -+}; -+ -+grub_err_t -+grub_relocator64_boot (struct grub_relocator *rel, -+ struct grub_relocator64_state state); -+ -+#endif /* ! GRUB_RELOCATOR_CPU_HEADER */ -diff --git a/include/grub/loongarch64/setjmp.h b/include/grub/loongarch64/setjmp.h -new file mode 100644 -index 0000000..d9a0776 ---- /dev/null -+++ b/include/grub/loongarch64/setjmp.h -@@ -0,0 +1,27 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2002,2004,2006,2007,2009,2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_SETJMP_CPU_HEADER -+#define GRUB_SETJMP_CPU_HEADER 1 -+ -+typedef grub_uint64_t grub_jmp_buf[12]; -+ -+int grub_setjmp (grub_jmp_buf env) RETURNS_TWICE; -+void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn)); -+ -+#endif /* ! GRUB_SETJMP_CPU_HEADER */ -diff --git a/include/grub/loongarch64/time.h b/include/grub/loongarch64/time.h -new file mode 100644 -index 0000000..c9a7334 ---- /dev/null -+++ b/include/grub/loongarch64/time.h -@@ -0,0 +1,39 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2003,2004,2005,2007,2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef KERNEL_CPU_TIME_HEADER -+#define KERNEL_CPU_TIME_HEADER 1 -+ -+#ifndef GRUB_UTIL -+ -+#define GRUB_TICKS_PER_SECOND (grub_arch_cpuclock / 2) -+ -+void grub_timer_init (grub_uint32_t cpuclock); -+ -+/* Return the real time in ticks. */ -+grub_uint64_t grub_get_rtc (void); -+ -+extern grub_uint32_t grub_arch_cpuclock; -+#endif -+ -+static inline void -+grub_cpu_idle(void) -+{ -+} -+ -+#endif -diff --git a/include/grub/loongarch64/types.h b/include/grub/loongarch64/types.h -new file mode 100644 -index 0000000..5dc7f21 ---- /dev/null -+++ b/include/grub/loongarch64/types.h -@@ -0,0 +1,34 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2002,2006,2007,2009,2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_TYPES_CPU_HEADER -+#define GRUB_TYPES_CPU_HEADER 1 -+ -+/* The size of void *. */ -+#define GRUB_TARGET_SIZEOF_VOID_P 8 -+ -+/* The size of long. */ -+#define GRUB_TARGET_SIZEOF_LONG 8 -+ -+#ifdef GRUB_CPU_LOONGARCH -+/* loongarch is little-endian. */ -+#undef GRUB_TARGET_WORDS_BIGENDIAN -+ -+#endif /* ! GRUB_TYPES_CPU_HEADER */ -+ -+#endif -diff --git a/include/grub/util/install.h b/include/grub/util/install.h -index dad1756..33feae9 100644 ---- a/include/grub/util/install.h -+++ b/include/grub/util/install.h -@@ -107,6 +107,7 @@ enum grub_install_plat - GRUB_INSTALL_PLATFORM_X86_64_XEN, - GRUB_INSTALL_PLATFORM_ARM64_EFI, - GRUB_INSTALL_PLATFORM_ARM_COREBOOT, -+ GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI, - GRUB_INSTALL_PLATFORM_MAX - }; - -diff --git a/util/grub-install-common.c b/util/grub-install-common.c -index fde4ca7..6504637 100644 ---- a/util/grub-install-common.c -+++ b/util/grub-install-common.c -@@ -738,27 +738,28 @@ static struct - const char *platform; - } platforms[GRUB_INSTALL_PLATFORM_MAX] = - { -- [GRUB_INSTALL_PLATFORM_I386_PC] = { "i386", "pc" }, -- [GRUB_INSTALL_PLATFORM_I386_EFI] = { "i386", "efi" }, -- [GRUB_INSTALL_PLATFORM_I386_QEMU] = { "i386", "qemu" }, -- [GRUB_INSTALL_PLATFORM_I386_COREBOOT] = { "i386", "coreboot" }, -- [GRUB_INSTALL_PLATFORM_I386_MULTIBOOT] = { "i386", "multiboot" }, -- [GRUB_INSTALL_PLATFORM_I386_IEEE1275] = { "i386", "ieee1275" }, -- [GRUB_INSTALL_PLATFORM_X86_64_EFI] = { "x86_64", "efi" }, -- [GRUB_INSTALL_PLATFORM_I386_XEN] = { "i386", "xen" }, -- [GRUB_INSTALL_PLATFORM_X86_64_XEN] = { "x86_64", "xen" }, -- [GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON] = { "mipsel", "loongson" }, -- [GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS] = { "mipsel", "qemu_mips" }, -- [GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS] = { "mips", "qemu_mips" }, -- [GRUB_INSTALL_PLATFORM_MIPSEL_ARC] = { "mipsel", "arc" }, -- [GRUB_INSTALL_PLATFORM_MIPS_ARC] = { "mips", "arc" }, -- [GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275] = { "sparc64", "ieee1275" }, -- [GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275] = { "powerpc", "ieee1275" }, -- [GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64", "efi" }, -- [GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm", "efi" }, -- [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64", "efi" }, -- [GRUB_INSTALL_PLATFORM_ARM_UBOOT] = { "arm", "uboot" }, -- [GRUB_INSTALL_PLATFORM_ARM_COREBOOT] = { "arm", "coreboot" }, -+ [GRUB_INSTALL_PLATFORM_I386_PC] = { "i386", "pc" }, -+ [GRUB_INSTALL_PLATFORM_I386_EFI] = { "i386", "efi" }, -+ [GRUB_INSTALL_PLATFORM_I386_QEMU] = { "i386", "qemu" }, -+ [GRUB_INSTALL_PLATFORM_I386_COREBOOT] = { "i386", "coreboot" }, -+ [GRUB_INSTALL_PLATFORM_I386_MULTIBOOT] = { "i386", "multiboot" }, -+ [GRUB_INSTALL_PLATFORM_I386_IEEE1275] = { "i386", "ieee1275" }, -+ [GRUB_INSTALL_PLATFORM_X86_64_EFI] = { "x86_64", "efi" }, -+ [GRUB_INSTALL_PLATFORM_I386_XEN] = { "i386", "xen" }, -+ [GRUB_INSTALL_PLATFORM_X86_64_XEN] = { "x86_64", "xen" }, -+ [GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON] = { "mipsel", "loongson" }, -+ [GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS] = { "mipsel", "qemu_mips" }, -+ [GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS] = { "mips", "qemu_mips" }, -+ [GRUB_INSTALL_PLATFORM_MIPSEL_ARC] = { "mipsel", "arc" }, -+ [GRUB_INSTALL_PLATFORM_MIPS_ARC] = { "mips", "arc" }, -+ [GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275] = { "sparc64", "ieee1275" }, -+ [GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275] = { "powerpc", "ieee1275" }, -+ [GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64", "efi" }, -+ [GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm", "efi" }, -+ [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64", "efi" }, -+ [GRUB_INSTALL_PLATFORM_ARM_UBOOT] = { "arm", "uboot" }, -+ [GRUB_INSTALL_PLATFORM_ARM_COREBOOT] = { "arm", "coreboot" }, -+ [GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI] = { "loongarch64", "efi" }, - }; - - char * -diff --git a/util/grub-install.c b/util/grub-install.c -index 65bb2f9..28b5d74 100644 ---- a/util/grub-install.c -+++ b/util/grub-install.c -@@ -322,6 +322,8 @@ get_default_platform (void) - return "arm-uboot"; - #elif defined (__aarch64__) - return "arm64-efi"; -+#elif defined (__loongarch64) -+ return "loongarch64-efi"; - #elif defined (__amd64__) || defined (__x86_64__) || defined (__i386__) - return grub_install_get_default_x86_platform (); - #else -@@ -477,6 +479,7 @@ have_bootdev (enum grub_install_plat pl) - case GRUB_INSTALL_PLATFORM_IA64_EFI: - case GRUB_INSTALL_PLATFORM_ARM_EFI: - case GRUB_INSTALL_PLATFORM_ARM64_EFI: -+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: - case GRUB_INSTALL_PLATFORM_I386_IEEE1275: - case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: - case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275: -@@ -895,6 +898,7 @@ main (int argc, char *argv[]) - case GRUB_INSTALL_PLATFORM_I386_EFI: - case GRUB_INSTALL_PLATFORM_IA64_EFI: - case GRUB_INSTALL_PLATFORM_X86_64_EFI: -+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: - is_efi = 1; - grub_util_error (_("this utility cannot be used for EFI platforms" - " because it does not support UEFI Secure Boot")); -@@ -921,6 +925,7 @@ main (int argc, char *argv[]) - case GRUB_INSTALL_PLATFORM_ARM_EFI: - case GRUB_INSTALL_PLATFORM_ARM64_EFI: - case GRUB_INSTALL_PLATFORM_IA64_EFI: -+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: - case GRUB_INSTALL_PLATFORM_I386_IEEE1275: - case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: - case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275: -@@ -965,6 +970,7 @@ main (int argc, char *argv[]) - case GRUB_INSTALL_PLATFORM_ARM_EFI: - case GRUB_INSTALL_PLATFORM_ARM64_EFI: - case GRUB_INSTALL_PLATFORM_IA64_EFI: -+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: - case GRUB_INSTALL_PLATFORM_I386_IEEE1275: - case GRUB_INSTALL_PLATFORM_ARM_UBOOT: - case GRUB_INSTALL_PLATFORM_I386_QEMU: -@@ -1110,6 +1116,9 @@ main (int argc, char *argv[]) - case GRUB_INSTALL_PLATFORM_ARM64_EFI: - efi_file = "BOOTAA64.EFI"; - break; -+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: -+ efi_file = "BOOTLOONGARCH64.EFI"; -+ break; - default: - grub_util_error ("%s", _("You've found a bug")); - break; -@@ -1137,6 +1146,9 @@ main (int argc, char *argv[]) - case GRUB_INSTALL_PLATFORM_ARM64_EFI: - efi_file = "grubaa64.efi"; - break; -+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: -+ efi_file = "grubloongarch64.efi"; -+ break; - default: - efi_file = "grub.efi"; - break; -@@ -1440,6 +1452,7 @@ main (int argc, char *argv[]) - case GRUB_INSTALL_PLATFORM_ARM_EFI: - case GRUB_INSTALL_PLATFORM_ARM64_EFI: - case GRUB_INSTALL_PLATFORM_IA64_EFI: -+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: - g = grub_util_guess_efi_drive (*curdev); - break; - case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: -@@ -1581,6 +1594,7 @@ main (int argc, char *argv[]) - case GRUB_INSTALL_PLATFORM_ARM_EFI: - case GRUB_INSTALL_PLATFORM_ARM64_EFI: - case GRUB_INSTALL_PLATFORM_IA64_EFI: -+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: - core_name = "core.efi"; - snprintf (mkimage_target, sizeof (mkimage_target), - "%s-%s", -@@ -1683,6 +1697,7 @@ main (int argc, char *argv[]) - case GRUB_INSTALL_PLATFORM_ARM_EFI: - case GRUB_INSTALL_PLATFORM_ARM64_EFI: - case GRUB_INSTALL_PLATFORM_IA64_EFI: -+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: - case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS: - case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS: - case GRUB_INSTALL_PLATFORM_I386_COREBOOT: -@@ -1917,6 +1932,7 @@ main (int argc, char *argv[]) - case GRUB_INSTALL_PLATFORM_ARM_EFI: - case GRUB_INSTALL_PLATFORM_ARM64_EFI: - case GRUB_INSTALL_PLATFORM_IA64_EFI: -+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: - { - char *dst = grub_util_path_concat (2, efidir, efi_file); - grub_install_copy_file (imgfile, dst, 1); -diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c -index 1bb5eb8..240e193 100644 ---- a/util/grub-mkimagexx.c -+++ b/util/grub-mkimagexx.c -@@ -783,6 +783,9 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, - struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off); - grub_uint64_t *gpptr = (void *) (pe_target + got_off); - unsigned unmatched_adr_got_page = 0; -+ grub_uint64_t oprs[10240]= {0}; -+ int opri = -1; -+ grub_uint32_t la_abs = 0; - #define MASK19 ((1 << 19) - 1) - #else - grub_uint32_t *tr = (void *) (pe_target + tramp_off); -@@ -1122,6 +1125,173 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, - } - break; - } -+ case EM_LOONGARCH64: -+ { -+ sym_addr += addend; -+ switch (ELF_R_TYPE (info)) -+ { -+ case R_LARCH_64: -+ { -+ *target=(grub_uint64_t)sym_addr; -+ } -+ break; -+ case R_LARCH_MARK_LA: -+ { -+ la_abs=1; -+ } -+ break; -+ case R_LARCH_SOP_PUSH_PCREL: -+ { -+ opri++; -+ oprs[opri]=(grub_uint64_t)(sym_addr-(target_section_addr+offset+image_target->vaddr_offset)); -+ } -+ break; -+ case R_LARCH_SOP_PUSH_ABSOLUTE: -+ { -+ opri++; -+ oprs[opri]=(grub_uint64_t)sym_addr; -+ } -+ break; -+ case R_LARCH_SOP_PUSH_PLT_PCREL: -+ { -+ opri++; -+ oprs[opri]=(grub_uint64_t)(sym_addr-(target_section_addr+offset+image_target->vaddr_offset)); -+ } -+ break; -+ case R_LARCH_SOP_SUB: -+ { -+ grub_uint64_t opr2=oprs[opri]; -+ opri--; -+ grub_uint64_t opr1=oprs[opri]; -+ opri--; -+ opri++; -+ oprs[opri]=opr1 - opr2; -+ } -+ break; -+ case R_LARCH_SOP_SL: -+ { -+ grub_uint64_t opr2=oprs[opri]; -+ opri--; -+ grub_uint64_t opr1=oprs[opri]; -+ opri--; -+ opri++; -+ oprs[opri]=opr1 << opr2; -+ } -+ break; -+ case R_LARCH_SOP_SR: -+ { -+ grub_uint64_t opr2=oprs[opri]; -+ opri--; -+ grub_uint64_t opr1=oprs[opri]; -+ opri--; -+ opri++; -+ oprs[opri]=opr1 >> opr2; -+ } -+ break; -+ case R_LARCH_SOP_ADD: -+ { -+ grub_uint64_t opr2=oprs[opri]; -+ opri--; -+ grub_uint64_t opr1=oprs[opri]; -+ opri--; -+ opri++; -+ oprs[opri]=opr1 + opr2; -+ } -+ break; -+ case R_LARCH_SOP_AND: -+ { -+ grub_uint64_t opr2=oprs[opri]; -+ opri--; -+ grub_uint64_t opr1=oprs[opri]; -+ opri--; -+ opri++; -+ oprs[opri]=opr1 & opr2; -+ } -+ break; -+ case R_LARCH_SOP_IF_ELSE: -+ { -+ grub_uint64_t opr3=oprs[opri]; -+ opri--; -+ grub_uint64_t opr2=oprs[opri]; -+ opri--; -+ grub_uint64_t opr1=oprs[opri]; -+ opri--; -+ if(opr1){ -+ opri++; -+ oprs[opri]=opr2; -+ } else { -+ opri++; -+ oprs[opri]=opr3; -+ } -+ } -+ break; -+ case R_LARCH_SOP_POP_32_S_10_5: -+ { -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *target=(*target) | ((opr1 & 0x1f) << 10); -+ } -+ break; -+ case R_LARCH_SOP_POP_32_U_10_12: -+ { -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *target=(*target) | ((opr1 & 0xfff) << 10); -+ } -+ break; -+ case R_LARCH_SOP_POP_32_S_10_12: -+ { -+ if(la_abs==1) -+ la_abs=0; -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *target = (*target) | ((opr1 & 0xfff) << 10); -+ } -+ break; -+ case R_LARCH_SOP_POP_32_S_10_16: -+ { -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *target = (*target) | ((opr1 & 0xffff) << 10); -+ } -+ break; -+ case R_LARCH_SOP_POP_32_S_10_16_S2: -+ { -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *target = (*target) | (((opr1 >> 2) & 0xffff) << 10); -+ } -+ break; -+ case R_LARCH_SOP_POP_32_S_5_20: -+ { -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *target = (*target) | ((opr1 & 0xfffff)<<5) ; -+ } -+ break; -+ case R_LARCH_SOP_POP_32_S_0_5_10_16_S2: -+ { -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *target =(*target) | (((opr1 >> 2) & 0xffff) << 10); -+ *target =(*target) | ((opr1 >> 18) & 0x1f); -+ } -+ break; -+ case R_LARCH_SOP_POP_32_S_0_10_10_16_S2: -+ { -+ grub_uint64_t opr1 = oprs[opri]; -+ opri--; -+ *target =(*target) | (((opr1 >> 2) & 0xffff) << 10); -+ *target =(*target) | ((opr1 >> 18) & 0x3ff); -+ } -+ break; -+ default: -+ grub_util_error (_("relocation 0x%x is not implemented yet"), -+ (unsigned int) ELF_R_TYPE (info)); -+ break; -+ } -+ break; -+ } - #endif - #if defined(MKIMAGE_ELF32) - case EM_ARM: -@@ -1310,7 +1480,10 @@ add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type, - - /* The spec does not mention the requirement of a Page RVA. - Here, align the address with a 4K boundary for safety. */ -- b->page_rva = (addr & ~(0x1000 - 1)); -+#ifdef GRUB_CPU_LOONGARCH64 -+ if (type) -+#endif -+ b->page_rva = (addr & ~(0x1000 - 1)); - b->block_size = sizeof (*b); - } - -@@ -1320,7 +1493,11 @@ add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type, - - /* Add a new entry. */ - cur_index = ((b->block_size - sizeof (*b)) >> 1); -+#ifdef GRUB_CPU_LOONGARCH64 -+ entry = GRUB_PE32_FIXUP_ENTRY (type, type ? (addr - b->page_rva) : addr); -+#else - entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva); -+#endif - b->entries[cur_index] = grub_host_to_target16 (entry); - b->block_size += 2; - } -@@ -1366,6 +1543,10 @@ static void - translate_relocation_pe (struct translate_context *ctx, - Elf_Addr addr, - Elf_Addr info, -+#ifdef GRUB_CPU_LOONGARCH64 -+ Elf_Addr sym_addr, -+ Elf_Addr addend, -+#endif - const struct grub_install_image_target_desc *image_target) - { - /* Necessary to relocate only absolute addresses. */ -@@ -1477,6 +1658,133 @@ translate_relocation_pe (struct translate_context *ctx, - } - break; - break; -+ case EM_LOONGARCH64: -+ switch (ELF_R_TYPE (info)) -+ { -+ case R_LARCH_NONE: -+ break; -+ case R_LARCH_32: -+ break; -+ case R_LARCH_64: -+ { -+ ctx->current_address = add_fixup_entry ( -+ &ctx->lst, -+ GRUB_PE32_REL_BASED_DIR64, -+ addr, 0, ctx->current_address, -+ image_target); -+ } -+ break; -+ case R_LARCH_RELATIVE: -+ break; -+ case R_LARCH_COPY: -+ break; -+ case R_LARCH_JUMP_SLOT: -+ break; -+ case R_LARCH_TLS_DTPMOD32: -+ break; -+ case R_LARCH_TLS_DTPMOD64: -+ break; -+ case R_LARCH_TLS_DTPREL32: -+ break; -+ case R_LARCH_TLS_DTPREL64: -+ break; -+ case R_LARCH_TLS_TPREL32: -+ break; -+ case R_LARCH_TLS_TPREL64: -+ break; -+ case R_LARCH_IRELATIVE: -+ break; -+ case R_LARCH_MARK_LA: -+ { -+ ctx->current_address = add_fixup_entry ( -+ &ctx->lst, -+ GRUB_PE32_REL_BASED_LOONGARCH64, -+ addr, 0, ctx->current_address, -+ image_target); -+ } -+ break; -+ case R_LARCH_MARK_PCREL: -+ break; -+ case R_LARCH_SOP_PUSH_PCREL: -+ break; -+ case R_LARCH_SOP_PUSH_ABSOLUTE: -+ break; -+ case R_LARCH_SOP_PUSH_DUP: -+ break; -+ case R_LARCH_SOP_PUSH_GPREL: -+ break; -+ case R_LARCH_SOP_PUSH_TLS_TPREL: -+ break; -+ case R_LARCH_SOP_PUSH_TLS_GOT: -+ break; -+ case R_LARCH_SOP_PUSH_TLS_GD: -+ break; -+ case R_LARCH_SOP_PUSH_PLT_PCREL: -+ break; -+ case R_LARCH_SOP_ASSERT: -+ break; -+ case R_LARCH_SOP_NOT: -+ break; -+ case R_LARCH_SOP_SUB: -+ break; -+ case R_LARCH_SOP_SL: -+ break; -+ case R_LARCH_SOP_SR: -+ break; -+ case R_LARCH_SOP_ADD: -+ break; -+ case R_LARCH_SOP_AND: -+ break; -+ case R_LARCH_SOP_IF_ELSE: -+ break; -+ case R_LARCH_SOP_POP_32_S_10_5: -+ break; -+ case R_LARCH_SOP_POP_32_U_10_12: -+ break; -+ case R_LARCH_SOP_POP_32_S_10_12: -+ break; -+ case R_LARCH_SOP_POP_32_S_10_16: -+ break; -+ case R_LARCH_SOP_POP_32_S_10_16_S2: -+ break; -+ case R_LARCH_SOP_POP_32_S_5_20: -+ break; -+ case R_LARCH_SOP_POP_32_S_0_5_10_16_S2: -+ break; -+ case R_LARCH_SOP_POP_32_S_0_10_10_16_S2: -+ break; -+ case R_LARCH_SOP_POP_32_U: -+ break; -+ case R_LARCH_ADD8: -+ break; -+ case R_LARCH_ADD16: -+ break; -+ case R_LARCH_ADD24: -+ break; -+ case R_LARCH_ADD32: -+ break; -+ case R_LARCH_ADD64: -+ break; -+ case R_LARCH_SUB8: -+ break; -+ case R_LARCH_SUB16: -+ break; -+ case R_LARCH_SUB24: -+ break; -+ case R_LARCH_SUB32: -+ break; -+ case R_LARCH_SUB64: -+ break; -+ case R_LARCH_GNU_VTINHERIT: -+ break; -+ case R_LARCH_GNU_VTENTRY: -+ break; -+ default: -+ grub_util_error (_("relocation 0x%x is not implemented yet"), -+ (unsigned int) ELF_R_TYPE (info)); -+ break; -+ } -+ break; - #if defined(MKIMAGE_ELF32) - case EM_ARM: - switch (ELF_R_TYPE (info)) -@@ -1565,10 +1873,18 @@ static void - translate_relocation (struct translate_context *ctx, - Elf_Addr addr, - Elf_Addr info, -+#ifdef GRUB_CPU_LOONGARCH64 -+ Elf_Addr sym_addr, -+ Elf_Addr addend, -+#endif - const struct grub_install_image_target_desc *image_target) - { - if (image_target->id == IMAGE_EFI) -+#ifdef GRUB_CPU_LOONGARCH64 -+ translate_relocation_pe (ctx, addr, info, sym_addr, addend, image_target); -+#else - translate_relocation_pe (ctx, addr, info, image_target); -+#endif - else - translate_relocation_raw (ctx, addr, info, image_target); - } -@@ -1709,11 +2025,21 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout, - if ((grub_target_to_host32 (s->sh_type) == SHT_REL) || - (grub_target_to_host32 (s->sh_type) == SHT_RELA)) - { -+#ifdef GRUB_CPU_LOONGARCH64 -+ Elf_Rela *r; -+#else - Elf_Rel *r; -+#endif - Elf_Word rtab_size, r_size, num_rs; - Elf_Off rtab_offset; - Elf_Addr section_address; - Elf_Word j; -+#ifdef GRUB_CPU_LOONGARCH64 -+ Elf_Shdr *symtab_section; -+ -+ symtab_section = (Elf_Shdr *) ((char *) smd->sections -+ + (grub_target_to_host32 (s->sh_link) * smd->section_entsize)); -+#endif - - if (!SUFFIX (is_kept_reloc_section) (s, image_target, smd)) - { -@@ -1732,20 +2058,39 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout, - - section_address = smd->vaddrs[grub_le_to_cpu32 (s->sh_info)]; - -+#ifdef GRUB_CPU_LOONGARCH64 -+ for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset); -+ j < num_rs; -+ j++, r = (Elf_Rela *) ((char *) r + r_size)) -+#else - for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset); - j < num_rs; - j++, r = (Elf_Rel *) ((char *) r + r_size)) -+#endif - { - Elf_Addr info; - Elf_Addr offset; - Elf_Addr addr; -+#ifdef GRUB_CPU_LOONGARCH64 -+ Elf_Addr sym_addr; -+ Elf_Addr addend; -+#endif - - offset = grub_target_to_host (r->r_offset); - info = grub_target_to_host (r->r_info); -- -+#ifdef GRUB_CPU_LOONGARCH64 -+ sym_addr = SUFFIX (get_symbol_address) (e, symtab_section, -+ ELF_R_SYM (info), image_target); -+ addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ? -+ grub_target_to_host (r->r_addend) : 0; -+#endif - addr = section_address + offset; - -+#ifdef GRUB_CPU_LOONGARCH64 -+ translate_relocation (&ctx, addr, info, sym_addr, addend, image_target); -+#else - translate_relocation (&ctx, addr, info, image_target); -+#endif - } - } - -diff --git a/util/grub-mknetdir.c b/util/grub-mknetdir.c -index ae31271..c998850 100644 ---- a/util/grub-mknetdir.c -+++ b/util/grub-mknetdir.c -@@ -112,7 +112,8 @@ static struct - [GRUB_INSTALL_PLATFORM_X86_64_EFI] = { "x86_64-efi", "efinet", ".efi" }, - [GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64-efi", "efinet", ".efi" }, - [GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm-efi", "efinet", ".efi" }, -- [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64-efi", "efinet", ".efi" } -+ [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64-efi", "efinet", ".efi" }, -+ [GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI] = { "loongarch64-efi", "efinet", ".efi" } - }; - - static void -diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c -index 03ba1ab..4a9943a 100644 ---- a/util/grub-module-verifier.c -+++ b/util/grub-module-verifier.c -@@ -119,6 +119,52 @@ struct grub_module_verifier_arch archs[] = { - -1 - } - }, -+ { "loongarch64", 8, 0, EM_LOONGARCH64, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ -+ R_LARCH_NONE, -+ R_LARCH_32, -+ R_LARCH_64, -+ R_LARCH_RELATIVE, -+ R_LARCH_COPY, -+ R_LARCH_JUMP_SLOT, -+ R_LARCH_TLS_DTPMOD32, -+ R_LARCH_TLS_DTPMOD64, -+ R_LARCH_TLS_DTPREL32, -+ R_LARCH_TLS_DTPREL64, -+ R_LARCH_TLS_TPREL32, -+ R_LARCH_TLS_TPREL64, -+ R_LARCH_IRELATIVE, -+ R_LARCH_MARK_LA, -+ R_LARCH_MARK_PCREL, -+ R_LARCH_SOP_PUSH_PCREL, -+ R_LARCH_SOP_PUSH_ABSOLUTE, -+ R_LARCH_SOP_PUSH_DUP, -+ R_LARCH_SOP_PUSH_GPREL, -+ R_LARCH_SOP_PUSH_TLS_TPREL, -+ R_LARCH_SOP_PUSH_TLS_GOT, -+ R_LARCH_SOP_PUSH_TLS_GD, -+ R_LARCH_SOP_PUSH_PLT_PCREL, -+ R_LARCH_SOP_ASSERT, -+ R_LARCH_SOP_NOT, -+ R_LARCH_SOP_SUB, -+ R_LARCH_SOP_SL, -+ R_LARCH_SOP_SR, -+ R_LARCH_SOP_ADD, -+ R_LARCH_SOP_AND, -+ R_LARCH_SOP_IF_ELSE, -+ R_LARCH_SOP_POP_32_S_10_5, -+ R_LARCH_SOP_POP_32_U_10_12, -+ R_LARCH_SOP_POP_32_S_10_12, -+ R_LARCH_SOP_POP_32_S_10_16, -+ R_LARCH_SOP_POP_32_S_10_16_S2, -+ R_LARCH_SOP_POP_32_S_5_20, -+ R_LARCH_SOP_POP_32_S_0_5_10_16_S2, -+ R_LARCH_SOP_POP_32_S_0_10_10_16_S2, -+ R_LARCH_SOP_POP_32_U, -+ -1 -+ }, (int[]){ -+ -1 -+ } -+ }, - }; - - struct platform_whitelist { -diff --git a/util/mkimage.c b/util/mkimage.c -index c770259..250ca81 100644 ---- a/util/mkimage.c -+++ b/util/mkimage.c -@@ -609,6 +609,22 @@ static const struct grub_install_image_target_desc image_targets[] = - .pe_target = GRUB_PE32_MACHINE_ARM64, - .elf_target = EM_AARCH64, - }, -+ { -+ .dirname = "loongarch64-efi", -+ .names = { "loongarch64-efi", NULL }, -+ .voidp_sizeof = 8, -+ .bigendian = 0, -+ .id = IMAGE_EFI, -+ .flags = PLATFORM_FLAGS_NONE, -+ .total_module_size = TARGET_NO_FIELD, -+ .decompressor_compressed_size = TARGET_NO_FIELD, -+ .decompressor_uncompressed_size = TARGET_NO_FIELD, -+ .decompressor_uncompressed_addr = TARGET_NO_FIELD, -+ .section_align = GRUB_PE32_SECTION_ALIGNMENT, -+ .vaddr_offset = EFI64_HEADER_SIZE, -+ .pe_target = GRUB_PE32_MACHINE_LOONGARCH64, -+ .elf_target = EM_LOONGARCH64, -+ }, - }; - - #include --- -2.1.0 - diff --git a/1003-cryptodisk-make-the-password-getter-and-additional-a.patch b/1003-cryptodisk-make-the-password-getter-and-additional-a.patch deleted file mode 100644 index bf6e451..0000000 --- a/1003-cryptodisk-make-the-password-getter-and-additional-a.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 6503036b4adfcb078dc33b23a61969d914f7449b Mon Sep 17 00:00:00 2001 -From: James Bottomley -Date: Thu, 31 Dec 2020 09:36:16 -0800 -Subject: [PATCH 1/3] cryptodisk: make the password getter and additional - argument to recover_key - -cherry-picked from https://lists.gnu.org/archive/html/grub-devel/2020-12/msg00258.html. - -For AMD SEV environments, the grub boot password has to be retrieved -from a given memory location rather than prompted for. This means -that the standard password getter needs to be replaced with one that -gets the passphrase from the SEV area and uses that instead. Adding -the password getter as a passed in argument to recover_key() makes -this possible. - -Signed-off-by: James Bottomley ---- - grub-core/disk/cryptodisk.c | 2 +- - grub-core/disk/geli.c | 12 +++++++----- - grub-core/disk/luks.c | 12 +++++++----- - grub-core/lib/crypto.c | 4 ++++ - grub-core/osdep/unix/password.c | 4 ++++ - grub-core/osdep/windows/password.c | 4 ++++ - include/grub/cryptodisk.h | 6 +++++- - 7 files changed, 32 insertions(+), 12 deletions(-) - -diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c -index 78a9025..133d36d 100644 ---- a/grub-core/disk/cryptodisk.c -+++ b/grub-core/disk/cryptodisk.c -@@ -839,7 +839,7 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source) - if (!dev) - continue; - -- err = cr->recover_key (source, dev); -+ err = cr->recover_key (source, dev, grub_password_get); - if (err) - { - cryptodisk_close (dev); -diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c -index e9d2329..ed43047 100644 ---- a/grub-core/disk/geli.c -+++ b/grub-core/disk/geli.c -@@ -398,7 +398,8 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, - } - - static grub_err_t --recover_key (grub_disk_t source, grub_cryptodisk_t dev) -+recover_key (grub_disk_t source, grub_cryptodisk_t dev, -+ grub_passwd_cb *password_get) - { - grub_size_t keysize; - grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN]; -@@ -438,11 +439,12 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) - tmp = NULL; - if (source->partition) - tmp = grub_partition_get_name (source->partition); -- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, -- source->partition ? "," : "", tmp ? : "", -- dev->uuid); -+ if (password_get (NULL, 0)) -+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, -+ source->partition ? "," : "", tmp ? : "", -+ dev->uuid); - grub_free (tmp); -- if (!grub_password_get (passphrase, MAX_PASSPHRASE)) -+ if (!password_get (passphrase, MAX_PASSPHRASE)) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); - - /* Calculate the PBKDF2 of the user supplied passphrase. */ -diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c -index 18b3a8b..037d20d 100644 ---- a/grub-core/disk/luks.c -+++ b/grub-core/disk/luks.c -@@ -309,7 +309,8 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, - - static grub_err_t - luks_recover_key (grub_disk_t source, -- grub_cryptodisk_t dev) -+ grub_cryptodisk_t dev, -+ grub_passwd_cb *password_get) - { - struct grub_luks_phdr header; - grub_size_t keysize; -@@ -344,11 +345,12 @@ luks_recover_key (grub_disk_t source, - tmp = NULL; - if (source->partition) - tmp = grub_partition_get_name (source->partition); -- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, -- source->partition ? "," : "", tmp ? : "", -- dev->uuid); -+ if (password_get (NULL, 0)) -+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, -+ source->partition ? "," : "", tmp ? : "", -+ dev->uuid); - grub_free (tmp); -- if (!grub_password_get (passphrase, MAX_PASSPHRASE)) -+ if (!password_get (passphrase, MAX_PASSPHRASE)) - { - grub_free (split_key); - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); -diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c -index ff62fa3..07c4400 100644 ---- a/grub-core/lib/crypto.c -+++ b/grub-core/lib/crypto.c -@@ -460,6 +460,10 @@ grub_password_get (char buf[], unsigned buf_size) - unsigned cur_len = 0; - int key; - -+ if (!buf) -+ /* want prompt */ -+ return 1; -+ - while (1) - { - key = grub_getkey (); -diff --git a/grub-core/osdep/unix/password.c b/grub-core/osdep/unix/password.c -index 9996b24..365ac4b 100644 ---- a/grub-core/osdep/unix/password.c -+++ b/grub-core/osdep/unix/password.c -@@ -34,6 +34,10 @@ grub_password_get (char buf[], unsigned buf_size) - int tty_changed = 0; - char *ptr; - -+ if (!buf) -+ /* want prompt */ -+ return 1; -+ - grub_refresh (); - - /* Disable echoing. Based on glibc. */ -diff --git a/grub-core/osdep/windows/password.c b/grub-core/osdep/windows/password.c -index 1d3af0c..2a66156 100644 ---- a/grub-core/osdep/windows/password.c -+++ b/grub-core/osdep/windows/password.c -@@ -33,6 +33,10 @@ grub_password_get (char buf[], unsigned buf_size) - DWORD mode = 0; - char *ptr; - -+ if (!buf) -+ /* want prompt */ -+ return 1; -+ - grub_refresh (); - - GetConsoleMode (hStdin, &mode); -diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h -index 32f564a..33c86ad 100644 ---- a/include/grub/cryptodisk.h -+++ b/include/grub/cryptodisk.h -@@ -101,6 +101,9 @@ struct grub_cryptodisk - }; - typedef struct grub_cryptodisk *grub_cryptodisk_t; - -+/* must match prototype for grub_password_get */ -+typedef int (grub_passwd_cb)(char buf[], unsigned buf_size); -+ - struct grub_cryptodisk_dev - { - struct grub_cryptodisk_dev *next; -@@ -108,7 +111,8 @@ struct grub_cryptodisk_dev - - grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid, - int boot_only); -- grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev); -+ grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev, -+ grub_passwd_cb *get_passwd); - }; - typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t; - --- -2.43.5 - diff --git a/1004-cryptodisk-add-OS-provided-secret-support.patch b/1004-cryptodisk-add-OS-provided-secret-support.patch deleted file mode 100644 index 958a745..0000000 --- a/1004-cryptodisk-add-OS-provided-secret-support.patch +++ /dev/null @@ -1,206 +0,0 @@ -From a6d7988415f1ff7e3977b7e15aacaf1e7f854aac Mon Sep 17 00:00:00 2001 -From: James Bottomley -Date: Thu, 31 Dec 2020 09:36:17 -0800 -Subject: [PATCH 2/3] cryptodisk: add OS provided secret support - -cherry-picked from https://lists.gnu.org/archive/html/grub-devel/2020-12/msg00259.html. - -Make use of the new OS provided secrets API so that if the new '-s' -option is passed in we try to extract the secret from the API rather -than prompting for it. - -The primary consumer of this is AMD SEV, which has been programmed to -provide an injectable secret to the encrypted virtual machine. OVMF -provides the secret area and passes it into the EFI Configuration -Tables. The grub EFI layer pulls the secret out and primes the -secrets API with it. The upshot of all of this is that a SEV -protected VM can do an encrypted boot with a protected boot secret. - -Signed-off-by: James Bottomley ---- - grub-core/disk/cryptodisk.c | 77 +++++++++++++++++++++++++++++++++++-- - include/grub/cryptodisk.h | 14 +++++++ - 2 files changed, 87 insertions(+), 4 deletions(-) - -diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c -index 133d36d..d2b1617 100644 ---- a/grub-core/disk/cryptodisk.c -+++ b/grub-core/disk/cryptodisk.c -@@ -41,6 +41,7 @@ static const struct grub_arg_option options[] = - /* TRANSLATORS: It's still restricted to cryptodisks only. */ - {"all", 'a', 0, N_("Mount all."), 0, 0}, - {"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0}, -+ {"secret", 's', 0, N_("Get secret passphrase from named module and optional identifier"), 0, 0}, - {0, 0, 0, 0, 0, 0} - }; - -@@ -809,6 +810,10 @@ grub_util_cryptodisk_get_uuid (grub_disk_t disk) - - static int check_boot, have_it; - static char *search_uuid; -+static char *os_passwd; -+ -+/* variable to hold the list of secret providers */ -+static struct grub_secret_entry *secret_providers; - - static void - cryptodisk_close (grub_cryptodisk_t dev) -@@ -819,6 +824,21 @@ cryptodisk_close (grub_cryptodisk_t dev) - grub_free (dev); - } - -+static int -+os_password_get(char buf[], unsigned len) -+{ -+ if (!buf) -+ /* we're not interactive so no prompt */ -+ return 0; -+ -+ /* os_passwd should be null terminated, so just copy everything */ -+ grub_strncpy(buf, os_passwd, len); -+ /* and add a terminator just in case */ -+ buf[len - 1] = 0; -+ -+ return 1; -+} -+ - static grub_err_t - grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source) - { -@@ -838,8 +858,17 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source) - return grub_errno; - if (!dev) - continue; -- -- err = cr->recover_key (source, dev, grub_password_get); -+ -+ if (os_passwd) -+ { -+ err = cr->recover_key (source, dev, os_password_get); -+ if (err) -+ /* if the key doesn't work ignore the access denied error */ -+ grub_error_pop(); -+ } -+ else -+ err = cr->recover_key (source, dev, grub_password_get); -+ - if (err) - { - cryptodisk_close (dev); -@@ -855,6 +884,18 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source) - return GRUB_ERR_NONE; - } - -+void -+grub_cryptodisk_add_secret_provider (struct grub_secret_entry *e) -+{ -+ grub_list_push(GRUB_AS_LIST_P (&secret_providers), GRUB_AS_LIST (e)); -+} -+ -+void -+grub_cryptodisk_remove_secret_provider (struct grub_secret_entry *e) -+{ -+ grub_list_remove (GRUB_AS_LIST (e)); -+} -+ - #ifdef GRUB_UTIL - #include - grub_err_t -@@ -931,7 +972,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) - { - struct grub_arg_list *state = ctxt->state; - -- if (argc < 1 && !state[1].set && !state[2].set) -+ if (argc < 1 && !state[1].set && !state[2].set && !state[3].set) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); - - have_it = 0; -@@ -949,6 +990,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) - - check_boot = state[2].set; - search_uuid = args[0]; -+ os_passwd = NULL; - grub_device_iterate (&grub_cryptodisk_scan_device, NULL); - search_uuid = NULL; - -@@ -959,11 +1001,37 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) - else if (state[1].set || (argc == 0 && state[2].set)) - { - search_uuid = NULL; -+ os_passwd = NULL; - check_boot = state[2].set; - grub_device_iterate (&grub_cryptodisk_scan_device, NULL); - search_uuid = NULL; - return GRUB_ERR_NONE; - } -+ else if (state[3].set) -+ { -+ struct grub_secret_entry *se; -+ grub_err_t rc; -+ -+ if (argc < 1) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "secret module must be specified"); -+#ifndef GRUB_UTIL -+ grub_dl_load (args[0]); -+#endif -+ se = grub_named_list_find (GRUB_AS_NAMED_LIST (secret_providers), args[0]); -+ if (se == NULL) -+ return grub_error (GRUB_ERR_INVALID_COMMAND, "No secret provider is found"); -+ -+ rc = se->get (args[1], &os_passwd); -+ if (rc) -+ return rc; -+ -+ search_uuid = NULL; -+ grub_device_iterate (&grub_cryptodisk_scan_device, NULL); -+ rc = se->put (args[1], have_it, &os_passwd); -+ os_passwd = NULL; -+ -+ return rc; -+ } - else - { - grub_err_t err; -@@ -974,6 +1042,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) - grub_size_t len; - - search_uuid = NULL; -+ os_passwd = NULL; - check_boot = state[2].set; - diskname = args[0]; - len = grub_strlen (diskname); -@@ -1141,7 +1210,7 @@ GRUB_MOD_INIT (cryptodisk) - { - grub_disk_dev_register (&grub_cryptodisk_dev); - cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0, -- N_("SOURCE|-u UUID|-a|-b"), -+ N_("SOURCE|-u UUID|-a|-b|-s MOD [ID]"), - N_("Mount a crypto device."), options); - grub_procfs_register ("luks_script", &luks_script); - } -diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h -index 33c86ad..6a93c56 100644 ---- a/include/grub/cryptodisk.h -+++ b/include/grub/cryptodisk.h -@@ -160,4 +160,18 @@ grub_util_get_geli_uuid (const char *dev); - grub_cryptodisk_t grub_cryptodisk_get_by_uuid (const char *uuid); - grub_cryptodisk_t grub_cryptodisk_get_by_source_disk (grub_disk_t disk); - -+struct grub_secret_entry { -+ /* as named list */ -+ struct grub_secret_entry *next; -+ struct grub_secret_entry **prev; -+ const char *name; -+ -+ /* additional entries */ -+ grub_err_t (*get)(const char *arg, char **secret); -+ grub_err_t (*put)(const char *arg, int have_it, char **secret); -+}; -+ -+void grub_cryptodisk_add_secret_provider (struct grub_secret_entry *e); -+void grub_cryptodisk_remove_secret_provider (struct grub_secret_entry *e); -+ - #endif --- -2.43.5 - diff --git a/1005-efi-Add-API-for-retrieving-the-EFI-secret-for-crypto.patch b/1005-efi-Add-API-for-retrieving-the-EFI-secret-for-crypto.patch deleted file mode 100644 index cf51219..0000000 --- a/1005-efi-Add-API-for-retrieving-the-EFI-secret-for-crypto.patch +++ /dev/null @@ -1,217 +0,0 @@ -From 9711568e6dce36a6245fada1509e9477c0268e30 Mon Sep 17 00:00:00 2001 -From: James Bottomley -Date: Thu, 31 Dec 2020 09:36:18 -0800 -Subject: [PATCH 3/3] efi: Add API for retrieving the EFI secret for cryptodisk - -cherry-picked from https://lists.gnu.org/archive/html/grub-devel/2020-12/msg00260.html. - -This module is designed to provide an efisecret command which -interrogates the EFI configuration table to find the location of the -confidential computing secret and tries to register the secret with -the cryptodisk. - -The secret is stored in a boot allocated area, usually a page in size. -The layout of the secret injection area is a header - -|GRUB_EFI_SECRET_TABLE_HEADER_GUID|len| - -with entries of the form - -|guid|len|data| - -the guid corresponding to the disk encryption passphrase is -GRUB_EFI_DISKPASSWD_GUID and data must be a zero terminated string. -To get a high entropy string that doesn't need large numbers of -iterations, use a base64 encoding of 33 bytes of random data. - -Signed-off-by: James Bottomley ---- - grub-core/Makefile.core.def | 8 ++ - grub-core/disk/efi/efisecret.c | 129 +++++++++++++++++++++++++++++++++ - include/grub/efi/api.h | 15 ++++ - 3 files changed, 152 insertions(+) - create mode 100644 grub-core/disk/efi/efisecret.c - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 0963e88..aded014 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -774,6 +774,14 @@ module = { - enable = efi; - }; - -+module = { -+ name = efisecret; -+ -+ common = disk/efi/efisecret.c; -+ -+ enable = efi; -+}; -+ - module = { - name = lsefimmap; - -diff --git a/grub-core/disk/efi/efisecret.c b/grub-core/disk/efi/efisecret.c -new file mode 100644 -index 0000000..745eede ---- /dev/null -+++ b/grub-core/disk/efi/efisecret.c -@@ -0,0 +1,129 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+static grub_efi_packed_guid_t secret_guid = GRUB_EFI_SECRET_TABLE_GUID; -+static grub_efi_packed_guid_t tableheader_guid = GRUB_EFI_SECRET_TABLE_HEADER_GUID; -+static grub_efi_packed_guid_t diskpasswd_guid = GRUB_EFI_DISKPASSWD_GUID; -+ -+/* -+ * EFI places the secret in the lower 4GB, so it uses a UINT32 -+ * for the pointer which we have to transform to the correct type -+ */ -+struct efi_secret { -+ grub_uint64_t base; -+ grub_uint64_t size; -+}; -+ -+struct secret_header { -+ grub_efi_packed_guid_t guid; -+ grub_uint32_t len; -+}; -+ -+struct secret_entry { -+ grub_efi_packed_guid_t guid; -+ grub_uint32_t len; -+ char data[0]; -+}; -+ -+static grub_err_t -+grub_efi_secret_put (const char *arg __attribute__((unused)), int have_it, -+ char **ptr) -+{ -+ struct secret_entry *e = (struct secret_entry *)(*ptr - (long)&((struct secret_entry *)0)->data); -+ -+ /* destroy the secret */ -+ grub_memset (e, 0, e->len); -+ *ptr = NULL; -+ -+ if (have_it) -+ return GRUB_ERR_NONE; -+ -+ return grub_error (GRUB_ERR_ACCESS_DENIED, "EFI secret failed to unlock any volumes"); -+} -+ -+static grub_err_t -+grub_efi_secret_find (struct efi_secret *s, char **secret_ptr) -+{ -+ int len; -+ struct secret_header *h; -+ struct secret_entry *e; -+ unsigned char *ptr = (unsigned char *)(unsigned long)s->base; -+ -+ /* the area must be big enough for a guid and a u32 length */ -+ if (s->size < sizeof (*h)) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area is too small"); -+ -+ h = (struct secret_header *)ptr; -+ if (grub_memcmp(&h->guid, &tableheader_guid, sizeof (h->guid))) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area does not start with correct guid\n"); -+ if (h->len < sizeof (*h)) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area is too small\n"); -+ -+ len = h->len - sizeof (*h); -+ ptr += sizeof (*h); -+ -+ while (len >= (int)sizeof (*e)) { -+ e = (struct secret_entry *)ptr; -+ if (e->len < sizeof(*e) || e->len > (unsigned int)len) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area is corrupt\n"); -+ -+ if (! grub_memcmp (&e->guid, &diskpasswd_guid, sizeof (e->guid))) { -+ int end = e->len - sizeof(*e); -+ -+ /* -+ * the passphrase must be a zero terminated string because the -+ * password routines call grub_strlen () to find its size -+ */ -+ if (e->data[end - 1] != '\0') -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area disk encryption password is not zero terminated\n"); -+ -+ *secret_ptr = e->data; -+ return GRUB_ERR_NONE; -+ } -+ ptr += e->len; -+ len -= e->len; -+ } -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret aread does not contain disk decryption password\n"); -+} -+ -+static grub_err_t -+grub_efi_secret_get (const char *arg __attribute__((unused)), char **ptr) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < grub_efi_system_table->num_table_entries; i++) -+ { -+ grub_efi_packed_guid_t *guid = -+ &grub_efi_system_table->configuration_table[i].vendor_guid; -+ -+ if (! grub_memcmp (guid, &secret_guid, sizeof (grub_efi_packed_guid_t))) { -+ struct efi_secret *s = -+ grub_efi_system_table->configuration_table[i].vendor_table; -+ -+ return grub_efi_secret_find(s, ptr); -+ } -+ } -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "No secret found in the EFI configuration table"); -+} -+ -+static struct grub_secret_entry secret = { -+ .name = "efisecret", -+ .get = grub_efi_secret_get, -+ .put = grub_efi_secret_put, -+}; -+ -+GRUB_MOD_INIT(efisecret) -+{ -+ grub_cryptodisk_add_secret_provider (&secret); -+} -+ -+GRUB_MOD_FINI(efisecret) -+{ -+ grub_cryptodisk_remove_secret_provider (&secret); -+} -diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h -index a57187f..d5c805d 100644 ---- a/include/grub/efi/api.h -+++ b/include/grub/efi/api.h -@@ -299,6 +299,21 @@ - { 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ - } - -+#define GRUB_EFI_SECRET_TABLE_GUID \ -+ { 0xadf956ad, 0xe98c, 0x484c, \ -+ { 0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47} \ -+ } -+ -+#define GRUB_EFI_SECRET_TABLE_HEADER_GUID \ -+ { 0x1e74f542, 0x71dd, 0x4d66, \ -+ { 0x96, 0x3e, 0xef, 0x42, 0x87, 0xff, 0x17, 0x3b } \ -+ } -+ -+#define GRUB_EFI_DISKPASSWD_GUID \ -+ { 0x736869e5, 0x84f0, 0x4973, \ -+ { 0x92, 0xec, 0x06, 0x87, 0x9c, 0xe3, 0xda, 0x0b } \ -+ } -+ - #define GRUB_EFI_ACPI_TABLE_GUID \ - { 0xeb9d2d30, 0x2d88, 0x11d3, \ - { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ --- -2.43.5 - diff --git a/1006-Update-patches-in-sync-with-loongarch64.patch b/1006-Update-patches-in-sync-with-loongarch64.patch deleted file mode 100644 index dc39a93..0000000 --- a/1006-Update-patches-in-sync-with-loongarch64.patch +++ /dev/null @@ -1,2815 +0,0 @@ -From 7118e2827e64c205e3b2241b85648f2948cab3a3 Mon Sep 17 00:00:00 2001 -From: Fedora Ninjas -Date: Sat, 22 Mar 2025 16:49:13 +0800 -Subject: [PATCH] Update patches in sync with loongarch64 - ---- - gentpl.py | 2 +- - grub-core/Makefile.am | 1 - - grub-core/Makefile.core.def | 11 +- - grub-core/kern/loongarch64/cache.S | 2 + - grub-core/kern/loongarch64/efi/init.c | 2 - - grub-core/kern/loongarch64/efi/startup.S | 4 +- - grub-core/kern/loongarch64/init.c | 47 -- - grub-core/lib/loongarch64/efi/loongson.c | 119 --- - grub-core/lib/loongarch64/relocator.c | 2 +- - grub-core/lib/loongarch64/setjmp.S | 80 +- - grub-core/loader/loongarch64/linux-efi.c | 143 ++++ - grub-core/loader/loongarch64/linux-elf.c | 910 +++++++++++++++++++++++ - grub-core/loader/loongarch64/linux.c | 731 +++++------------- - include/grub/efi/api.h | 20 + - include/grub/fdt.h | 2 +- - include/grub/loongarch64/asm.h | 10 - - include/grub/loongarch64/efi/loongson.h | 113 --- - include/grub/loongarch64/efi/memory.h | 7 +- - include/grub/loongarch64/efi/time.h | 0 - include/grub/loongarch64/linux.h | 163 +++- - include/grub/loongarch64/time.h | 12 - - 21 files changed, 1487 insertions(+), 894 deletions(-) - delete mode 100644 grub-core/kern/loongarch64/init.c - delete mode 100644 grub-core/lib/loongarch64/efi/loongson.c - create mode 100644 grub-core/loader/loongarch64/linux-efi.c - create mode 100644 grub-core/loader/loongarch64/linux-elf.c - delete mode 100644 include/grub/loongarch64/asm.h - delete mode 100644 include/grub/loongarch64/efi/loongson.h - delete mode 100644 include/grub/loongarch64/efi/time.h - -diff --git a/gentpl.py b/gentpl.py -index 3afd642..fa7f1ba 100644 ---- a/gentpl.py -+++ b/gentpl.py -@@ -78,7 +78,7 @@ GROUPS["terminfomodule"] = GRUB_PLATFORMS[:]; - for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) - - # Flattened Device Trees (FDT) --GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi" ] -+GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi", "loongarch64_efi" ] - - # Needs software helpers for division - # Must match GRUB_DIVISION_IN_SOFTWARE in misc.h -diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am -index a976fad..ec771c5 100644 ---- a/grub-core/Makefile.am -+++ b/grub-core/Makefile.am -@@ -227,7 +227,6 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdt.h --KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loongson.h - endif - - if COND_powerpc_ieee1275 -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index aded014..b89e58e 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -250,6 +250,9 @@ kernel = { - arm64_efi = kern/arm64/efi/init.c; - arm64_efi = kern/efi/fdt.c; - -+ loongarch64_efi = kern/loongarch64/efi/init.c; -+ loongarch64_efi = kern/efi/fdt.c; -+ - i386_pc = kern/i386/pc/init.c; - i386_pc = kern/i386/pc/mmap.c; - i386_pc = term/i386/pc/console.c; -@@ -300,14 +303,8 @@ kernel = { - extra_dist = video/sis315_init.c; - mips_loongson = commands/keylayouts.c; - -- loongarch64 = kern/loongarch64/init.c; - loongarch64 = kern/loongarch64/dl.c; - loongarch64 = kern/loongarch64/cache.S; -- loongarch64 = kern/generic/rtc_get_time_ms.c; -- loongarch64 = kern/efi/fdt.c; -- loongarch64 = lib/fdt.c; -- loongarch64_efi = kern/loongarch64/efi/init.c; -- loongarch64_efi = lib/loongarch64/efi/loongson.c; - - powerpc_ieee1275 = kern/powerpc/cache.S; - powerpc_ieee1275 = kern/powerpc/dl.c; -@@ -1767,6 +1764,8 @@ module = { - i386_pc = lib/i386/pc/vesa_modes_table.c; - mips = loader/mips/linux.c; - loongarch64 = loader/loongarch64/linux.c; -+ loongarch64 = loader/loongarch64/linux-elf.c; -+ loongarch64 = loader/loongarch64/linux-efi.c; - powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c; - sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c; - ia64_efi = loader/ia64/efi/linux.c; -diff --git a/grub-core/kern/loongarch64/cache.S b/grub-core/kern/loongarch64/cache.S -index d291c67..b268261 100644 ---- a/grub-core/kern/loongarch64/cache.S -+++ b/grub-core/kern/loongarch64/cache.S -@@ -19,6 +19,8 @@ - #include - - FUNCTION (grub_arch_sync_caches) -+ ibar 0 -+ dbar 0 - jr $ra - - FUNCTION (grub_arch_sync_dma_caches) -diff --git a/grub-core/kern/loongarch64/efi/init.c b/grub-core/kern/loongarch64/efi/init.c -index 632c39a..15c41aa 100644 ---- a/grub-core/kern/loongarch64/efi/init.c -+++ b/grub-core/kern/loongarch64/efi/init.c -@@ -1,4 +1,3 @@ --/* init.c - initialize an arm-based EFI system */ - /* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2013 Free Software Foundation, Inc. -@@ -24,7 +23,6 @@ - #include - #include - #include --#include - - static grub_uint64_t tmr; - static grub_efi_event_t tmr_evt; -diff --git a/grub-core/kern/loongarch64/efi/startup.S b/grub-core/kern/loongarch64/efi/startup.S -index 1ffff08..00ecd15 100644 ---- a/grub-core/kern/loongarch64/efi/startup.S -+++ b/grub-core/kern/loongarch64/efi/startup.S -@@ -19,8 +19,9 @@ - #include - - .file "startup.S" -- .text - .globl start, _start -+ .text -+ - .align 4 - - FUNCTION(start) -@@ -42,4 +43,3 @@ FUNCTION(_start) - ld.d $ra, $sp, 0 - addi.d $sp, $sp, 16 - jr $ra -- -diff --git a/grub-core/kern/loongarch64/init.c b/grub-core/kern/loongarch64/init.c -deleted file mode 100644 -index b2de930..0000000 ---- a/grub-core/kern/loongarch64/init.c -+++ /dev/null -@@ -1,47 +0,0 @@ --/* -- * GRUB -- GRand Unified Bootloader -- * Copyright (C) 2009,2017 Free Software Foundation, Inc. -- * -- * GRUB is free software: you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation, either version 3 of the License, or -- * (at your option) any later version. -- * -- * GRUB is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with GRUB. If not, see . -- */ -- --#include --#include --#include --#include -- --grub_uint32_t grub_arch_cpuclock; -- --/* FIXME: use interrupt to count high. */ --grub_uint64_t --grub_get_rtc (void) --{ -- static grub_uint32_t high = 0; -- static grub_uint32_t last = 0; -- grub_uint32_t low; -- -- asm volatile ("csrrd %0, " GRUB_CPU_LOONGARCH_COP0_TIMER_COUNT : "=r" (low)); -- if (low < last) -- high++; -- last = low; -- -- return (((grub_uint64_t) high) << 32) | low; --} -- --void --grub_timer_init (grub_uint32_t cpuclock) --{ -- grub_arch_cpuclock = cpuclock; -- grub_install_get_time_ms (grub_rtc_get_time_ms); --} -diff --git a/grub-core/lib/loongarch64/efi/loongson.c b/grub-core/lib/loongarch64/efi/loongson.c -deleted file mode 100644 -index eda1e1c..0000000 ---- a/grub-core/lib/loongarch64/efi/loongson.c -+++ /dev/null -@@ -1,119 +0,0 @@ --/* -- * GRUB -- GRand Unified Bootloader -- * Copyright (C) 2017 Free Software Foundation, Inc. -- * -- * GRUB is free software: you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation, either version 3 of the License, or -- * (at your option) any later version. -- * -- * GRUB is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with GRUB. If not, see . -- */ -- --#include --#include --#include --#include --#include --#include -- --unsigned long --grub_efi_get_bpi_version (const char *str) --{ -- unsigned long version = GRUB_EFI_BPI_VER_NONE; -- -- version = grub_strtoul (str + 4, 0, 0); -- -- return version; --} -- --void * --grub_efi_loongson_get_boot_params (void) --{ -- static void * boot_params = NULL; -- grub_efi_configuration_table_t *tables; -- grub_efi_guid_t loongson_bpi_guid = GRUB_EFI_LOONGSON_BPI_TABLE_GUID; -- unsigned int i; -- -- if (boot_params) -- return boot_params; -- -- /* Look for Loongson boot params interface in UEFI config tables. */ -- tables = grub_efi_system_table->configuration_table; -- -- for (i = 0; i < grub_efi_system_table->num_table_entries; i++) -- if (grub_memcmp (&tables[i].vendor_guid, &loongson_bpi_guid, sizeof (loongson_bpi_guid)) == 0) -- { -- boot_params= tables[i].vendor_table; -- grub_dprintf ("loongson", "found registered BPI @ %p\n", boot_params); -- break; -- } -- return boot_params; --} -- --grub_uint8_t --grub_efi_loongson_calculatesum8 (const grub_uint8_t *buffer, grub_efi_uintn_t length) --{ -- grub_uint8_t sum; -- grub_efi_uintn_t count; -- -- for (sum = 0, count = 0; count < length; count++) -- { -- sum = (grub_uint8_t) (sum + *(buffer + count)); -- } -- return sum; --} -- --grub_uint8_t --grub_efi_loongson_grub_calculatechecksum8 (const grub_uint8_t *buffer, grub_efi_uintn_t length) --{ -- grub_uint8_t checksum; -- -- checksum = grub_efi_loongson_calculatesum8(buffer, length); -- -- return (grub_uint8_t) (0x100 - checksum); --} -- -- --grub_uint32_t --grub_efi_loongson_memmap_v1_sort(struct memmap_v1 array[], grub_uint32_t length, -- mem_map_v1 * bpmem, grub_uint32_t index, grub_uint32_t memtype) --{ -- grub_uint64_t tempmemsize = 0; -- grub_uint32_t j = 0; -- grub_uint32_t t = 0; -- -- for(j = 0; j < length;) -- { -- tempmemsize = array[j].memsize; -- for(t = j + 1; t < length; t++) -- { -- if(array[j].memstart + tempmemsize == array[t].memstart) -- { -- tempmemsize += array[t].memsize; -- } -- else -- { -- break; -- } -- } -- bpmem->map[index].memtype = memtype; -- bpmem->map[index].memstart = array[j].memstart; -- bpmem->map[index].memsize = tempmemsize; -- grub_dprintf("loongson", "v1 map[%d]:type %x, start 0x%lx, end 0x%lx\n", -- index, -- bpmem->map[index].memtype, -- bpmem->map[index].memstart, -- bpmem->map[index].memstart+ bpmem->map[index].memsize -- ); -- j = t; -- index++; -- } -- return index; --} -diff --git a/grub-core/lib/loongarch64/relocator.c b/grub-core/lib/loongarch64/relocator.c -index 4b253ca..7217b68 100644 ---- a/grub-core/lib/loongarch64/relocator.c -+++ b/grub-core/lib/loongarch64/relocator.c -@@ -122,7 +122,7 @@ grub_relocator64_boot (struct grub_relocator *rel, - unsigned i; - grub_addr_t vtarget; - -- err = grub_relocator_alloc_chunk_align (rel, &ch, 0, -+ err = grub_relocator_alloc_chunk_align (rel, &ch, 0x3000000, - (0xffffffff - stateset_size) - + 1, stateset_size, - grub_relocator_align, -diff --git a/grub-core/lib/loongarch64/setjmp.S b/grub-core/lib/loongarch64/setjmp.S -index 47db814..bb09959 100644 ---- a/grub-core/lib/loongarch64/setjmp.S -+++ b/grub-core/lib/loongarch64/setjmp.S -@@ -1,6 +1,6 @@ - /* - * GRUB -- GRand Unified Bootloader -- * Copyright (C) 2003,2007,2009 Free Software Foundation, Inc. -+ * Copyright (C) 2021 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -16,9 +16,7 @@ - * along with GRUB. If not, see . - */ - --#include - #include --#include - - .file "setjmp.S" - -@@ -27,48 +25,44 @@ GRUB_MOD_LICENSE "GPLv3+" - .text - - /* -- * int grub_setjmp (grub_jmp_buf env) -+ * int grub_setjmp (jmp_buf env) - */ - FUNCTION(grub_setjmp) -- GRUB_ASM_REG_S $s0, $a0,0 -- GRUB_ASM_REG_S $s1, $a0,8 -- GRUB_ASM_REG_S $s2, $a0,16 -- GRUB_ASM_REG_S $s3, $a0,24 -- GRUB_ASM_REG_S $s4, $a0,32 -- GRUB_ASM_REG_S $s5, $a0,40 -- GRUB_ASM_REG_S $s6, $a0,48 -- GRUB_ASM_REG_S $s7, $a0,56 -- GRUB_ASM_REG_S $s8, $a0,64 -- GRUB_ASM_REG_S $fp, $a0,72 -- GRUB_ASM_REG_S $sp, $a0,80 -- GRUB_ASM_REG_S $ra, $a0,88 -- move $v0, $zero -- move $v1, $zero -- jr $ra -- nop -+ st.d $s0, $a0, 0x0 -+ st.d $s1, $a0, 0x8 -+ st.d $s2, $a0, 0x10 -+ st.d $s3, $a0, 0x18 -+ st.d $s4, $a0, 0x20 -+ st.d $s5, $a0, 0x28 -+ st.d $s6, $a0, 0x30 -+ st.d $s7, $a0, 0x38 -+ st.d $s8, $a0, 0x40 -+ st.d $fp, $a0, 0x48 -+ st.d $sp, $a0, 0x50 -+ st.d $ra, $a0, 0x58 -+ -+ move $a0, $zero -+ jr $ra -+ - /* -- * int grub_longjmp (grub_jmp_buf env, int val) -+ * void grub_longjmp (jmp_buf env, int val) - */ - FUNCTION(grub_longjmp) -- GRUB_ASM_REG_L $s0, $a0,0 -- GRUB_ASM_REG_L $s1, $a0,8 -- GRUB_ASM_REG_L $s2, $a0,16 -- GRUB_ASM_REG_L $s3, $a0,24 -- GRUB_ASM_REG_L $s4, $a0,32 -- GRUB_ASM_REG_L $s5, $a0,40 -- GRUB_ASM_REG_L $s6, $a0,48 -- GRUB_ASM_REG_L $s7, $a0,56 -- GRUB_ASM_REG_L $s8, $a0,64 -- GRUB_ASM_REG_L $fp, $a0,72 -- GRUB_ASM_REG_L $sp, $a0,80 -- GRUB_ASM_REG_L $ra, $a0,88 -- addi.w $v0, $zero, 1 -- /* -- * replace: movn $v0, $a1, $a1 -- */ -- bnez $a1, .ZW0 -- addi.d $v0, $a1, 0 --.ZW0: -- addi.d $v1,$zero,0 -- jr $ra -- nop -+ ld.d $s0, $a0, 0x0 -+ ld.d $s1, $a0, 0x8 -+ ld.d $s2, $a0, 0x10 -+ ld.d $s3, $a0, 0x18 -+ ld.d $s4, $a0, 0x20 -+ ld.d $s5, $a0, 0x28 -+ ld.d $s6, $a0, 0x30 -+ ld.d $s7, $a0, 0x38 -+ ld.d $s8, $a0, 0x40 -+ ld.d $fp, $a0, 0x48 -+ ld.d $sp, $a0, 0x50 -+ ld.d $ra, $a0, 0x58 -+ -+ li.w $a0, 1 -+ beqz $a1, .L0 -+ move $a0, $a1 -+.L0: -+ jr $ra -diff --git a/grub-core/loader/loongarch64/linux-efi.c b/grub-core/loader/loongarch64/linux-efi.c -new file mode 100644 -index 0000000..6f5ff15 ---- /dev/null -+++ b/grub-core/loader/loongarch64/linux-efi.c -@@ -0,0 +1,143 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2021 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define GRUB_EFI_PE_MAGIC 0x5A4D -+ -+grub_err_t -+finalize_efi_params_linux (struct linux_loongarch64_kernel_params *kernel_params) -+{ -+ int node, retval; -+ -+ void *fdt; -+ -+ fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE); -+ -+ if (!fdt) -+ goto failure; -+ -+ node = grub_fdt_find_subnode (fdt, 0, "chosen"); -+ if (node < 0) -+ node = grub_fdt_add_subnode (fdt, 0, "chosen"); -+ -+ if (node < 1) -+ goto failure; -+ -+ /* Set initrd info */ -+ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) -+ { -+ grub_dprintf ("linux", "Initrd @ %p-%p\n", -+ (void *) kernel_params->ramdisk_addr, -+ (void *) (kernel_params->ramdisk_addr + kernel_params->ramdisk_size)); -+ -+ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start", -+ kernel_params->ramdisk_addr); -+ if (retval) -+ goto failure; -+ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end", -+ kernel_params->ramdisk_addr + kernel_params->ramdisk_size); -+ if (retval) -+ goto failure; -+ } -+ -+ if (grub_fdt_install() != GRUB_ERR_NONE) -+ goto failure; -+ -+ return GRUB_ERR_NONE; -+ -+failure: -+ grub_fdt_unload(); -+ return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); -+} -+ -+grub_err_t -+grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh) -+{ -+ if ((lh->code0 & 0xffff) == GRUB_EFI_PE_MAGIC) -+ return GRUB_ERR_NONE; -+ else -+ return 1; -+ -+ grub_dprintf ("linux", "UEFI stub kernel:\n"); -+ grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset); -+ -+ return GRUB_ERR_NONE; -+} -+ -+grub_err_t -+grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args) -+{ -+ grub_efi_memory_mapped_device_path_t *mempath; -+ grub_efi_handle_t image_handle; -+ grub_efi_boot_services_t *b; -+ grub_efi_status_t status; -+ grub_efi_loaded_image_t *loaded_image; -+ int len; -+ -+ mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t)); -+ if (!mempath) -+ return grub_errno; -+ -+ mempath[0].header.type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE; -+ mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE; -+ mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath)); -+ mempath[0].memory_type = GRUB_EFI_LOADER_DATA; -+ mempath[0].start_address = addr; -+ mempath[0].end_address = addr + size; -+ -+ mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE; -+ mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; -+ mempath[1].header.length = sizeof (grub_efi_device_path_t); -+ -+ b = grub_efi_system_table->boot_services; -+ status = b->load_image (0, grub_efi_image_handle, -+ (grub_efi_device_path_t *) mempath, -+ (void *) addr, size, &image_handle); -+ if (status != GRUB_EFI_SUCCESS) -+ return grub_error (GRUB_ERR_BAD_OS, "cannot load image"); -+ -+ grub_dprintf ("linux", "linux command line: '%s'\n", args); -+ -+ /* Convert command line to UCS-2 */ -+ loaded_image = grub_efi_get_loaded_image (image_handle); -+ loaded_image->load_options_size = len = -+ (grub_strlen (args) + 1) * sizeof (grub_efi_char16_t); -+ loaded_image->load_options = -+ grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size)); -+ if (!loaded_image->load_options) -+ return grub_errno; -+ -+ loaded_image->load_options_size = -+ 2 * grub_utf8_to_utf16 (loaded_image->load_options, len, -+ (grub_uint8_t *) args, len, NULL); -+ -+ grub_dprintf ("linux", "starting image %p\n", image_handle); -+ status = b->start_image (image_handle, 0, NULL); -+ -+ /* When successful, not reached */ -+ b->unload_image (image_handle); -+ grub_efi_free_pages ((grub_addr_t) loaded_image->load_options, -+ GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size)); -+ -+ return grub_errno; -+} -diff --git a/grub-core/loader/loongarch64/linux-elf.c b/grub-core/loader/loongarch64/linux-elf.c -new file mode 100644 -index 0000000..d54028e ---- /dev/null -+++ b/grub-core/loader/loongarch64/linux-elf.c -@@ -0,0 +1,910 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2021 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define GRUB_EFI_MMAP_NR_SLACK_SLOTS 8 -+ -+#define GRUB_ADDRESS_TYPE_SYSRAM 1 -+#define GRUB_ADDRESS_TYPE_RESERVED 2 -+#define GRUB_ADDRESS_TYPE_ACPI 3 -+#define GRUB_ADDRESS_TYPE_NVS 4 -+#define GRUB_ADDRESS_TYPE_PMEM 5 -+ -+#define GRUB_EFI_LOONGSON_BPI_TABLE_GUID \ -+ { 0x4660f721, 0x2ec5, 0x416a, \ -+ { 0x89, 0x9a, 0x43, 0x18, 0x02, 0x50, 0xa0, 0xc9 } \ -+ } -+ -+#define GRUB_EFI_LARCH_SCREEN_INFO_GUID \ -+ { 0x07fd51a6, 0X9532, 0X926f, \ -+ { 0X51, 0Xdc, 0X6a, 0X63, 0X60, 0X2f, 0X84, 0Xb4 } \ -+ } -+ -+#define GRUB_EFI_SCREEN_INFO_GUID \ -+ { 0xe03fc20a, 0x85dc, 0x406e, \ -+ { 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95 } \ -+ } -+ -+static struct grub_relocator *relocator; -+static grub_efi_guid_t compat_screen_info_guid = GRUB_EFI_LARCH_SCREEN_INFO_GUID; -+static grub_efi_guid_t screen_info_guid = GRUB_EFI_SCREEN_INFO_GUID; -+ -+void grub_linux_loongarch_elf_relocator_unload (void) -+{ -+ grub_relocator_unload (relocator); -+} -+ -+static void find_bits(unsigned long mask, grub_efi_uint8_t *pos, grub_efi_uint8_t *size) -+{ -+ grub_efi_uint8_t first, len; -+ -+ first = 0; -+ len = 0; -+ -+ if (mask) { -+ while (!(mask & 0x1)) { -+ mask = mask >> 1; -+ first++; -+ } -+ -+ while (mask & 0x1) { -+ mask = mask >> 1; -+ len++; -+ } -+ } -+ -+ *pos = first; -+ *size = len; -+} -+ -+static void -+setup_pixel_info(struct screen_info *si, grub_efi_uint32_t pixels_per_scan_line, -+ struct grub_efi_gop_pixel_bitmask pixel_info, int pixel_format) -+{ -+ if (pixel_format == GRUB_EFI_GOT_RGBA8) { -+ si->lfb_depth = 32; -+ si->lfb_linelength = pixels_per_scan_line * 4; -+ si->red_size = 8; -+ si->red_pos = 0; -+ si->green_size = 8; -+ si->green_pos = 8; -+ si->blue_size = 8; -+ si->blue_pos = 16; -+ si->rsvd_size = 8; -+ si->rsvd_pos = 24; -+ } else if (pixel_format == GRUB_EFI_GOT_BGRA8) { -+ si->lfb_depth = 32; -+ si->lfb_linelength = pixels_per_scan_line * 4; -+ si->red_size = 8; -+ si->red_pos = 16; -+ si->green_size = 8; -+ si->green_pos = 8; -+ si->blue_size = 8; -+ si->blue_pos = 0; -+ si->rsvd_size = 8; -+ si->rsvd_pos = 24; -+ } else if (pixel_format == GRUB_EFI_GOT_BITMASK) { -+ find_bits(pixel_info.r, &si->red_pos, &si->red_size); -+ find_bits(pixel_info.g, &si->green_pos, -+ &si->green_size); -+ find_bits(pixel_info.b, &si->blue_pos, &si->blue_size); -+ find_bits(pixel_info.a, &si->rsvd_pos, -+ &si->rsvd_size); -+ si->lfb_depth = si->red_size + si->green_size + -+ si->blue_size + si->rsvd_size; -+ si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8; -+ } else { -+ si->lfb_depth = 4; -+ si->lfb_linelength = si->lfb_width / 2; -+ si->red_size = 0; -+ si->red_pos = 0; -+ si->green_size = 0; -+ si->green_pos = 0; -+ si->blue_size = 0; -+ si->blue_pos = 0; -+ si->rsvd_size = 0; -+ si->rsvd_pos = 0; -+ } -+} -+ -+static struct screen_info *alloc_screen_info(void) -+{ -+ grub_efi_status_t status; -+ grub_efi_boot_services_t *b; -+ struct screen_info *si; -+ -+ b = grub_efi_system_table->boot_services; -+ status = efi_call_3 (b->allocate_pool, GRUB_EFI_RUNTIME_SERVICES_DATA, -+ sizeof(*si), (void**)&si); -+ if (status != GRUB_EFI_SUCCESS) -+ return NULL; -+ -+ grub_memset ((void *)si, 0, sizeof(struct screen_info)); -+ -+ status = b->install_configuration_table (&compat_screen_info_guid, si); -+ if (status != GRUB_EFI_SUCCESS) -+ goto free_mem; -+ -+ status = b->install_configuration_table (&screen_info_guid, si); -+ if (status == GRUB_EFI_SUCCESS) { -+ return si; -+ } -+ -+free_table: -+ b->install_configuration_table (&compat_screen_info_guid, NULL); -+free_mem: -+ efi_call_1 (b->free_pool, si); -+ -+ return NULL; -+} -+ -+static struct screen_info *setup_screen_info(void) -+{ -+ grub_efi_boot_services_t *b; -+ grub_efi_handle_t gop_handle; -+ struct screen_info *si = NULL; -+ struct grub_efi_gop *gop, *first_gop; -+ grub_efi_handle_t *handles; -+ grub_efi_uintn_t num_handles, i; -+ grub_efi_guid_t graphics_output_guid = GRUB_EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; -+ grub_efi_uint16_t width, height; -+ grub_efi_uint32_t ext_lfb_base, pixels_per_scan_line; -+ grub_efi_uint64_t fb_base; -+ struct grub_efi_gop_pixel_bitmask pixel_info; -+ grub_efi_gop_pixel_format_t pixel_format; -+ -+ si = alloc_screen_info(); -+ if (!si) -+ return NULL; -+ -+ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, -+ &graphics_output_guid, NULL, &num_handles); -+ if (!handles || num_handles == 0) -+ goto free_screen_info; -+ -+ gop = NULL; -+ first_gop = NULL; -+ -+ for (i = 0; i < num_handles; i++) -+ { -+ struct grub_efi_gop_mode *mode; -+ struct grub_efi_gop_mode_info *info = NULL; -+ grub_efi_guid_t conout_proto = GRUB_EFI_CONSOLE_OUT_DEVICE_GUID; -+ void *dummy = NULL; -+ grub_efi_uint8_t conout_found = 0; -+ grub_efi_uint64_t current_fb_base; -+ -+ gop_handle = handles[i]; -+ gop = grub_efi_open_protocol (gop_handle, &graphics_output_guid, -+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); -+ -+ dummy = grub_efi_open_protocol (gop_handle, &conout_proto, -+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); -+ if (dummy != NULL) -+ conout_found = 1; -+ -+ mode = gop->mode; -+ info = mode->info; -+ current_fb_base = mode->fb_base; -+ -+ if ((!first_gop || conout_found) && -+ info->pixel_format != GRUB_EFI_GOT_BLT_ONLY) { -+ /* -+ * Systems that use the UEFI Console Splitter may -+ * provide multiple GOP devices, not all of which are -+ * backed by real hardware. The workaround is to search -+ * for a GOP implementing the ConOut protocol, and if -+ * one isn't found, to just fall back to the first GOP. -+ */ -+ width = info->width; -+ height = info->height; -+ pixel_format = info->pixel_format; -+ pixel_info = info->pixel_bitmask; -+ pixels_per_scan_line = info->pixels_per_scanline; -+ fb_base = current_fb_base; -+ -+ /* -+ * Once we've found a GOP supporting ConOut, -+ * don't bother looking any further. -+ */ -+ first_gop = gop; -+ if (conout_found) -+ break; -+ } -+ } -+ -+ /* Did we find any GOPs? */ -+ if (!first_gop) -+ goto free_screen_info; -+ -+ /* EFI framebuffer */ -+ si->orig_video_isVGA = GRUB_VIDEO_TYPE_EFI; -+ -+ si->lfb_width = width; -+ si->lfb_height = height; -+ si->lfb_base = fb_base; -+ grub_dprintf ("loongson", "Screen info fb base: 0x%"PRIxGRUB_UINT32_T"\n", si->lfb_base); -+ -+ ext_lfb_base = (grub_uint64_t)fb_base >> 32; -+ if (ext_lfb_base) { -+ si->capabilities |= GRUB_VIDEO_CAPABILITY_64BIT_BASE; -+ si->ext_lfb_base = ext_lfb_base; -+ } -+ si->pages = 1; -+ -+ setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format); -+ -+ si->lfb_size = si->lfb_linelength * si->lfb_height; -+ si->capabilities |= GRUB_VIDEO_CAPABILITY_SKIP_QUIRKS; -+ -+ return si; -+ -+free_screen_info: -+ b = grub_efi_system_table->boot_services; -+ b->install_configuration_table (&compat_screen_info_guid, NULL); -+ b->install_configuration_table (&screen_info_guid, NULL); -+ if (si) -+ efi_call_1 (b->free_pool, si); -+ -+ grub_dprintf ("loongson", "No screen info\n"); -+ return NULL; -+} -+ -+static grub_err_t -+allocate_memmap_and_exit_boot (struct linux_loongarch64_kernel_params *kernel_params) -+{ -+ grub_err_t err; -+ grub_efi_status_t status; -+ grub_efi_uintn_t mmap_size, desc_size, size; -+ grub_efi_uint32_t desc_version; -+ grub_efi_memory_descriptor_t *mmap_buf; -+ grub_efi_boot_services_t *b; -+ struct efi_boot_memmap *m, tmp; -+ struct efi_initrd *tbl = NULL; -+ grub_efi_guid_t boot_memmap_guid = GRUB_EFI_BOOT_MEMMAP_GUID; -+ grub_efi_guid_t initrd_media_guid = GRUB_EFI_INITRD_MEDIA_GUID; -+ -+ setup_screen_info(); -+ -+ b = grub_efi_system_table->boot_services; -+ -+ grub_dprintf ("loongson", "ramdisk_addr:0x%"PRIxGRUB_UINT64_T", \ -+ size:0x%"PRIxGRUB_UINT64_T"\n", -+ kernel_params->ramdisk_addr, -+ kernel_params->ramdisk_size); -+#if 0 -+ char string[64]; -+ -+ /* Set initrd info to cmdline*/ -+ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) -+ { -+ grub_printf ( "Initrd @ %p-%p\n", -+ (void *) kernel_params->ramdisk_addr, -+ (void *) (kernel_params->ramdisk_addr + kernel_params->ramdisk_size)); -+ /* initrd */ -+ grub_snprintf (string, -+ sizeof (GRUB_INITRD_STRING), -+ "initrd=0x%lx,0x%lx", -+ ((grub_uint64_t) kernel_params->ramdisk_addr & 0xffffffff), -+ (grub_uint64_t) kernel_params->ramdisk_size); -+ *(char*) ((grub_addr_t) kernel_params->linux_args + kernel_params->ramdisk_args_len - 2) = ' '; -+ grub_memcpy ((char*) ((grub_addr_t) kernel_params->linux_args + kernel_params->ramdisk_args_len - 1), -+ string, sizeof (GRUB_INITRD_STRING)); -+ } -+#else -+ /* Set initrd info to system table*/ -+ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) -+ { -+ tbl = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (sizeof(struct efi_initrd))); -+ if (!tbl) -+ return grub_error (GRUB_ERR_IO, "cannot allocate tbl memory"); -+ tbl->base = kernel_params->ramdisk_addr; -+ tbl->size = kernel_params->ramdisk_size; -+ -+ status = b->install_configuration_table (&initrd_media_guid, tbl); -+ if (status != GRUB_EFI_SUCCESS) { -+ grub_error (GRUB_ERR_IO, "failed to install initrd media"); -+ goto free_tbl; -+ } -+ } -+#endif -+ -+ tmp.map_size = 0; -+ status = grub_efi_get_memory_map (&tmp.map_size, NULL, &tmp.map_key, -+ &tmp.desc_size, &tmp.desc_ver); -+ if (status != 0) { -+ grub_error (GRUB_ERR_IO, "cannot get memory map"); -+ goto uninstall_initrd_table; -+ } -+ size = tmp.map_size + tmp.desc_size * GRUB_EFI_MMAP_NR_SLACK_SLOTS; -+ m = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (sizeof(*m) + size)); -+ if (!m) { -+ grub_error (GRUB_ERR_IO, "cannot allocate m memory"); -+ goto uninstall_initrd_table; -+ } -+ -+ status = b->install_configuration_table (&boot_memmap_guid, m); -+ if (status != GRUB_EFI_SUCCESS) { -+ grub_error (GRUB_ERR_IO, "failed to install boot memmap"); -+ goto free_m; -+ } -+ -+ m->buff_size = m->map_size = size; -+ if (grub_efi_get_memory_map (&m->map_size, m->map, -+ &m->map_key, &m->desc_size, -+ &m->desc_ver) <= 0) -+ { -+ grub_error (GRUB_ERR_IO, "cannot get EFI memory map"); -+ goto uninstall_mem_table; -+ } -+ -+ mmap_size = grub_efi_find_mmap_size (); -+ if (! mmap_size) -+ goto uninstall_mem_table; -+ -+ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); -+ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, -+ &desc_size, &desc_version); -+ if (err) { -+ grub_error (GRUB_ERR_IO, "failed to finish boot services"); -+ goto free_map; -+ } -+ -+ return 0; -+ -+free_map: -+ if (mmap_buf) -+ grub_efi_free_pages ((grub_addr_t) mmap_buf, -+ GRUB_EFI_BYTES_TO_PAGES (mmap_size)); -+ -+uninstall_mem_table: -+ b->install_configuration_table (&boot_memmap_guid, NULL); -+ -+free_m: -+ if (m) -+ grub_efi_free_pages ((grub_addr_t) m, -+ GRUB_EFI_BYTES_TO_PAGES (sizeof(*m) + size)); -+ -+uninstall_initrd_table: -+ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) -+ b->install_configuration_table (&initrd_media_guid, NULL); -+ -+free_tbl: -+ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) { -+ if (tbl) -+ grub_efi_free_pages ((grub_addr_t) tbl, -+ GRUB_EFI_BYTES_TO_PAGES (sizeof(struct efi_initrd))); -+ } -+ -+ return grub_error(GRUB_ERR_BAD_OS, "failed to V40 boot"); -+} -+ -+static grub_err_t -+allocate_fdt_and_exit_boot (struct linux_loongarch64_kernel_params *kernel_params) -+{ -+ int node, retval; -+ grub_err_t err; -+ unsigned int size; -+ grub_efi_uintn_t mmap_size; -+ grub_efi_uintn_t desc_size; -+ grub_efi_uint32_t desc_version; -+ grub_efi_memory_descriptor_t *mmap_buf; -+ -+ size = GRUB_FDT_EMPTY_TREE_SZ + FDT_ADDR_SIZE_EXTRA + GRUB_EFI_LINUX_FDT_EXTRA_SPACE; -+ -+ kernel_params->fdt = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (size)); -+ if (!kernel_params->fdt) -+ return GRUB_ERR_OUT_OF_MEMORY; -+ -+ grub_fdt_create_empty_tree (kernel_params->fdt, size); -+ grub_fdt_set_prop32 (kernel_params->fdt, 0, FDT_ADDR_CELLS_STRING, 2); -+ grub_fdt_set_prop32 (kernel_params->fdt, 0, FDT_SIZE_CELLS_STRING, 2); -+ -+ node = grub_fdt_find_subnode (kernel_params->fdt, 0, "chosen"); -+ if (node < 0) -+ node = grub_fdt_add_subnode (kernel_params->fdt, 0, "chosen"); -+ if (node < 1) -+ goto failure; -+ -+ grub_dprintf ("loongson", "command_line %s, len %ld\n", (char *)kernel_params->linux_args, -+ grub_strlen(kernel_params->linux_args) + 1); -+ if ((kernel_params->linux_args != NULL) && (grub_strlen(kernel_params->linux_args) > 0)) { -+ retval = grub_fdt_set_prop (kernel_params->fdt, node, "bootargs", kernel_params->linux_args, -+ grub_strlen(kernel_params->linux_args) + 1); -+ if (retval) -+ goto failure; -+ } -+ -+ /* Set initrd info */ -+ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) -+ { -+ grub_dprintf ("linux", "Initrd @ %p-%p\n", -+ (void *) kernel_params->ramdisk_addr, -+ (void *) (kernel_params->ramdisk_addr + kernel_params->ramdisk_size)); -+ -+ retval = grub_fdt_set_prop64 (kernel_params->fdt, node, "linux,initrd-start", -+ kernel_params->ramdisk_addr); -+ if (retval) -+ goto failure; -+ retval = grub_fdt_set_prop64 (kernel_params->fdt, node, "linux,initrd-end", -+ (kernel_params->ramdisk_addr + kernel_params->ramdisk_size)); -+ if (retval) -+ goto failure; -+ } -+ -+ node = grub_fdt_find_subnode (kernel_params->fdt, 0, "chosen"); -+ retval = grub_fdt_set_prop64 (kernel_params->fdt, node, "linux,uefi-system-table", -+ (grub_uint64_t)grub_efi_system_table); -+ if (retval) -+ goto failure; -+ -+ mmap_size = grub_efi_find_mmap_size (); -+ if (! mmap_size) -+ return grub_errno; -+ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); -+ if (! mmap_buf) -+ return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); -+ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, -+ &desc_size, &desc_version); -+ if (err) -+ return err; -+ -+ if (!mmap_buf || !mmap_size || !desc_size) -+ return GRUB_ERR_BAD_ARGUMENT; -+ -+ retval = grub_fdt_set_prop64 (kernel_params->fdt, node, "linux,uefi-mmap-start", -+ (grub_uint64_t)mmap_buf); -+ if (retval) -+ goto failure; -+ -+ retval = grub_fdt_set_prop32 (kernel_params->fdt, node, "linux,uefi-mmap-size", -+ mmap_size); -+ if (retval) -+ goto failure; -+ -+ retval = grub_fdt_set_prop32 (kernel_params->fdt, node, "linux,uefi-mmap-desc-size", -+ desc_size); -+ if (retval) -+ goto failure; -+ -+ retval = grub_fdt_set_prop32 (kernel_params->fdt, node, "linux,uefi-mmap-desc-ver", -+ desc_version); -+ if (retval) -+ goto failure; -+ -+ return GRUB_ERR_NONE; -+ -+failure: -+ if (!kernel_params->fdt) { -+ return GRUB_ERR_BAD_OS; -+ } -+ grub_efi_free_pages ((grub_addr_t) kernel_params->fdt, -+ GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (kernel_params->fdt))); -+ kernel_params->fdt = NULL; -+ return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); -+} -+ -+static void -+grub_linux_loongarch_elf_make_argv (struct linux_loongarch64_kernel_params *kernel_params) -+{ -+ static void* linux_args_addr; -+ int size; -+ grub_uint64_t *linux_argv; -+ char *args, *p, *linux_args; -+ int i, argc; -+ grub_err_t err; -+ -+ argc = kernel_params->linux_argc; -+ args = kernel_params->linux_args; -+ -+ /* new size */ -+ p = args; -+ size = (argc + 3 + 1) * sizeof (grub_uint64_t); /* orig arguments */ -+ for (i = 0; i < argc; i++) -+ { -+ size += ALIGN_UP (grub_strlen (p) + 1, 4); -+ p += grub_strlen (p) + 1; -+ } -+ -+ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) -+ { -+ size += ALIGN_UP (sizeof (GRUB_RD_START_STRING), 4) \ -+ + ALIGN_UP (sizeof (GRUB_RD_SIZE_STRING), 4) \ -+ + ALIGN_UP (sizeof (GRUB_INITRD_STRING), 4); -+ } -+ size = ALIGN_UP (size, 8); -+ -+ /* alloc memory */ -+ linux_args_addr = grub_linux_loongarch_alloc_virtual_mem_align (size, 8, &err); -+ -+ linux_argv = linux_args_addr; -+ linux_args = (char *)(linux_argv + (argc + 1 + 3)); -+ p = args; -+ for (i = 0; i < argc; i++) -+ { -+ grub_memcpy (linux_args, p, grub_strlen (p) + 1); -+ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; -+ linux_argv++; -+ linux_args += ALIGN_UP (grub_strlen (p) + 1, 4); -+ p += grub_strlen (p) + 1; -+ } -+ -+ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) -+ { -+ /* rd_start */ -+ grub_snprintf (linux_args, -+ sizeof (GRUB_RD_START_STRING), -+ "rd_start=0x%lx", -+ (grub_uint64_t) kernel_params->ramdisk_addr); -+ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; -+ linux_argv++; -+ linux_args += ALIGN_UP (sizeof (GRUB_RD_START_STRING), 4); -+ kernel_params->linux_argc++; -+ -+ /* rd_size */ -+ grub_snprintf (linux_args, -+ sizeof (GRUB_RD_SIZE_STRING), -+ "rd_size=0x%lx", -+ (grub_uint64_t) kernel_params->ramdisk_size); -+ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; -+ linux_argv++; -+ linux_args += ALIGN_UP (sizeof (GRUB_RD_SIZE_STRING), 4); -+ kernel_params->linux_argc++; -+ -+ /* initrd */ -+ grub_snprintf (linux_args, -+ sizeof (GRUB_INITRD_STRING), -+ "initrd=0x%lx,0x%lx", -+ ((grub_uint64_t) kernel_params->ramdisk_addr & 0xffffffff), -+ (grub_uint64_t) kernel_params->ramdisk_size); -+ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; -+ linux_argv++; -+ linux_args += ALIGN_UP (sizeof (GRUB_INITRD_STRING), 4); -+ kernel_params->linux_argc++; -+ } -+ -+ /* Reserve space for initrd arguments. */ -+ *linux_argv = 0; -+ -+ grub_free (kernel_params->linux_args); -+ kernel_params->linux_argv = (grub_addr_t) linux_args_addr; -+} -+ -+grub_err_t -+grub_linux_loongarch_elf_linux_boot_image (struct linux_loongarch64_kernel_params -+ *kernel_params) -+{ -+ struct boot_params_interface *boot_params = NULL; -+ struct grub_relocator64_state state; -+ grub_err_t err; -+ -+ /* linux kernel type is ELF */ -+ grub_memset (&state, 0, sizeof (state)); -+ -+ state.jumpreg = 1; -+ state.gpr[1] = kernel_params->kernel_addr; /* ra */ -+ if (grub_linux_loongarch_elf_get_boot_params (&boot_params) == 0) -+ { -+ grub_dprintf ("loongson", "V40 boot\n"); -+ if (allocate_memmap_and_exit_boot(kernel_params) != GRUB_ERR_NONE) -+ return grub_errno; -+ state.gpr[4] = 1 << FLAGS_EFI_SUPPORT_BIT; /* a0 = flag */ -+ state.gpr[5] = (grub_uint64_t)kernel_params->linux_args; /* a1 = cmdline */ -+ state.gpr[6] = (grub_uint64_t)grub_efi_system_table; /* a2 = system_table */ -+ } else { -+ grub_dprintf ("loongson", "BPI boot\n"); -+ grub_linux_loongarch_elf_make_argv (kernel_params); -+ state.gpr[4] = kernel_params->linux_argc; /* a0 = argc */ -+ state.gpr[5] = kernel_params->linux_argv; /* a1 = args */ -+ state.gpr[6] = (grub_uint64_t) boot_params; /* a2 = envp */ -+ err = grub_linux_loongarch_elf_boot_params (boot_params); -+ if (err) -+ return err; -+ } -+ -+ /* Boot the ELF kernel */ -+ grub_relocator64_boot (relocator, state); -+ -+ return GRUB_ERR_NONE; -+} -+ -+void* -+grub_linux_loongarch_alloc_virtual_mem_addr (grub_addr_t addr, -+ grub_size_t size, -+ grub_err_t *err) -+{ -+ relocator = grub_relocator_new (); -+ if (!relocator) -+ return NULL; -+ -+ grub_relocator_chunk_t ch; -+ *err = grub_relocator_alloc_chunk_addr (relocator, &ch, -+ grub_vtop ((void *) addr), -+ size); -+ if (*err) -+ return NULL; -+ return get_virtual_current_address (ch); -+} -+ -+void* -+grub_linux_loongarch_alloc_virtual_mem_align (grub_size_t size, -+ grub_size_t align, -+ grub_err_t *err) -+{ -+ grub_relocator_chunk_t ch; -+ -+ *err = grub_relocator_alloc_chunk_align (relocator, &ch, -+ 0x3000000, (0xffffffff - size) + 1, -+ size, align, -+ GRUB_RELOCATOR_PREFERENCE_LOW, 0); -+ return get_virtual_current_address (ch); -+} -+ -+void* -+grub_linux_loongarch_alloc_initrd_mem_align (grub_size_t size, -+ grub_size_t align, -+ grub_err_t *err) -+{ -+ grub_relocator_chunk_t ch; -+ -+ /* Firstly try to allocate from memory higher than 256MB */ -+ *err = grub_relocator_alloc_chunk_align (relocator, &ch, -+ 0x10000000, (0xffffffff - size) + 1, size, align, -+ GRUB_RELOCATOR_PREFERENCE_LOW, 0); -+ if (*err != GRUB_ERR_NONE) -+ { -+ /* Failed, try to allocate in range 0 ~ 256MB */ -+ *err = grub_relocator_alloc_chunk_align (relocator, &ch, -+ 0, (0xfffffff - size) + 1, size, align, -+ GRUB_RELOCATOR_PREFERENCE_HIGH, 0); -+ } -+ return get_virtual_current_address (ch); -+} -+ -+int -+grub_linux_loongarch_elf_get_boot_params (struct boot_params_interface **boot_params) -+{ -+ grub_efi_configuration_table_t *tables; -+ grub_efi_guid_t bpi_guid = GRUB_EFI_LOONGSON_BPI_TABLE_GUID; -+ unsigned int i; -+ int found = 0; -+ -+ /* Look for Loongson BPI in UEFI config tables. */ -+ tables = grub_efi_system_table->configuration_table; -+ -+ for (i = 0; i < grub_efi_system_table->num_table_entries; i++) -+ if (grub_memcmp (&tables[i].vendor_guid, &bpi_guid, sizeof (bpi_guid)) == 0) -+ { -+ *boot_params = tables[i].vendor_table; -+ char *p = (char*) &((*boot_params)->signature); -+ if (grub_strncmp (p, "BPI", 3) == 0) -+ { -+ found = 1; -+ break; -+ } -+ } -+ return found; -+} -+ -+static grub_uint8_t -+grub_kernel_update_checksum (const grub_uint8_t *buffer, grub_efi_uintn_t length) -+{ -+ grub_uint8_t sum; -+ grub_efi_uintn_t count; -+ -+ for (sum = 0, count = 0; count < length; count++) -+ { -+ sum = (grub_uint8_t) (sum + *(buffer + count)); -+ } -+ -+ return (grub_uint8_t) (0x100 - sum); -+} -+ -+static grub_uint32_t -+grub_efi_loongarch64_memmap_sort (struct memmap array[], -+ grub_uint32_t length, -+ struct loongsonlist_mem_map* bpmem, -+ grub_uint32_t index, -+ grub_uint32_t memtype) -+{ -+ grub_uint64_t tempmemsize = 0; -+ grub_uint32_t j = 0; -+ grub_uint32_t t = 0; -+ -+ for(j = 0; j < length;) -+ { -+ tempmemsize = array[j].mem_size; -+ for(t = j + 1; t < length; t++) -+ { -+ if(array[j].mem_start + tempmemsize == array[t].mem_start) -+ { -+ tempmemsize += array[t].mem_size; -+ } -+ else -+ { -+ break; -+ } -+ } -+ bpmem->map[index].mem_type = memtype; -+ bpmem->map[index].mem_start = array[j].mem_start; -+ bpmem->map[index].mem_size = tempmemsize; -+ grub_dprintf ("loongson", "map[%d]:type %"PRIuGRUB_UINT32_T", start 0x%" -+ PRIxGRUB_UINT64_T", end 0x%"PRIxGRUB_UINT64_T"\n", -+ index, -+ bpmem->map[index].mem_type, -+ bpmem->map[index].mem_start, -+ bpmem->map[index].mem_start+ bpmem->map[index].mem_size -+ ); -+ j = t; -+ index++; -+ } -+ return index; -+} -+ -+grub_err_t -+grub_linux_loongarch_elf_boot_params (struct boot_params_interface *boot_params) -+{ -+ grub_int8_t checksum = 0; -+ grub_err_t err; -+ -+ struct loongsonlist_mem_map *loongson_mem_map = NULL; -+ struct _extention_list_hdr * listpointer = NULL; -+ grub_uint32_t tmp_index = 0; -+ grub_efi_memory_descriptor_t * lsdesc = NULL; -+ -+ grub_uint32_t free_index = 0; -+ grub_uint32_t reserve_index = 0; -+ grub_uint32_t acpi_table_index = 0; -+ grub_uint32_t acpi_nvs_index = 0; -+ -+ grub_efi_uintn_t mmap_size; -+ grub_efi_uintn_t desc_size; -+ grub_efi_memory_descriptor_t *mmap_buf; -+ -+ struct memmap reserve_mem[GRUB_LOONGSON3_BOOT_MEM_MAP_MAX]; -+ struct memmap free_mem[GRUB_LOONGSON3_BOOT_MEM_MAP_MAX]; -+ struct memmap acpi_table_mem[GRUB_LOONGSON3_BOOT_MEM_MAP_MAX]; -+ struct memmap acpi_nvs_mem[GRUB_LOONGSON3_BOOT_MEM_MAP_MAX]; -+ -+ grub_memset (reserve_mem, 0, sizeof(struct memmap) * GRUB_LOONGSON3_BOOT_MEM_MAP_MAX); -+ grub_memset (free_mem, 0, sizeof(struct memmap) * GRUB_LOONGSON3_BOOT_MEM_MAP_MAX); -+ grub_memset (acpi_table_mem, 0, sizeof(struct memmap) * GRUB_LOONGSON3_BOOT_MEM_MAP_MAX); -+ grub_memset (acpi_nvs_mem, 0, sizeof(struct memmap) * GRUB_LOONGSON3_BOOT_MEM_MAP_MAX); -+ -+ /* Check extlist headers */ -+ listpointer = boot_params->extlist; -+ for( ;listpointer != NULL; listpointer = listpointer->next) -+ { -+ char *pl= (char *)&(listpointer->signature); -+ if(grub_strncmp(pl, "MEM", 3) == 0) -+ { -+ loongson_mem_map = (struct loongsonlist_mem_map *)listpointer; -+ break; -+ } -+ } -+ -+ mmap_size = grub_efi_find_mmap_size (); -+ if (! mmap_size) -+ return grub_errno; -+ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); -+ if (! mmap_buf) -+ return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); -+ -+ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, -+ &desc_size, NULL); -+ if (err) -+ return err; -+ -+ if (!mmap_buf || !mmap_size || !desc_size) -+ return -1; -+ -+ /* -+ According to UEFI SPEC,mmap_buf is the accurate Memory Map array \ -+ now we can fill platform specific memory structure. -+ */ -+ for (lsdesc = mmap_buf; lsdesc < (grub_efi_memory_descriptor_t *)((char *)mmap_buf + mmap_size); -+ lsdesc = (grub_efi_memory_descriptor_t *)((char *)lsdesc + desc_size)) -+ { -+ /* System RAM */ -+ if((lsdesc->type != GRUB_EFI_ACPI_RECLAIM_MEMORY) && \ -+ (lsdesc->type != GRUB_EFI_ACPI_MEMORY_NVS) && \ -+ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_DATA) && \ -+ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_CODE) && \ -+ (lsdesc->type != GRUB_EFI_RESERVED_MEMORY_TYPE) && \ -+ (lsdesc->type != GRUB_EFI_PAL_CODE)) -+ { -+ free_mem[free_index].mem_type = GRUB_ADDRESS_TYPE_SYSRAM; -+ free_mem[free_index].mem_start = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; -+ free_mem[free_index].mem_size = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; -+ free_index++; -+ -+ /*ACPI*/ -+ }else if((lsdesc->type == GRUB_EFI_ACPI_RECLAIM_MEMORY)){ -+ acpi_table_mem[acpi_table_index].mem_type = GRUB_ADDRESS_TYPE_ACPI; -+ acpi_table_mem[acpi_table_index].mem_start = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; -+ acpi_table_mem[acpi_table_index].mem_size = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; -+ acpi_table_index++; -+ }else if((lsdesc->type == GRUB_EFI_ACPI_MEMORY_NVS)){ -+ acpi_nvs_mem[acpi_nvs_index].mem_type = GRUB_ADDRESS_TYPE_NVS; -+ acpi_nvs_mem[acpi_nvs_index].mem_start = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; -+ acpi_nvs_mem[acpi_nvs_index].mem_size = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; -+ acpi_nvs_index++; -+ -+ /* Reserve */ -+ }else{ -+ reserve_mem[reserve_index].mem_type = GRUB_ADDRESS_TYPE_RESERVED; -+ reserve_mem[reserve_index].mem_start = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; -+ reserve_mem[reserve_index].mem_size = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; -+ reserve_index++; -+ } -+ } -+ -+ tmp_index = loongson_mem_map->map_count; -+ /*System RAM Sort*/ -+ tmp_index = grub_efi_loongarch64_memmap_sort(free_mem, -+ free_index, -+ loongson_mem_map, -+ tmp_index, -+ GRUB_ADDRESS_TYPE_SYSRAM); -+ /*ACPI Sort*/ -+ tmp_index = grub_efi_loongarch64_memmap_sort(acpi_table_mem, -+ acpi_table_index, -+ loongson_mem_map, -+ tmp_index, -+ GRUB_ADDRESS_TYPE_ACPI); -+ tmp_index = grub_efi_loongarch64_memmap_sort(acpi_nvs_mem, -+ acpi_nvs_index, -+ loongson_mem_map, -+ tmp_index, -+ GRUB_ADDRESS_TYPE_NVS); -+ -+ /*Reserve Sort*/ -+ { -+ grub_uint64_t loongarch_addr; -+ asm volatile ("csrrd %0, 0x181" : "=r" (loongarch_addr)); -+ if ((loongarch_addr & 0xff00000000000000) == 0x9000000000000000) -+ tmp_index = grub_efi_loongarch64_memmap_sort(reserve_mem, -+ reserve_index, -+ loongson_mem_map, -+ tmp_index, -+ GRUB_ADDRESS_TYPE_RESERVED); -+ else -+ tmp_index = grub_efi_loongarch64_memmap_sort(reserve_mem, -+ reserve_index, -+ loongson_mem_map, -+ tmp_index, -+ GRUB_ADDRESS_TYPE_RESERVED + 1); -+ } -+ loongson_mem_map->map_count = tmp_index; -+ loongson_mem_map->header.checksum = 0; -+ -+ checksum = grub_kernel_update_checksum ((grub_uint8_t *) loongson_mem_map, -+ loongson_mem_map->header.length); -+ loongson_mem_map->header.checksum = checksum; -+ -+ return grub_errno; -+} -diff --git a/grub-core/loader/loongarch64/linux.c b/grub-core/loader/loongarch64/linux.c -index 7594ca2..8dae4fe 100644 ---- a/grub-core/loader/loongarch64/linux.c -+++ b/grub-core/loader/loongarch64/linux.c -@@ -1,7 +1,6 @@ --/* linux.c - boot Linux */ - /* - * GRUB -- GRand Unified Bootloader -- * Copyright (C) 2003,2004,2005,2007,2009,2010,2017 Free Software Foundation, Inc. -+ * Copyright (C) 2021 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -17,346 +16,76 @@ - * along with GRUB. If not, see . - */ - --#include --#include --#include --#include - #include --#include --#include - #include - #include --#include --#include --#include --#include - #include - #include - #include --#include -+#include - #include - - GRUB_MOD_LICENSE ("GPLv3+"); - --#pragma GCC diagnostic ignored "-Wcast-align" -- --typedef unsigned long size_t; -+#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024) - --#define FDT_ADDR_CELLS_STRING "#address-cells" --#define FDT_SIZE_CELLS_STRING "#size-cells" --#define FDT_ADDR_SIZE_EXTRA ((2 * grub_fdt_prop_entry_size (sizeof(grub_uint32_t))) + \ -- sizeof (FDT_ADDR_CELLS_STRING) + \ -- sizeof (FDT_SIZE_CELLS_STRING)) -+static struct linux_loongarch64_kernel_params kernel_params; - -+static grub_addr_t phys_addr; - static grub_dl_t my_mod; - static int loaded; --static int initrd_loaded = 0; --static grub_size_t linux_size; -- --static struct grub_relocator *relocator; --static grub_addr_t target_addr, entry_addr; --static int linux_argc; --static grub_uint8_t *linux_args_addr; --static grub_off_t rd_addr_arg_off, rd_size_arg_off, initrd_addr_arg_off; -- --static void *fdt; --static int is_fdt_boot; --static grub_addr_t initrd_start, initrd_end; --static char *fdt_linux_args; -+static int is_bpi_boot; -+static int grub_loongarch_linux_type = GRUB_LOONGARCH_LINUX_BAD; - - static grub_err_t --allocate_fdt_and_exit_boot (void) -+grub_linux_boot (void) - { -- int node, retval; -- grub_err_t err; -- unsigned int size; -- grub_efi_uintn_t mmap_size; -- grub_efi_uintn_t desc_size; -- grub_efi_uint32_t desc_version; -- grub_efi_memory_descriptor_t *mmap_buf; -- -- size = GRUB_FDT_EMPTY_TREE_SZ + FDT_ADDR_SIZE_EXTRA + GRUB_EFI_LINUX_FDT_EXTRA_SPACE; -- -- fdt = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (size)); -- if (!fdt) -- return GRUB_ERR_OUT_OF_MEMORY; -- -- grub_fdt_create_empty_tree (fdt, size); -- grub_fdt_set_prop32 (fdt, 0, FDT_ADDR_CELLS_STRING, 2); -- grub_fdt_set_prop32 (fdt, 0, FDT_SIZE_CELLS_STRING, 2); -- -- node = grub_fdt_find_subnode (fdt, 0, "chosen"); -- if (node < 0) -- node = grub_fdt_add_subnode (fdt, 0, "chosen"); -- if (node < 1) -- goto failure; -- -- grub_dprintf ("loongson", "command_line %s, len %ld\n", -- fdt_linux_args, grub_strlen(fdt_linux_args) + 1); -- if ((fdt_linux_args != NULL) && (grub_strlen(fdt_linux_args) > 0)) { -- retval = grub_fdt_set_prop (fdt, node, "bootargs", fdt_linux_args, -- grub_strlen(fdt_linux_args) + 1); -- if (retval) -- goto failure; -- } - -- /* Set initrd info */ -- if (initrd_start && initrd_end > initrd_start) -- { -- grub_dprintf ("linux", "Initrd @ %p-%p\n", -- (void *) initrd_start, (void *) initrd_end); -- -- retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start", -- initrd_start); -- if (retval) -- goto failure; -- retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end", -- initrd_end); -- if (retval) -- goto failure; -+ if (grub_loongarch_linux_type == GRUB_LOONGARCH_LINUX_EFI) { -+ if (finalize_efi_params_linux (&kernel_params) != GRUB_ERR_NONE) -+ return grub_errno; -+ return (grub_arch_efi_linux_boot_image((grub_addr_t) kernel_params.kernel_addr, -+ kernel_params.kernel_size, -+ kernel_params.linux_args)); - } -- -- node = grub_fdt_find_subnode (fdt, 0, "chosen"); -- retval = grub_fdt_set_prop64 (fdt, node, "linux,uefi-system-table", -- (grub_uint64_t)grub_efi_system_table); -- if (retval) -- goto failure; -- -- mmap_size = grub_efi_find_mmap_size (); -- if (! mmap_size) -- return grub_errno; -- mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); -- if (! mmap_buf) -- return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); -- err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, -- &desc_size, &desc_version); -- if (err) -- return err; -- -- if (!mmap_buf || !mmap_size || !desc_size) -- return GRUB_ERR_BAD_ARGUMENT; -- -- retval = grub_fdt_set_prop64 (fdt, node, "linux,uefi-mmap-start", -- (grub_uint64_t)mmap_buf); -- if (retval) -- goto failure; -- -- retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-size", -- mmap_size); -- if (retval) -- goto failure; -- -- retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-desc-size", -- desc_size); -- if (retval) -- goto failure; -- -- retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-desc-ver", -- desc_version); -- if (retval) -- goto failure; -- -- return GRUB_ERR_NONE; -- --failure: -- if (!fdt) { -- return GRUB_ERR_BAD_OS; -+ if (grub_loongarch_linux_type == GRUB_LOONGARCH_LINUX_ELF) { -+ return grub_linux_loongarch_elf_linux_boot_image (&kernel_params); - } -- grub_efi_free_pages ((grub_addr_t) fdt, -- GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt))); -- fdt = NULL; -- return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); --} -- --static grub_err_t --allocate_boot_params_and_exit_boot (void) --{ -- grub_efi_uintn_t mmap_size; -- grub_efi_uintn_t desc_size; -- grub_efi_uint32_t desc_version; -- grub_efi_memory_descriptor_t *mmap_buf; -- grub_efi_memory_descriptor_t * lsdesc = NULL; -- grub_err_t err; -- struct boot_params_interface * boot_params; -- mem_map_v1 * mem_map_v1_table = NULL; -- unsigned long bpi_version = 0; -- grub_int8_t checksum = 0; -- grub_uint32_t tmp_index = 0; -- grub_uint32_t free_index = 0; -- grub_uint32_t reserve_index = 0; -- grub_uint32_t acpi_table_index = 0; -- grub_uint32_t acpi_nvs_index = 0; -- -- struct memmap_v1 reserve_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; -- struct memmap_v1 free_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; -- struct memmap_v1 acpi_table_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; -- struct memmap_v1 acpi_nvs_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; -- -- grub_memset(reserve_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); -- grub_memset(free_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); -- grub_memset(acpi_table_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); -- grub_memset(acpi_nvs_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); -- -- boot_params = (struct boot_params_interface *)grub_efi_loongson_get_boot_params(); -- -- ext_list * listpointer = NULL; -- /* Check extlist headers */ -- listpointer = boot_params->extlist; -- for( ;listpointer != NULL; listpointer = listpointer->next) -- { -- char *pl= (char *)&(listpointer->signature); -- if(grub_strncmp(pl, "MEM", 3) == 0) -- { -- mem_map_v1_table = (mem_map_v1 *)listpointer; -- break; -- } -- } -- -- mmap_size = grub_efi_find_mmap_size (); -- if (! mmap_size) -- return grub_errno; -- mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); -- if (! mmap_buf) -- return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); -- err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, -- &desc_size, &desc_version); -- if (err) -- return err; -- -- if (!mmap_buf || !mmap_size || !desc_size) -- return GRUB_ERR_BAD_ARGUMENT; -- -- char *p = (char *)&(boot_params->signature); -- bpi_version = grub_efi_get_bpi_version(p); -- grub_dprintf("loongson", "get bpi version:%ld\n", bpi_version); -- -- if (bpi_version <= GRUB_EFI_BPI_VER_V2) -- { -- /* -- According to UEFI SPEC,mmap_buf is the accurate Memory Map array \ -- now we can fill platform specific memory structure. -- */ -- for(lsdesc = mmap_buf; lsdesc < (grub_efi_memory_descriptor_t *)((char *)mmap_buf + mmap_size); -- lsdesc = (grub_efi_memory_descriptor_t *)((char *)lsdesc + desc_size)) -- { -- grub_dprintf("loongson", "type:%d, phy_start:0x%lx, phy_end:0x%lx\n", lsdesc->type, -- lsdesc->physical_start, lsdesc->physical_start + lsdesc->num_pages * GRUB_EFI_PAGE_SIZE); -- -- /* System RAM */ -- if ((lsdesc->type != GRUB_EFI_ACPI_RECLAIM_MEMORY) && \ -- (lsdesc->type != GRUB_EFI_ACPI_MEMORY_NVS) && \ -- (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_DATA) && \ -- (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_CODE) && \ -- (lsdesc->type != GRUB_EFI_RESERVED_MEMORY_TYPE) && \ -- (lsdesc->type != GRUB_EFI_PAL_CODE)) -- { -- free_mem_v1[free_index].memtype = GRUB_EFI_LOONGSON_SYSTEM_RAM; -- free_mem_v1[free_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; -- free_mem_v1[free_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; -- free_index++; -- -- /*ACPI*/ -- } else if ((lsdesc->type == GRUB_EFI_ACPI_RECLAIM_MEMORY)){ -- acpi_table_mem_v1[acpi_table_index].memtype = GRUB_EFI_LOONGSON_ACPI_TABLE; -- acpi_table_mem_v1[acpi_table_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; -- acpi_table_mem_v1[acpi_table_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; -- acpi_table_index++; -- } else if ((lsdesc->type == GRUB_EFI_ACPI_MEMORY_NVS)){ -- acpi_nvs_mem_v1[acpi_nvs_index].memtype = GRUB_EFI_LOONGSON_ACPI_NVS; -- acpi_nvs_mem_v1[acpi_nvs_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; -- acpi_nvs_mem_v1[acpi_nvs_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; -- acpi_nvs_index++; -- -- /* Reserve */ -- } else { -- reserve_mem_v1[reserve_index].memtype = GRUB_EFI_LOONGSON_MEMORY_RESERVED; -- reserve_mem_v1[reserve_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; -- reserve_mem_v1[reserve_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; -- reserve_index++; -- } -- } -- -- tmp_index = mem_map_v1_table->mapcount; -- /*System RAM Sort*/ -- tmp_index = grub_efi_loongson_memmap_v1_sort(free_mem_v1, free_index, mem_map_v1_table, -- tmp_index, GRUB_EFI_LOONGSON_SYSTEM_RAM); -- /*ACPI Sort*/ -- tmp_index = grub_efi_loongson_memmap_v1_sort(acpi_table_mem_v1, acpi_table_index, -- mem_map_v1_table, tmp_index, GRUB_EFI_LOONGSON_ACPI_TABLE); -- tmp_index = grub_efi_loongson_memmap_v1_sort(acpi_nvs_mem_v1, acpi_nvs_index, -- mem_map_v1_table, tmp_index, GRUB_EFI_LOONGSON_ACPI_NVS); -- /*Reserve Sort*/ -- { -- grub_uint64_t loongarch_addr; -- asm volatile ("csrrd %0, 0x181" : "=r" (loongarch_addr)); -- if ((loongarch_addr & 0xff00000000000000) == 0x9000000000000000) -- tmp_index = grub_efi_loongson_memmap_v1_sort(reserve_mem_v1, reserve_index, -- mem_map_v1_table, tmp_index, -- GRUB_EFI_LOONGSON_MEMORY_RESERVED); -- else -- tmp_index = grub_efi_loongson_memmap_v1_sort(reserve_mem_v1, reserve_index, -- mem_map_v1_table, tmp_index, -- GRUB_EFI_LOONGSON_MEMORY_RESERVED + 1); -- } -- mem_map_v1_table->mapcount = tmp_index; -- mem_map_v1_table->header.checksum = 0; -- -- checksum = grub_efi_loongson_grub_calculatechecksum8((grub_uint8_t *)mem_map_v1_table, -- mem_map_v1_table->header.length); -- mem_map_v1_table->header.checksum = checksum; -- } - - return GRUB_ERR_NONE; - } - - static grub_err_t --grub_linux_boot (void) -+grub_linux_unload (void) - { -- struct grub_relocator64_state state; -- -- grub_memset (&state, 0, sizeof (state)); -- -- /* Boot the kernel. */ -- state.gpr[1] = entry_addr; -- grub_dprintf("loongson", "entry_addr is 0x%lx\n", state.gpr[1]); - -- if (is_fdt_boot == 1) -- { -- if (allocate_fdt_and_exit_boot () != GRUB_ERR_NONE) -- return grub_errno; -+ if (grub_loongarch_linux_type == GRUB_LOONGARCH_LINUX_EFI) { -+ if (kernel_params.ramdisk_addr) -+ grub_efi_free_pages ((grub_efi_physical_address_t) kernel_params.ramdisk_addr, -+ GRUB_EFI_BYTES_TO_PAGES (kernel_params.ramdisk_size)); -+ kernel_params.ramdisk_size = 0; - -- state.gpr[4] = 1 << FLAGS_EFI_SUPPORT_BIT; -- state.gpr[5] = (grub_uint64_t)fdt; -- state.gpr[6] = 0; -- } else { -- state.gpr[4] = linux_argc; -- state.gpr[5] = (grub_addr_t) linux_args_addr; -- state.gpr[6] = (grub_uint64_t)grub_efi_loongson_get_boot_params(); -- -- if (allocate_boot_params_and_exit_boot () != GRUB_ERR_NONE) -- return grub_errno; -+ if (kernel_params.kernel_addr) -+ grub_efi_free_pages ((grub_addr_t) kernel_params.kernel_addr, -+ GRUB_EFI_BYTES_TO_PAGES (kernel_params.kernel_size)); -+ kernel_params.kernel_addr = 0; - } -- grub_dprintf("loongson", "gpr[4]:%ld, gpr[5]:0x%lx, gpr[6]:0x%lx\n", -- state.gpr[4], state.gpr[5], state.gpr[6]); - -- state.jumpreg = 1; -- grub_relocator64_boot (relocator, state); -- -- return GRUB_ERR_NONE; --} -+ if (grub_loongarch_linux_type == GRUB_LOONGARCH_LINUX_ELF) { -+ grub_free (kernel_params.linux_args); -+ kernel_params.linux_args = 0; -+ grub_linux_loongarch_elf_relocator_unload (); -+ } - --static grub_err_t --grub_linux_unload (void) --{ -- grub_relocator_unload (relocator); - grub_dl_unref (my_mod); - loaded = 0; -+ grub_loongarch_linux_type = GRUB_LOONGARCH_LINUX_BAD; - - return GRUB_ERR_NONE; - } - --static grub_err_t --grub_linux_load64 (grub_elf_t elf, const char *filename) -+grub_err_t -+grub_linux_loongarch_elf_load_kernel (grub_elf_t elf, const char *filename) - { - Elf64_Addr base; - grub_err_t err; -@@ -365,16 +94,14 @@ grub_linux_load64 (grub_elf_t elf, const char *filename) - int flag; - - /* Linux's entry point incorrectly contains a virtual address. */ -- entry_addr = elf->ehdr.ehdr64.e_entry; -- grub_dprintf("loongson", "entry address = 0x%lx\n", entry_addr); -+ kernel_params.kernel_addr = elf->ehdr.ehdr64.e_entry; -+ kernel_params.kernel_size = grub_elf64_size (elf, &base, 0); - -- linux_size = grub_elf64_size (elf, &base, 0); -- grub_dprintf("loongson", "base = 0x%lx\n", base); -- -- if (linux_size == 0) -+ if (kernel_params.kernel_size == 0) - return grub_errno; -- target_addr = base; -- linux_size = ALIGN_UP (base + linux_size - base, 8); -+ -+ phys_addr = base; -+ kernel_params.kernel_size = ALIGN_UP (base + kernel_params.kernel_size - base, 8); - - asm volatile ("csrrd %0, 0x181" : "=r" (addr)); - if (addr & 0x1) { -@@ -382,157 +109,163 @@ grub_linux_load64 (grub_elf_t elf, const char *filename) - } else { - flag = GRUB_ELF_LOAD_FLAGS_30BITS; - base &= ~ELF64_LOADMASK; -- entry_addr &= ~ELF64_LOADMASK; -+ kernel_params.kernel_addr &= ~ELF64_LOADMASK; - } - -- relocator = grub_relocator_new (); -- if (!relocator) -- return grub_errno; -- -- { -- grub_relocator_chunk_t ch; -- err = grub_relocator_alloc_chunk_addr (relocator, &ch, -- grub_vtop ((void *) target_addr), -- linux_size); -- if (err) -- return err; -- playground = get_virtual_current_address (ch); -- } -+ playground = grub_linux_loongarch_alloc_virtual_mem_addr (phys_addr, -+ kernel_params.kernel_size, -+ &err); -+ if (playground == NULL) -+ return err; - - /* Now load the segments into the area we claimed. */ -- return grub_elf64_load (elf, filename, playground - base, flag, 0, 0); -+ return grub_elf64_load (elf, filename, playground - base, -+ flag, 0, 0); - } - - static grub_err_t - grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) - { -- grub_elf_t elf = 0; -+ grub_file_t file = 0; -+ struct linux_arch_kernel_header lh; -+ struct boot_params_interface *boot_params = NULL; -+ grub_elf_t elf = NULL; - grub_err_t err; -- int args_size = 0; -+ grub_size_t cmdline_size; -+ int i; - - grub_dl_ref (my_mod); - -- if (argc == 0) -- { -- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -- } -- -- elf = grub_elf_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL); -- if (! elf) -- return grub_errno; -+ /* Release the previously used memory. */ -+ grub_loader_unset (); - -- if (elf->ehdr.ehdr64.e_type != ET_EXEC) -+ if (argc == 0) - { -- grub_elf_close (elf); -- return grub_error (GRUB_ERR_UNKNOWN_OS, -- N_("this ELF file is not of the right type")); -+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -+ goto fail; - } - -- /* Release the previously used memory. */ -- grub_loader_unset (); -- loaded = 0; -- -- if (grub_elf_is_elf64 (elf)) -- err = grub_linux_load64 (elf, argv[0]); -- else -- err = grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic")); -+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL); -+ if (!file) -+ goto fail; - -- grub_elf_close (elf); -+ kernel_params.kernel_size = grub_file_size (file); -+ grub_dprintf ("linux", "kernel file size: %" PRIuGRUB_SIZE "\n", -+ kernel_params.kernel_size); - -- if (err) -- return err; -+ if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh)) -+ return grub_errno; - -- if (grub_efi_loongson_get_boot_params() == NULL) { -- grub_size_t cmdline_size; -+ if (grub_arch_efi_linux_check_image (&lh) == GRUB_ERR_NONE) { -+ grub_loongarch_linux_type = GRUB_LOONGARCH_LINUX_EFI; -+ } - -- is_fdt_boot = 1; -- cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); -- fdt_linux_args = grub_malloc (cmdline_size); -- if (!fdt_linux_args) -+ if (grub_loongarch_linux_type != GRUB_LOONGARCH_LINUX_EFI) { -+ elf = grub_elf_file (file, argv[0]); -+ if (elf != NULL) - { -- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); -- goto fail; -+ /* linux kernel type is ELF */ -+ grub_loongarch_linux_type = GRUB_LOONGARCH_LINUX_ELF; -+ if (elf->ehdr.ehdr64.e_type != ET_EXEC) -+ { -+ grub_error (GRUB_ERR_UNKNOWN_OS, -+ N_("this ELF file is not of the right type")); -+ goto fail; -+ } -+ if (elf->ehdr.ehdr64.e_machine != EM_LOONGARCH64) -+ { -+ grub_error (GRUB_ERR_BAD_OS, "invalid magic number"); -+ goto fail; -+ } -+ -+ if (grub_elf_is_elf64 (elf)) -+ { -+ err = grub_linux_loongarch_elf_load_kernel (elf, argv[0]); -+ if (err) -+ goto fail; -+ } else { -+ grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic")); -+ goto fail; -+ } -+ grub_dprintf ("linux", "kernel @ %p\n", (void*) elf->ehdr.ehdr64.e_entry); - } -- grub_memcpy (fdt_linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); -- err = grub_create_loader_cmdline (argc, argv, -- fdt_linux_args + sizeof (LINUX_IMAGE) - 1, -- cmdline_size, -- GRUB_VERIFY_KERNEL_CMDLINE); -- if (err) -- goto fail; -- grub_dprintf("loongson", "fdt linux args:%s\n", -- fdt_linux_args + sizeof (LINUX_IMAGE) - 1); -- - } else { -- int i; -- grub_uint64_t *linux_argv; -- char *linux_args; -- -- is_fdt_boot = 0; -- /* For arguments. */ -- linux_argc = argc; -- /* Main arguments. */ -- args_size = (linux_argc) * sizeof (grub_uint64_t); -- /* Initrd address/size and initrd */ -- args_size += 3 * sizeof (grub_uint64_t); -- /* NULL terminator. */ -- args_size += sizeof (grub_uint64_t); -- /* First argument is always "a0". */ -- args_size += ALIGN_UP (sizeof ("a0"), 4); -- /* Normal arguments. */ -- for (i = 1; i < argc; i++) -- args_size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); -- -- /* rd arguments. */ -- args_size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); -- args_size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); -- args_size += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); -- -- args_size = ALIGN_UP (args_size, 8); -- -- linux_args_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (args_size)); -- grub_dprintf ("linux", "linux args numpages: %lld\n", -- (long long) GRUB_EFI_BYTES_TO_PAGES (args_size)); -- if (!linux_args_addr) -- { -- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); -- goto fail; -+ if (grub_file_seek (file, 0) == (grub_off_t) -1) -+ goto fail; -+ -+ if (grub_file_read (file, &lh, sizeof (lh)) < (grub_ssize_t) sizeof (lh)) -+ { -+ if (!grub_errno) -+ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), -+ argv[0]); -+ goto fail; -+ } -+ -+ if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE) -+ { -+ goto fail; -+ } -+ /* linux kernel type is EFI */ -+ grub_loongarch_linux_type = GRUB_LOONGARCH_LINUX_EFI; -+ kernel_params.kernel_addr = (grub_addr_t) grub_efi_allocate_any_pages ( -+ GRUB_EFI_BYTES_TO_PAGES (kernel_params.kernel_size)); -+ grub_dprintf ("linux", "kernel numpages: %" PRIuGRUB_SIZE "\n", -+ GRUB_EFI_BYTES_TO_PAGES (kernel_params.kernel_size)); -+ if (!kernel_params.kernel_addr) -+ { -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); -+ goto fail; -+ } -+ -+ grub_file_seek (file, 0); -+ if (grub_file_read (file, (void*) kernel_params.kernel_addr, kernel_params.kernel_size) -+ < (grub_int64_t) kernel_params.kernel_size) -+ { -+ if (!grub_errno) -+ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]); -+ goto fail; -+ } -+ -+ grub_dprintf ("linux", "kernel @ %p\n", (void*) kernel_params.kernel_addr); - } -- linux_argv = (grub_uint64_t *) linux_args_addr; -- linux_args = (char *) (linux_argv + (linux_argc + 1 + 3)); -- -- grub_memcpy (linux_args, "a0", sizeof ("a0")); -- *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; -- linux_argv++; -- linux_args += ALIGN_UP (sizeof ("a0"), 4); - -- for (i = 1; i < argc; i++) -+ cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE) -+ + sizeof (GRUB_INITRD_STRING); -+ kernel_params.ramdisk_args_len = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); -+ kernel_params.linux_argc = argc; -+ kernel_params.linux_args = grub_malloc (cmdline_size); -+ if (!kernel_params.linux_args) - { -- grub_memcpy (linux_args, argv[i], grub_strlen (argv[i]) + 1); -- *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; -- linux_argv++; -- linux_args += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); -+ goto fail; - } - -- /* Reserve space for rd arguments. */ -- rd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; -- linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); -- *linux_argv = 0; -- linux_argv++; -+ grub_memcpy (kernel_params.linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); - -- rd_size_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; -- linux_args += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); -- *linux_argv = 0; -- linux_argv++; -- -- /* Reserve space for initrd arguments. */ -- initrd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; -- linux_args += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); -- *linux_argv = 0; -- linux_argv++; -+ if (grub_linux_loongarch_elf_get_boot_params (&boot_params) == 1) -+ is_bpi_boot = 1; -+ else -+ is_bpi_boot = 0; - -- *linux_argv = 0; -+ if (is_bpi_boot == 0) -+ { -+ err = grub_create_loader_cmdline (argc, argv, -+ (char*) ((grub_addr_t) kernel_params.linux_args + sizeof (LINUX_IMAGE) - 1), -+ kernel_params.ramdisk_args_len, -+ GRUB_VERIFY_KERNEL_CMDLINE); -+ if (err) -+ goto fail; -+ } else { -+ /* save args from linux cmdline */ -+ char *p = kernel_params.linux_args; -+ -+ p += sizeof (LINUX_IMAGE) - 1; -+ for (i=0; i < argc; i++) -+ { -+ grub_memcpy (p, argv[i], grub_strlen(argv[i]) + 1); -+ p += grub_strlen(argv[i]) + 1; -+ } - } - - if (grub_errno == GRUB_ERR_NONE) -@@ -541,133 +274,81 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - loaded = 1; - } - -- initrd_loaded = 0; -- - fail: -+ if (elf != NULL) { -+ /* grub_elf_close will call grub_file_close() */ -+ grub_elf_close (elf); -+ } else { -+ if (file) -+ grub_file_close (file); -+ } -+ - if (grub_errno != GRUB_ERR_NONE) - { - grub_dl_unref (my_mod); - loaded = 0; - } - -- if (fdt_linux_args && !loaded) -- grub_free (fdt_linux_args); -+ if (kernel_params.linux_args && !loaded) -+ grub_free (kernel_params.linux_args); - -- if (linux_args_addr && !loaded) -- grub_efi_free_pages ((grub_addr_t) linux_args_addr, -- GRUB_EFI_BYTES_TO_PAGES (args_size)); -+ if (grub_loongarch_linux_type == GRUB_LOONGARCH_LINUX_EFI) { -+ if (kernel_params.kernel_addr && !loaded) -+ grub_efi_free_pages ((grub_addr_t) kernel_params.kernel_addr, -+ GRUB_EFI_BYTES_TO_PAGES (kernel_params.kernel_size)); -+ } - - return grub_errno; - } - --#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024) -- --/* -- * This function returns a pointer to a legally allocated initrd buffer, -- * or NULL if unsuccessful -- */ --static void * --allocate_initrd_mem (int initrd_pages) --{ -- grub_addr_t max_addr; -- -- if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE) -- return NULL; -- -- max_addr += INITRD_MAX_ADDRESS_OFFSET - 1; -- -- return grub_efi_allocate_pages_real (max_addr, initrd_pages, -- GRUB_EFI_ALLOCATE_MAX_ADDRESS, -- GRUB_EFI_LOADER_DATA); --} -- -- - static grub_err_t - grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) - { -- grub_size_t initrd_size, initrd_pages; -- grub_err_t err; -- void *initrd_mem = NULL; - struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 }; -+ grub_size_t initrd_size; -+ void *initrd_mem = NULL; -+ grub_err_t err; - - if (argc == 0) -- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -+ { -+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -+ goto fail; -+ } - - if (!loaded) -- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); -- -- if (initrd_loaded) -- return grub_error (GRUB_ERR_BAD_ARGUMENT, "only one initrd command can be issued."); -+ { -+ grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("you need to load the kernel first")); -+ goto fail; -+ } - - if (grub_initrd_init (argc, argv, &initrd_ctx)) - goto fail; - - initrd_size = grub_get_initrd_size (&initrd_ctx); -+ grub_dprintf ("linux", "Loading initrd\n"); - -- if (is_fdt_boot == 1) //fdt -- { -- initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size)); -- initrd_mem = allocate_initrd_mem (initrd_pages); -- if (!initrd_mem) -+ initrd_mem = grub_linux_loongarch_alloc_initrd_mem_align (initrd_size, 0x10000, &err); -+ if (err) -+ goto fail; -+ -+ if (!initrd_mem) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); - goto fail; - } -- } else { -- grub_relocator_chunk_t ch; -- err = grub_relocator_alloc_chunk_align (relocator, &ch, -- 0, (0xffffffff - initrd_size) + 1, -- initrd_size, 0x10000, -- GRUB_RELOCATOR_PREFERENCE_HIGH, 0); -- -- if (err) -- return err; -- initrd_mem = get_virtual_current_address (ch); -- } - - if (grub_initrd_load (&initrd_ctx, argv, initrd_mem)) - goto fail; - -- initrd_start = (grub_addr_t) initrd_mem; -- initrd_end = initrd_start + initrd_size; -- grub_dprintf ("linux", "[addr=%p, size=0x%lx]\n", -- (void *) initrd_start, initrd_size); -- -- if (is_fdt_boot == 0) //bpi -- { -- grub_snprintf ((char *) linux_args_addr + rd_addr_arg_off, -- sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), -- "rd_start=0x%lx", -- (grub_uint64_t) initrd_mem); -- ((grub_uint64_t *) linux_args_addr)[linux_argc] -- = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_addr_arg_off); -- linux_argc++; -- -- grub_snprintf ((char *) linux_args_addr + rd_size_arg_off, -- sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%lx", -- (grub_uint64_t) initrd_size); -- ((grub_uint64_t *) linux_args_addr)[linux_argc] -- = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_size_arg_off); -- linux_argc++; -- -- grub_snprintf ((char *) linux_args_addr + initrd_addr_arg_off, -- sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), -- "initrd=0x%lx,0x%lx", -- ((grub_uint64_t) initrd_mem & GRUB_EFI_MAX_PHY_ADDRESS), -- (grub_uint64_t) initrd_size); -- ((grub_uint64_t *) linux_args_addr)[linux_argc] -- = (grub_uint64_t) ((grub_addr_t) linux_args_addr + initrd_addr_arg_off); -- linux_argc++; -- } -- -- initrd_loaded = 1; -- -- fail: -+ /* save ramdisk addr and size */ -+ kernel_params.ramdisk_addr = (grub_addr_t) initrd_mem; -+ kernel_params.ramdisk_size = initrd_size; -+ grub_dprintf ("linux", "ramdisk [addr=%p, size=0x%lx]\n", -+ (void *) initrd_mem, initrd_size); -+fail: - grub_initrd_close (&initrd_ctx); -- if (is_fdt_boot == 1) -- if (initrd_mem && !initrd_start) -- grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages); - - return grub_errno; - } -@@ -677,9 +358,9 @@ static grub_command_t cmd_linux, cmd_initrd; - GRUB_MOD_INIT(linux) - { - cmd_linux = grub_register_command ("linux", grub_cmd_linux, -- 0, N_("Load Linux.")); -+ N_("FILE [ARGS...]"), N_("Load Linux.")); - cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, -- 0, N_("Load initrd.")); -+ N_("FILE"), N_("Load initrd.")); - my_mod = mod; - } - -diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h -index d5c805d..c34f9d1 100644 ---- a/include/grub/efi/api.h -+++ b/include/grub/efi/api.h -@@ -374,6 +374,26 @@ - { 0xa1, 0x92, 0xbf, 0x1d, 0x57, 0xd0, 0xb1, 0x89 } \ - } - -+#define GRUB_EFI_BOOT_MEMMAP_GUID \ -+ { 0x800f683f, 0xd08b, 0x423a, \ -+ { 0xa2, 0x93, 0x96, 0x5c, 0x3c, 0x6f, 0xe2, 0xb4 } \ -+ } -+ -+#define GRUB_EFI_INITRD_MEDIA_GUID \ -+ { 0x5568e427, 0x68fc, 0x4f3d, \ -+ { 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68 } \ -+ } -+ -+#define GRUB_EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ -+ { 0x9042a9de, 0x23dc, 0x4a38, \ -+ { 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } \ -+ } -+ -+#define GRUB_EFI_CONSOLE_OUT_DEVICE_GUID \ -+ { 0xd3b36f2c, 0xd551, 0x11d4, \ -+ { 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ -+ } -+ - struct grub_efi_sal_system_table - { - grub_uint32_t signature; -diff --git a/include/grub/fdt.h b/include/grub/fdt.h -index a0710ab..2f4f270 100644 ---- a/include/grub/fdt.h -+++ b/include/grub/fdt.h -@@ -146,6 +146,6 @@ int EXPORT_FUNC(grub_fdt_set_prop) (void *fdt, unsigned int nodeoffset, const ch - grub_fdt_set_prop ((fdt), (nodeoffset), "reg", reg_64, 16); \ - }) - --#endif /* defined(__arm__) || defined(__aarch64__) */ -+#endif /* defined(__arm__) || defined(__aarch64__) || defined(__loongarch__) */ - - #endif /* ! GRUB_FDT_HEADER */ -diff --git a/include/grub/loongarch64/asm.h b/include/grub/loongarch64/asm.h -deleted file mode 100644 -index c3e77e9..0000000 ---- a/include/grub/loongarch64/asm.h -+++ /dev/null -@@ -1,10 +0,0 @@ --#ifndef GRUB_LOONGARCH64_ASM_HEADER --#define GRUB_LOONGARCH64_ASM_HEADER 1 -- --#define GRUB_ASM_T4 $a4 --#define GRUB_ASM_T5 $a5 --#define GRUB_ASM_SZREG 8 --#define GRUB_ASM_REG_S st.d --#define GRUB_ASM_REG_L ld.d -- --#endif -diff --git a/include/grub/loongarch64/efi/loongson.h b/include/grub/loongarch64/efi/loongson.h -deleted file mode 100644 -index 7a9ccb4..0000000 ---- a/include/grub/loongarch64/efi/loongson.h -+++ /dev/null -@@ -1,113 +0,0 @@ --/* -- * GRUB -- GRand Unified Bootloader -- * Copyright (C) 2017 Free Software Foundation, Inc. -- * -- * GRUB is free software: you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation, either version 3 of the License, or -- * (at your option) any later version. -- * -- * GRUB is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with GRUB. If not, see . -- */ -- --#ifndef GRUB_EFI_LOONGSON_HEADER --#define GRUB_EFI_LOONGSON_HEADER 1 -- --#include -- --#include -- --#define GRUB_EFI_LOONGSON_BPI_TABLE_GUID \ -- { 0x4660f721, 0x2ec5, 0x416a, \ -- { 0x89, 0x9a, 0x43, 0x18, 0x02, 0x50, 0xa0, 0xc9 } \ -- } -- --#define GRUB_EFI_MAX_PHY_ADDRESS 0xffffffffffffULL --#define ELF32_LOADMASK (0xf0000000UL) --#define ELF64_LOADMASK (0xf000000000000000ULL) --#define FLAGS_EFI_SUPPORT_BIT 0 --#define GRUB_EFI_LOONGSON_MMAP_MAX 128 -- --typedef enum -- { -- GRUB_EFI_LOONGSON_SYSTEM_RAM = 1, -- GRUB_EFI_LOONGSON_MEMORY_RESERVED, -- GRUB_EFI_LOONGSON_ACPI_TABLE, -- GRUB_EFI_LOONGSON_ACPI_NVS, -- GRUB_EFI_LOONGSON_MAX_MEMORY_TYPE -- } --grub_efi_loongson_memory_type; -- --typedef enum -- { -- GRUB_EFI_BPI_VER_NONE = 0, -- GRUB_EFI_BPI_VER_V1 = 1000, -- GRUB_EFI_BPI_VER_V2 = 1001, -- } -- grub_efi_loongson_bpi_version; -- --grub_uint8_t --EXPORT_FUNC(grub_efi_loongson_calculatesum8) (const grub_uint8_t *Buffer, -- grub_efi_uintn_t Length); -- --grub_uint8_t --EXPORT_FUNC(grub_efi_loongson_grub_calculatechecksum8) (const grub_uint8_t *Buffer, -- grub_efi_uintn_t Length); -- --unsigned long --EXPORT_FUNC(grub_efi_get_bpi_version) (const char *str); -- --void * --EXPORT_FUNC(grub_efi_loongson_get_boot_params) (void); -- --typedef struct _extention_list_hdr { -- grub_uint64_t signature; -- grub_uint32_t length; -- grub_uint8_t revision; -- grub_uint8_t checksum; -- union { -- struct _extention_list_hdr *next; -- grub_uint64_t next_offset; -- }; --}GRUB_PACKED --ext_list; -- --typedef struct boot_params_interface { -- grub_uint64_t signature; //{'B', 'P', 'I', 'x', 'x', 'x', 'x', 'x'} -- grub_efi_system_table_t *systemtable; -- union { -- ext_list *extlist; -- grub_uint64_t extlist_offset; -- }; -- grub_uint64_t flags; --}GRUB_PACKED --boot_params_interface; -- --typedef struct { -- ext_list header; //{MEM} -- grub_uint8_t mapcount; -- struct GRUB_PACKED memmap_v1 { -- grub_uint32_t memtype; -- grub_uint64_t memstart; -- grub_uint64_t memsize; -- } map[GRUB_EFI_LOONGSON_MMAP_MAX]; --}GRUB_PACKED --mem_map_v1; -- --typedef struct { -- ext_list header; //{VBIOS} -- grub_uint64_t vbiosaddr; --}GRUB_PACKED --vbios; -- --grub_uint32_t --EXPORT_FUNC (grub_efi_loongson_memmap_v1_sort) (struct memmap_v1 array[], -- grub_uint32_t length, mem_map_v1 * mem, -- grub_uint32_t index, grub_uint32_t memtype); --#endif /* ! GRUB_EFI_LOONGSON_HEADER */ -diff --git a/include/grub/loongarch64/efi/memory.h b/include/grub/loongarch64/efi/memory.h -index 73641a1..16b2e0b 100644 ---- a/include/grub/loongarch64/efi/memory.h -+++ b/include/grub/loongarch64/efi/memory.h -@@ -6,7 +6,12 @@ grub_efi_max_usable_address(void) - { - grub_uint64_t addr; - asm volatile ("csrrd %0, 0x181" : "=r" (addr)); -- return addr |= 0xffffffffffUL; -+ if (addr & 0x1) -+ addr |= 0xfffffffffffUL; -+ else -+ addr = 0xfffffffffffUL; -+ -+ return addr; - } - - #endif /* ! GRUB_MEMORY_CPU_HEADER */ -diff --git a/include/grub/loongarch64/efi/time.h b/include/grub/loongarch64/efi/time.h -deleted file mode 100644 -index e69de29..0000000 -diff --git a/include/grub/loongarch64/linux.h b/include/grub/loongarch64/linux.h -index 3c6cf65..4ac3c57 100644 ---- a/include/grub/loongarch64/linux.h -+++ b/include/grub/loongarch64/linux.h -@@ -28,8 +28,7 @@ - - #define GRUB_LOONGSON3_BOOT_MEM_MAP_MAX 128 - --#define GRUB_LINUX_LOONGARCH_MAGIC_SIGNATURE 0x4C6F6F6E67417263 /* 'LoongArc' */ --#define GRUB_LINUX_LOONGARCH_MAGIC_SIGNATURE2 0x68 /* 'h' */ -+#define GRUB_LINUX_LOONGARCH_MAGIC_SIGNATURE 0x6E6F73676E6F6F4C /* 'Loongson' */ - #define linux_arch_kernel_header linux_loongarch64_kernel_header - - /* From linux/Documentation/loongarch/booting.txt -@@ -48,27 +47,171 @@ struct linux_loongarch64_kernel_header - grub_uint64_t res0; /* reserved */ - grub_uint64_t res1; /* reserved */ - grub_uint64_t res2; /* reserved */ -- grub_uint64_t magic; /* Magic number, little endian, "LoongArc" */ -- grub_uint32_t magic1; /* Magic number, little endian, "h" */ -+ grub_uint64_t magic; /* Magic number, little endian, "Loongson" */ - grub_uint64_t res3; /* reserved */ -+ grub_uint32_t res4; /* reserved */ - grub_uint32_t hdr_offset; /* Offset of PE/COFF header */ - }; - - struct linux_loongarch64_kernel_params - { -- grub_addr_t kernel_addr; /* kernel entry address */ -- grub_size_t kernel_size; /* kernel size */ -- grub_addr_t ramdisk_addr; /* initrd load address */ -- grub_size_t ramdisk_size; /* initrd size */ -- int linux_argc; -- grub_addr_t linux_argv; -+ grub_addr_t kernel_addr; /* kernel entry address */ -+ grub_size_t kernel_size; /* kernel size */ -+ grub_addr_t ramdisk_addr; /* initrd load address */ -+ grub_size_t ramdisk_size; /* initrd size */ -+ int ramdisk_args_len; /* position of initrd in linux_args*/ -+ int linux_argc; /* cmdline parameters number*/ -+ grub_addr_t linux_argv; /* cmdline parameters address*/ - void* linux_args; -+ void* fdt; - }; - - #include - #include - -+#define GRUB_EFI_MAX_PHY_ADDRESS 0xffffffffffffULL - #define ELF32_LOADMASK (0xf0000000UL) - #define ELF64_LOADMASK (0xf000000000000000ULL) -+#define FLAGS_EFI_SUPPORT_BIT 0 -+ -+/*initrd info*/ -+#define GRUB_RD_START_STRING "rd_start=0xXXXXXXXXXXXXXXXX" -+#define GRUB_RD_SIZE_STRING "rd_size=0xXXXXXXXXXXXXXXXX" -+#define GRUB_INITRD_STRING "initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX" -+ -+#define FDT_ADDR_CELLS_STRING "#address-cells" -+#define FDT_SIZE_CELLS_STRING "#size-cells" -+#define FDT_ADDR_SIZE_EXTRA ((2 * grub_fdt_prop_entry_size (sizeof(grub_uint32_t))) + \ -+ sizeof (FDT_ADDR_CELLS_STRING) + \ -+ sizeof (FDT_SIZE_CELLS_STRING)) -+ -+struct efi_boot_memmap { -+ grub_efi_uintn_t map_size; -+ grub_efi_uintn_t desc_size; -+ grub_efi_uint32_t desc_ver; -+ grub_efi_uintn_t map_key; -+ grub_efi_uintn_t buff_size; -+ grub_efi_memory_descriptor_t map[]; -+}; -+ -+struct efi_initrd { -+ grub_efi_uintn_t base; -+ grub_efi_uintn_t size; -+}; -+ -+/* -+ * These are set up by the setup-routine at boot-time: -+ */ -+struct screen_info { -+ grub_efi_uint8_t orig_x; /* 0x00 */ -+ grub_efi_uint8_t orig_y; /* 0x01 */ -+ grub_efi_uint16_t ext_mem_k; /* 0x02 */ -+ grub_efi_uint16_t orig_video_page; /* 0x04 */ -+ grub_efi_uint8_t orig_video_mode; /* 0x06 */ -+ grub_efi_uint8_t orig_video_cols; /* 0x07 */ -+ grub_efi_uint8_t flags; /* 0x08 */ -+ grub_efi_uint8_t unused2; /* 0x09 */ -+ grub_efi_uint16_t orig_video_ega_bx;/* 0x0a */ -+ grub_efi_uint16_t unused3; /* 0x0c */ -+ grub_efi_uint8_t orig_video_lines; /* 0x0e */ -+ grub_efi_uint8_t orig_video_isVGA; /* 0x0f */ -+ grub_efi_uint16_t orig_video_points;/* 0x10 */ -+ -+ /* VESA graphic mode -- linear frame buffer */ -+ grub_efi_uint16_t lfb_width; /* 0x12 */ -+ grub_efi_uint16_t lfb_height; /* 0x14 */ -+ grub_efi_uint16_t lfb_depth; /* 0x16 */ -+ grub_efi_uint32_t lfb_base; /* 0x18 */ -+ grub_efi_uint32_t lfb_size; /* 0x1c */ -+ grub_efi_uint16_t cl_magic, cl_offset; /* 0x20 */ -+ grub_efi_uint16_t lfb_linelength; /* 0x24 */ -+ grub_efi_uint8_t red_size; /* 0x26 */ -+ grub_efi_uint8_t red_pos; /* 0x27 */ -+ grub_efi_uint8_t green_size; /* 0x28 */ -+ grub_efi_uint8_t green_pos; /* 0x29 */ -+ grub_efi_uint8_t blue_size; /* 0x2a */ -+ grub_efi_uint8_t blue_pos; /* 0x2b */ -+ grub_efi_uint8_t rsvd_size; /* 0x2c */ -+ grub_efi_uint8_t rsvd_pos; /* 0x2d */ -+ grub_efi_uint16_t vesapm_seg; /* 0x2e */ -+ grub_efi_uint16_t vesapm_off; /* 0x30 */ -+ grub_efi_uint16_t pages; /* 0x32 */ -+ grub_efi_uint16_t vesa_attributes; /* 0x34 */ -+ grub_efi_uint32_t capabilities; /* 0x36 */ -+ grub_efi_uint32_t ext_lfb_base; /* 0x3a */ -+ grub_efi_uint8_t _reserved[2]; /* 0x3e */ -+} __attribute__((packed)); -+ -+#define GRUB_VIDEO_TYPE_EFI 0x70 -+#define GRUB_VIDEO_CAPABILITY_SKIP_QUIRKS (1 << 0) -+#define GRUB_VIDEO_CAPABILITY_64BIT_BASE (1 << 1) /* Frame buffer base is 64-bit */ -+ -+ -+/* From arch/loongarch/include/asm/mach-loongson64/boot_param.h */ -+struct _extention_list_hdr { -+ grub_uint64_t signature; -+ grub_uint32_t length; -+ grub_uint8_t revision; -+ grub_uint8_t checksum; -+ union { -+ struct _extention_list_hdr *next; -+ grub_uint64_t next_offset; -+ }; -+ -+} GRUB_PACKED; -+ -+struct boot_params_interface { -+ grub_uint64_t signature; /* {"B", "P", "I", "0", "1", ... } */ -+ grub_efi_system_table_t *systemtable; -+ union { -+ struct _extention_list_hdr *extlist; -+ grub_uint64_t extlist_offset; -+ }; -+ grub_uint64_t flags; -+}GRUB_PACKED; -+ -+struct loongsonlist_mem_map { -+ struct _extention_list_hdr header; /* {"M", "E", "M"} */ -+ grub_uint8_t map_count; -+ struct memmap { -+ grub_uint32_t mem_type; -+ grub_uint64_t mem_start; -+ grub_uint64_t mem_size; -+ } GRUB_PACKED map[GRUB_LOONGSON3_BOOT_MEM_MAP_MAX]; -+}GRUB_PACKED; -+ -+grub_err_t -+finalize_efi_params_linux (struct linux_loongarch64_kernel_params *kernel_params); -+ -+grub_err_t -+grub_linux_loongarch_elf_linux_boot_image (struct linux_loongarch64_kernel_params -+ *kernel_params); -+ -+void* -+grub_linux_loongarch_alloc_virtual_mem_addr (grub_addr_t addr, -+ grub_size_t size, -+ grub_err_t *err); -+ -+void* -+grub_linux_loongarch_alloc_virtual_mem_align (grub_size_t size, -+ grub_size_t align, -+ grub_err_t *err); -+ -+void* -+grub_linux_loongarch_alloc_initrd_mem_align (grub_size_t size, -+ grub_size_t align, -+ grub_err_t *err); -+ -+void -+grub_linux_loongarch_elf_relocator_unload (void); -+ -+int -+grub_linux_loongarch_elf_get_boot_params (struct boot_params_interface **boot_params); -+ -+grub_err_t -+grub_linux_loongarch_elf_boot_params (struct boot_params_interface *boot_params); -+ -+grub_err_t -+grub_linux_loongarch_elf_load_kernel (grub_elf_t elf, const char *filename); - - #endif /* ! GRUB_LOONGARCH64_LINUX_HEADER */ -diff --git a/include/grub/loongarch64/time.h b/include/grub/loongarch64/time.h -index c9a7334..0a10fbd 100644 ---- a/include/grub/loongarch64/time.h -+++ b/include/grub/loongarch64/time.h -@@ -19,18 +19,6 @@ - #ifndef KERNEL_CPU_TIME_HEADER - #define KERNEL_CPU_TIME_HEADER 1 - --#ifndef GRUB_UTIL -- --#define GRUB_TICKS_PER_SECOND (grub_arch_cpuclock / 2) -- --void grub_timer_init (grub_uint32_t cpuclock); -- --/* Return the real time in ticks. */ --grub_uint64_t grub_get_rtc (void); -- --extern grub_uint32_t grub_arch_cpuclock; --#endif -- - static inline void - grub_cpu_idle(void) - { --- -2.43.5 - diff --git a/20-grub.install b/20-grub.install index 40a437c..0ecf1e2 100755 --- a/20-grub.install +++ b/20-grub.install @@ -62,7 +62,7 @@ case "$COMMAND" in "$KERNEL_DIR"/dtb do [[ -e "$i" ]] || continue - rm -rf "/boot/${i##*/}-${KERNEL_VERSION}" + rm -f "/boot/${i##*/}-${KERNEL_VERSION}" cp -aT "$i" "/boot/${i##*/}-${KERNEL_VERSION}" command -v restorecon &>/dev/null && \ restorecon -R "/boot/${i##*/}-${KERNEL_VERSION}" diff --git a/grub.macros b/grub.macros index 07a0edd..229a82a 100644 --- a/grub.macros +++ b/grub.macros @@ -92,7 +92,7 @@ %endif -%global efi_only aarch64 %{arm} loongarch64 +%global efi_only aarch64 %{arm} %global efi_arch x86_64 ia64 %{efi_only} %ifarch %{efi_arch} %global with_efi_arch 1 @@ -122,7 +122,7 @@ %global platform_modules " appendedsig " %endif -%ifarch aarch64 %{arm} loongarch64 +%ifarch aarch64 %{arm} %global platform_modules " " %endif @@ -187,14 +187,6 @@ )} %endif -%ifarch loongarch64 -%global with_emu_arch 0 -%global efiarch loongarch64 -%global target_cpu_name loongarch64 -%global grub_target_name loongarch64-efi -%global package_arch efi-loongarch64 -%endif - %global _target_platform %{target_cpu_name}-%{_vendor}-%{_target_os}%{?_gnu} %global _alt_target_platform %{alt_target_cpu_name}-%{_vendor}-%{_target_os}%{?_gnu} @@ -230,7 +222,7 @@ %ifarch x86_64 %global with_efi_common 1 -%global with_legacy_modules 1 +%global with_legacy_modules 0 %global with_legacy_common 0 %else %global with_efi_common 0 diff --git a/grub.patches b/grub.patches index 798ccc8..a913b39 100644 --- a/grub.patches +++ b/grub.patches @@ -663,11 +663,14 @@ Patch0663: 0663-types-Make-bool-generally-available.patch Patch0664: 0664-Remove-exttra-bool-definitions.patch Patch0665: 0665-fs-xfs-Fix-issues-found-while-fuzzing-the-XFS-filesy.patch Patch0666: 0666-ieee1275-ofnet-Fix-grub_malloc-removed-after-added-s.patch -# Support loongarch64 -#Patch1000: 1000-loongarch64-add-support.patch -Patch1001: 1001-bls-make-list.patch -Patch1002: 1002-Add-LoongArch64-support-and-update-interface-to-v40.patch -Patch1003: 1003-cryptodisk-make-the-password-getter-and-additional-a.patch -Patch1004: 1004-cryptodisk-add-OS-provided-secret-support.patch -Patch1005: 1005-efi-Add-API-for-retrieving-the-EFI-secret-for-crypto.patch -Patch1006: 1006-Update-patches-in-sync-with-loongarch64.patch +Patch0667: 0667-fs-xfs-Add-bigtime-incompat-feature-support.patch +Patch0668: 0668-fs-xfs-Add-needsrepair-incompat-feature-support.patch +Patch0669: 0669-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch +Patch0670: 0670-fs-Remove-trailing-whitespaces.patch +Patch0671: 0671-fs-xfs-Fix-memory-leaks-in-XFS-module.patch +Patch0672: 0672-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch +Patch0673: 0673-fs-xfs-Fix-XFS-directory-extent-parsing.patch +Patch0674: 0674-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch +Patch0675: 0675-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch +Patch0676: 0676-fs-xfs-fix-large-extent-counters-incompat-feature-su.patch +Patch0677: 0677-fs-ext2-Rework-out-of-bounds-read-for-inline-and-ext.patch diff --git a/grub2.spec b/grub2.spec index abb85ae..112d5c1 100644 --- a/grub2.spec +++ b/grub2.spec @@ -1,18 +1,13 @@ -%define anolis_release .0.1 %undefine _hardened_build %global tarversion 2.02 %undefine _missing_build_ids_terminate_build %global _configure_gnuconfig_hack 0 -%ifarch loongarch64 -%global _configure_gnuconfig_hack 1 -%endif - Name: grub2 Epoch: 1 Version: 2.02 -Release: 162%{anolis_release}%{?dist} +Release: 165%{?dist} Summary: Bootloader with support for Linux, Multiboot and more Group: System Environment/Base License: GPLv3+ @@ -119,7 +114,7 @@ Requires(post): dracut %{desc} This subpackage provides tools for support of all platforms. -%ifarch x86_64 loongarch64 +%ifarch x86_64 %package tools-efi Summary: Support tools for GRUB. Group: System Environment/Base @@ -189,11 +184,6 @@ git add grub-%{grublegacyarch}-%{tarversion} %endif git commit -m "After making subdirs" -%ifarch loongarch64 -%_update_config_sub -%_update_config_guess -%endif - %build %if 0%{with_efi_arch} %{expand:%do_primary_efi_build %%{grubefiarch} %%{grubefiname} %%{grubeficdname} %%{_target_platform} %%{efi_target_cflags} %%{efi_host_cflags} %{old_sb_ca} %{old_sb_cer} %{old_sb_key} %{sb_ca} %{sb_cer} %{sb_key}} @@ -235,11 +225,8 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir ln -s %{name}-set-password ${RPM_BUILD_ROOT}/%{_sbindir}/%{name}-setpassword echo '.so man8/%{name}-set-password.8' > ${RPM_BUILD_ROOT}/%{_datadir}/man/man8/%{name}-setpassword.8 %ifnarch x86_64 -rm -vf ${RPM_BUILD_ROOT}/%{_sbindir}/%{name}-bios-setup -%endif - -%ifnarch x86_64 loongarch64 rm -vf ${RPM_BUILD_ROOT}/%{_bindir}/%{name}-render-label +rm -vf ${RPM_BUILD_ROOT}/%{_sbindir}/%{name}-bios-setup rm -vf ${RPM_BUILD_ROOT}/%{_sbindir}/%{name}-macbless %endif @@ -412,7 +399,7 @@ fi %{_datadir}/man/man1/%{name}-editenv* %{_datadir}/man/man1/%{name}-mkpasswd-* -%ifarch x86_64 loongarch64 +%ifarch x86_64 %files tools-efi %{_sbindir}/%{name}-macbless %{_bindir}/%{name}-render-label @@ -536,16 +523,17 @@ fi %endif %changelog -* Fri Mar 28 2025 Bo Ren - 2.02-162.0.1 -- Build pc-modules package on x86_64 (geliwei@openanolis.org) -- Add loongarch64 base support (zhangwenlong@loongson.cn)(chenguoqi@loongson.cn) -- Fix a bug in bls_make_list, blscfg. (zhonglingh@linux.alibaba.com) -- Delete LoongArch64 support old version due to compile error(yangqiming@loongson.cn) -- Add LoongArch64 support(yangqiming@loongson.cn) -- LoongArch64 support fdt and phy-addr BIOS(yangqiming@loongson.cn) -- Remove dtb dir with correct argument (Liwei Ge) -- Support use confidential computing provisioned secrets for disk decryption(hanliyang@hygon.cn) -- Update for loongarch64 in sync with latest v2.04(liuxue@loongson.cn) +* Thu Apr 17 2025 Nicolas Frayer - 2.02-165 +- fs/ext2: Rework of OOB read patch +- Resolves: #RHEL-86553 + +* Fri Apr 4 2025 Leo Sandoval - 2.02-164 +- Bump NVR to sign the build +- Resolves: #RHEL-85627 + +* Thu Apr 3 2025 Nicolas Frayer - 2.02-163 +- fs/xfs: Synced xfs to latest +- Resolves: #RHEL-85627 * Tue Mar 25 2025 Nicolas Frayer - 2.02-162 - ieee1275/ofnet: Fix grub_malloc() removed after added safe -- Gitee From b4e80f76d87c7e07c4a6525c270f0676f99fdaad Mon Sep 17 00:00:00 2001 From: songmingliang Date: Tue, 17 May 2022 18:12:12 +0800 Subject: [PATCH 2/8] build: build pc-modules package on x86_64 --- grub.macros | 2 +- grub2.spec | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/grub.macros b/grub.macros index 229a82a..e55de53 100644 --- a/grub.macros +++ b/grub.macros @@ -222,7 +222,7 @@ %ifarch x86_64 %global with_efi_common 1 -%global with_legacy_modules 0 +%global with_legacy_modules 1 %global with_legacy_common 0 %else %global with_efi_common 0 diff --git a/grub2.spec b/grub2.spec index 112d5c1..30e830c 100644 --- a/grub2.spec +++ b/grub2.spec @@ -1,3 +1,4 @@ +%define anolis_release .0.1 %undefine _hardened_build %global tarversion 2.02 @@ -7,7 +8,7 @@ Name: grub2 Epoch: 1 Version: 2.02 -Release: 165%{?dist} +Release: 165%{anolis_release}%{?dist} Summary: Bootloader with support for Linux, Multiboot and more Group: System Environment/Base License: GPLv3+ @@ -523,6 +524,9 @@ fi %endif %changelog +* Wed Apr 30 2025 Bo Ren - 2.02-165.0.1 +- Build pc-modules package on x86_64 (geliwei@openanolis.org) + * Thu Apr 17 2025 Nicolas Frayer - 2.02-165 - fs/ext2: Rework of OOB read patch - Resolves: #RHEL-86553 -- Gitee From aa41c6aa7a95beab01fc6847ced7960f13acb468 Mon Sep 17 00:00:00 2001 From: songmingliang Date: Tue, 17 May 2022 18:43:45 +0800 Subject: [PATCH 3/8] Add loongarch64 base support --- 1000-loongarch64-add-support.patch | 3968 ++++++++++++++++++++++++++++ grub.macros | 12 +- grub.patches | 2 + grub2.spec | 19 +- 4 files changed, 3996 insertions(+), 5 deletions(-) create mode 100644 1000-loongarch64-add-support.patch diff --git a/1000-loongarch64-add-support.patch b/1000-loongarch64-add-support.patch new file mode 100644 index 0000000..2d83c94 --- /dev/null +++ b/1000-loongarch64-add-support.patch @@ -0,0 +1,3968 @@ +From febee03c70471fd2ce6f0b4cc0f365c32c106ab3 Mon Sep 17 00:00:00 2001 +From: Fedora Ninjas +Date: Wed, 18 May 2022 23:50:45 +0800 +Subject: [PATCH] add loongarch64 support + +--- + conf/Makefile.common | 4 + + configure.ac | 9 + + gentpl.py | 5 +- + grub-core/Makefile.am | 7 + + grub-core/Makefile.core.def | 20 + + grub-core/kern/efi/mm.c | 29 +- + grub-core/kern/elfXX.c | 6 + + grub-core/kern/loongarch64/cache.S | 26 + + grub-core/kern/loongarch64/dl.c | 258 +++++++++ + grub-core/kern/loongarch64/efi/init.c | 76 +++ + grub-core/kern/loongarch64/efi/startup.S | 45 ++ + grub-core/kern/loongarch64/init.c | 47 ++ + grub-core/lib/loongarch64/efi/loongson.c | 505 ++++++++++++++++ + grub-core/lib/loongarch64/efi/loongson_asm.S | 58 ++ + grub-core/lib/loongarch64/relocator.c | 163 ++++++ + grub-core/lib/loongarch64/relocator_asm.S | 51 ++ + grub-core/lib/loongarch64/setjmp.S | 74 +++ + grub-core/lib/loongson/reboot.c | 33 ++ + grub-core/lib/setjmp.S | 2 + + grub-core/loader/efi/chainloader.c | 2 + + grub-core/loader/loongarch64/linux.c | 580 +++++++++++++++++++ + include/grub/dl.h | 2 +- + include/grub/efi/api.h | 3 +- + include/grub/efi/pe32.h | 2 + + include/grub/elf.h | 55 ++ + include/grub/loongarch64/asm.h | 10 + + include/grub/loongarch64/efi/boot.h | 0 + include/grub/loongarch64/efi/loader.h | 25 + + include/grub/loongarch64/efi/loongson.h | 290 ++++++++++ + include/grub/loongarch64/efi/memory.h | 14 + + include/grub/loongarch64/efi/time.h | 0 + include/grub/loongarch64/io.h | 62 ++ + include/grub/loongarch64/kernel.h | 24 + + include/grub/loongarch64/linux.h | 22 + + include/grub/loongarch64/loongarch64.h | 30 + + include/grub/loongarch64/memory.h | 57 ++ + include/grub/loongarch64/relocator.h | 38 ++ + include/grub/loongarch64/setjmp.h | 27 + + include/grub/loongarch64/time.h | 39 ++ + include/grub/loongarch64/types.h | 34 ++ + include/grub/util/install.h | 1 + + util/grub-install-common.c | 43 +- + util/grub-install.c | 16 + + util/grub-mkimagexx.c | 349 ++++++++++- + util/grub-mknetdir.c | 3 +- + util/grub-module-verifier.c | 46 ++ + util/mkimage.c | 16 + + 47 files changed, 3176 insertions(+), 32 deletions(-) + create mode 100644 grub-core/kern/loongarch64/cache.S + create mode 100644 grub-core/kern/loongarch64/dl.c + create mode 100644 grub-core/kern/loongarch64/efi/init.c + create mode 100644 grub-core/kern/loongarch64/efi/startup.S + create mode 100644 grub-core/kern/loongarch64/init.c + create mode 100644 grub-core/lib/loongarch64/efi/loongson.c + create mode 100644 grub-core/lib/loongarch64/efi/loongson_asm.S + create mode 100644 grub-core/lib/loongarch64/relocator.c + create mode 100644 grub-core/lib/loongarch64/relocator_asm.S + create mode 100644 grub-core/lib/loongarch64/setjmp.S + create mode 100644 grub-core/lib/loongson/reboot.c + create mode 100644 grub-core/loader/loongarch64/linux.c + create mode 100644 include/grub/loongarch64/asm.h + create mode 100644 include/grub/loongarch64/efi/boot.h + create mode 100644 include/grub/loongarch64/efi/loader.h + create mode 100644 include/grub/loongarch64/efi/loongson.h + create mode 100644 include/grub/loongarch64/efi/memory.h + create mode 100644 include/grub/loongarch64/efi/time.h + create mode 100644 include/grub/loongarch64/io.h + create mode 100644 include/grub/loongarch64/kernel.h + create mode 100644 include/grub/loongarch64/linux.h + create mode 100644 include/grub/loongarch64/loongarch64.h + create mode 100644 include/grub/loongarch64/memory.h + create mode 100644 include/grub/loongarch64/relocator.h + create mode 100644 include/grub/loongarch64/setjmp.h + create mode 100644 include/grub/loongarch64/time.h + create mode 100644 include/grub/loongarch64/types.h + +diff --git a/conf/Makefile.common b/conf/Makefile.common +index 521cdda..cc1d190 100644 +--- a/conf/Makefile.common ++++ b/conf/Makefile.common +@@ -20,6 +20,10 @@ endif + if COND_powerpc_ieee1275 + CFLAGS_PLATFORM += -mcpu=powerpc + endif ++if COND_loongarch64 ++ CFLAGS_PLATFORM += -fno-strict-aliasing -march=loongarch64 -mabi=lp64 -fno-plt -Wa,-mla-global-with-pcrel ++ CPPFLAGS_PLATFORM = -fno-strict-aliasing -march=loongarch64 -mabi=lp64 -fno-plt -Wa,-mla-global-with-pcrel ++endif + + # Other options + +diff --git a/configure.ac b/configure.ac +index f59a7b8..4715d17 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -116,6 +116,10 @@ case "$target_cpu" in + i[[3456]]86) target_cpu=i386 ;; + amd64) target_cpu=x86_64 ;; + sparc) target_cpu=sparc64 ;; ++ loongarch64) ++ target_cpu=loongarch64 ++ machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_LOONGARCH64=1" ++ ;; + mipsel|mips64el) + target_cpu=mipsel + machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPSEL=1" +@@ -148,6 +152,7 @@ if test "x$with_platform" = x; then + powerpc64-*) platform=ieee1275 ;; + powerpc64le-*) platform=ieee1275 ;; + sparc64-*) platform=ieee1275 ;; ++ loongarch64-*) platform=efi;; + mipsel-*) platform=loongson ;; + mips-*) platform=arc ;; + ia64-*) platform=efi ;; +@@ -196,6 +201,7 @@ case "$target_cpu"-"$platform" in + mipsel-yeeloong) platform=loongson ;; + mipsel-fuloong) platform=loongson ;; + mipsel-loongson) ;; ++ loongarch64-efi) ;; + arm-uboot) ;; + arm-coreboot) ;; + arm-efi) ;; +@@ -251,6 +257,7 @@ case "$platform" in + pc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_PCBIOS=1" ;; + emu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EMU=1" ;; + loongson) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_LOONGSON=1" ;; ++ loongson64) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_LOONARCH64=1" ;; + qemu_mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_QEMU_MIPS=1" ;; + arc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_ARC=1" ;; + esac +@@ -2098,6 +2105,8 @@ AM_CONDITIONAL([COND_mips_arc], [test "(" x$target_cpu = xmips -o x$target_cpu = + AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275]) + AM_CONDITIONAL([COND_sparc64_emu], [test x$target_cpu = xsparc64 -a x$platform = xemu]) + AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275]) ++AM_CONDITIONAL([COND_loongarch64_efi], [test x$target_cpu = xloongarch64 -a x$platform = xefi]) ++AM_CONDITIONAL([COND_loongarch64], [test x$target_cpu = xloongarch64]) + AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips -o x$target_cpu = xmipsel]) + AM_CONDITIONAL([COND_mipsel], [test x$target_cpu = xmipsel]) + AM_CONDITIONAL([COND_mipseb], [test x$target_cpu = xmips]) +diff --git a/gentpl.py b/gentpl.py +index d662c30..3afd642 100644 +--- a/gentpl.py ++++ b/gentpl.py +@@ -32,7 +32,7 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", + "mips_loongson", "sparc64_ieee1275", + "powerpc_ieee1275", "mips_arc", "ia64_efi", + "mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi", +- "arm_coreboot"] ++ "arm_coreboot", "loongarch64_efi"] + + GROUPS = {} + +@@ -44,13 +44,14 @@ GROUPS["x86_64"] = [ "x86_64_efi" ] + GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"] + GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ] + GROUPS["sparc64"] = [ "sparc64_ieee1275" ] ++GROUPS["loongarch64"] = [ "loongarch64_efi" ] + GROUPS["powerpc"] = [ "powerpc_ieee1275" ] + GROUPS["arm"] = [ "arm_uboot", "arm_efi", "arm_coreboot" ] + GROUPS["arm64"] = [ "arm64_efi" ] + + # Groups based on firmware + GROUPS["pc"] = [ "i386_pc" ] +-GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi" ] ++GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi", "loongarch64_efi"] + GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ] + GROUPS["uboot"] = [ "arm_uboot" ] + GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ] +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index 308ad88..24e2ac3 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -222,6 +222,13 @@ KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h + KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h + endif + ++if COND_loongarch64_efi ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h ++KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loongson.h ++endif ++ + if COND_powerpc_ieee1275 + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index ef06f8c..74e66d3 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -95,6 +95,9 @@ kernel = { + arm_coreboot_ldflags = '-Wl,-r,-d'; + arm_coreboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + ++ loongarch64_efi_ldflags = '-Wl,-r,-d'; ++ loongarch64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; ++ + i386_pc_startup = kern/i386/pc/startup.S; + i386_efi_startup = kern/i386/efi/startup.S; + x86_64_efi_startup = kern/x86_64/efi/startup.S; +@@ -105,6 +108,7 @@ kernel = { + i386_coreboot_startup = kern/i386/coreboot/startup.S; + i386_multiboot_startup = kern/i386/coreboot/startup.S; + mips_startup = kern/mips/startup.S; ++ loongarch64_efi_startup = kern/loongarch64/efi/startup.S; + sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S; + powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; + arm_uboot_startup = kern/arm/startup.S; +@@ -295,6 +299,14 @@ kernel = { + extra_dist = video/sis315_init.c; + mips_loongson = commands/keylayouts.c; + ++ loongarch64 = kern/loongarch64/init.c; ++ loongarch64 = kern/loongarch64/dl.c; ++ loongarch64 = kern/loongarch64/cache.S; ++ loongarch64 = kern/generic/rtc_get_time_ms.c; ++ loongarch64_efi = kern/loongarch64/efi/init.c; ++ loongarch64_efi = lib/loongarch64/efi/loongson.c; ++ loongarch64_efi = lib/loongarch64/efi/loongson_asm.S; ++ + powerpc_ieee1275 = kern/powerpc/cache.S; + powerpc_ieee1275 = kern/powerpc/dl.c; + powerpc_ieee1275 = kern/powerpc/compiler-rt.S; +@@ -810,6 +822,7 @@ module = { + enable = sparc64_ieee1275; + enable = powerpc_ieee1275; + enable = mips_arc; ++ enable = loongarch64_efi; + enable = ia64_efi; + enable = arm_efi; + enable = arm64_efi; +@@ -896,6 +909,7 @@ module = { + i386_qemu = lib/i386/halt.c; + xen = lib/xen/halt.c; + efi = lib/efi/halt.c; ++ loongarch64_efi = commands/acpihalt.c; + ieee1275 = lib/ieee1275/halt.c; + emu = lib/emu/halt.c; + uboot = lib/dummy/halt.c; +@@ -911,6 +925,7 @@ module = { + mips_arc = lib/mips/arc/reboot.c; + mips_loongson = lib/mips/loongson/reboot.c; + mips_qemu_mips = lib/mips/qemu_mips/reboot.c; ++ loongarch64_efi = lib/loongson/reboot.c; + xen = lib/xen/reboot.c; + uboot = lib/uboot/reboot.c; + arm_coreboot = lib/dummy/reboot.c; +@@ -1608,6 +1623,8 @@ module = { + efi = lib/efi/relocator.c; + mips = lib/mips/relocator_asm.S; + mips = lib/mips/relocator.c; ++ loongarch64 = lib/loongarch64/relocator_asm.S; ++ loongarch64 = lib/loongarch64/relocator.c; + powerpc = lib/powerpc/relocator_asm.S; + powerpc = lib/powerpc/relocator.c; + xen = lib/xen/relocator.c; +@@ -1620,6 +1637,7 @@ module = { + extra_dist = kern/powerpc/cache_flush.S; + + enable = mips; ++ enable = loongarch64; + enable = powerpc; + enable = x86; + enable = xen; +@@ -1737,6 +1755,7 @@ module = { + xen = loader/i386/xen.c; + i386_pc = lib/i386/pc/vesa_modes_table.c; + mips = loader/mips/linux.c; ++ loongarch64 = loader/loongarch64/linux.c; + powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c; + sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c; + ia64_efi = loader/ia64/efi/linux.c; +@@ -1838,6 +1857,7 @@ module = { + enable = arm_efi; + enable = arm64_efi; + enable = mips; ++ enable = loongarch64_efi; + }; + + module = { +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 9e76f23..fb087e3 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -157,7 +157,11 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, + grub_efi_physical_address_t ret = address; + + /* Limit the memory access to less than 4GB for 32-bit platforms. */ ++#ifdef GRUB_CPU_LOONGARCH64 ++ if (address > grub_efi_max_usable_address()) ++#else + if (address > GRUB_EFI_MAX_USABLE_ADDRESS) ++#endif + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("invalid memory address (0x%llx > 0x%llx)"), +@@ -177,7 +181,11 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, + { + /* Uggh, the address 0 was allocated... This is too annoying, + so reallocate another one. */ ++#ifdef GRUB_CPU_LOONGARCH64 ++ ret = grub_efi_max_usable_address(); ++#else + ret = address; ++#endif + status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &ret); + grub_efi_free_pages (0, pages); + if (status != GRUB_EFI_SUCCESS) +@@ -195,9 +203,14 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, + void * + grub_efi_allocate_any_pages (grub_efi_uintn_t pages) + { +- return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS, ++#ifdef GRUB_CPU_LOONGARCH64 ++ return grub_efi_allocate_pages_real (grub_efi_max_usable_address(), + pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, + GRUB_EFI_LOADER_DATA); ++#else ++ return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS, ++ pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, ++#endif GRUB_EFI_LOADER_DATA); + } + + void * +@@ -471,7 +484,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) + { + if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY +-#if 1 ++#ifdef GRUB_CPU_LOONGARCH64 ++ && desc->physical_start <= grub_efi_max_usable_address() ++#else + && desc->physical_start <= GRUB_EFI_MAX_ALLOCATION_ADDRESS + #endif + && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000 +@@ -486,8 +501,14 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, + - desc->physical_start); + desc->physical_start = 0x100000; + } +- +-#if 1 ++#ifdef GRUB_CPU_LOONGARCH64 ++ if (BYTES_TO_PAGES (filtered_desc->physical_start) ++ + filtered_desc->num_pages ++ > BYTES_TO_PAGES_DOWN (grub_efi_max_usable_address())) ++ filtered_desc->num_pages ++ = (BYTES_TO_PAGES_DOWN (grub_efi_max_usable_address()) ++ - BYTES_TO_PAGES (filtered_desc->physical_start)); ++#else + if (BYTES_TO_PAGES (filtered_desc->physical_start) + + filtered_desc->num_pages + > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS)) +diff --git a/grub-core/kern/elfXX.c b/grub-core/kern/elfXX.c +index 1859d18..8b1dce9 100644 +--- a/grub-core/kern/elfXX.c ++++ b/grub-core/kern/elfXX.c +@@ -134,6 +134,12 @@ grub_elfXX_load (grub_elf_t elf, const char *filename, + load_addr &= 0x3FFFFFFFFFFFFFFFULL; + break; + } ++#ifdef GRUB_CPU_LOONGARCH64 ++ grub_uint64_t addr; ++ asm volatile ("csrrd %0, 0x181" : "=r" (addr)); ++ if ((load_addr >> 48) != (addr >> 48)) ++ return grub_error (GRUB_ERR_BAD_OS, "bad address space"); ++#endif + load_addr += (grub_addr_t) load_offset; + + if (load_addr < load_base) +diff --git a/grub-core/kern/loongarch64/cache.S b/grub-core/kern/loongarch64/cache.S +new file mode 100644 +index 0000000..d291c67 +--- /dev/null ++++ b/grub-core/kern/loongarch64/cache.S +@@ -0,0 +1,26 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2009,2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++ ++FUNCTION (grub_arch_sync_caches) ++ jr $ra ++ ++FUNCTION (grub_arch_sync_dma_caches) ++ jr $ra ++ +diff --git a/grub-core/kern/loongarch64/dl.c b/grub-core/kern/loongarch64/dl.c +new file mode 100644 +index 0000000..a6fd387 +--- /dev/null ++++ b/grub-core/kern/loongarch64/dl.c +@@ -0,0 +1,258 @@ ++/* loongarch64/dl.c - arch-dependent part of loadable module support */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2002,2005,2007,2009,2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Check if EHDR is a valid ELF header. */ ++grub_err_t ++grub_arch_dl_check_header (void *ehdr) ++{ ++ Elf_Ehdr *e = ehdr; ++ ++ /* Check the magic numbers. */ ++ if (e->e_ident[EI_CLASS] != ELFCLASS64 ++ || e->e_ident[EI_DATA] != ELFDATA2LSB ++ || e->e_machine != EM_LOONGARCH64) ++ return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic")); ++ ++ return GRUB_ERR_NONE; ++} ++ ++#pragma GCC diagnostic ignored "-Wcast-align" ++ ++grub_err_t ++grub_arch_dl_get_tramp_got_size (const void *ehdr __attribute__ ((unused)), ++ grub_size_t *tramp, grub_size_t *got) ++{ ++ *tramp = 0; ++ *got = 0; ++ return GRUB_ERR_NONE; ++} ++ ++/* Relocate symbols. */ ++grub_err_t ++grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, ++ Elf_Shdr *s, grub_dl_segment_t seg) ++{ ++ Elf_Ehdr *e = ehdr; ++ Elf_Rel *rel, *max; ++ grub_uint64_t oprs[10240]={0}; ++ int opri=-1; ++ grub_uint32_t la_abs = 0; ++ ++ for (rel = (Elf_Rel *) ((char *) e + s->sh_offset), ++ max = (Elf_Rel *) ((char *) rel + s->sh_size); ++ rel < max; ++ rel = (Elf_Rel *) ((char *) rel + s->sh_entsize)) ++ { ++ grub_uint8_t *addr; ++ Elf_Sym *sym; ++ Elf_Addr r_info; ++ grub_uint64_t sym_value; ++ ++ if (seg->size < rel->r_offset) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "reloc offset is out of the segment"); ++ ++ r_info = (grub_uint64_t) (rel->r_info); ++ ++ addr = (grub_uint8_t *) ((char*)seg->addr + rel->r_offset); ++ sym = (Elf_Sym *) ((char*)mod->symtab ++ + mod->symsize * ELF_R_SYM (r_info)); ++ sym_value = sym->st_value; ++ if (s->sh_type == SHT_RELA) ++ { ++ sym_value += ((Elf_Rela *) rel)->r_addend; ++ } ++ switch (ELF_R_TYPE (r_info)) ++ { ++ case R_LARCH_64: ++ { ++ *(grub_uint64_t *)addr=(grub_uint64_t)sym_value; ++ } ++ break; ++ case R_LARCH_MARK_LA: ++ { ++ la_abs=1; ++ } ++ break; ++ case R_LARCH_SOP_PUSH_PCREL: ++ { ++ opri++; ++ oprs[opri]=(grub_uint64_t)(sym_value-(grub_uint64_t)addr); ++ } ++ break; ++ case R_LARCH_SOP_PUSH_ABSOLUTE: ++ { ++ opri++; ++ oprs[opri]=(grub_uint64_t)sym_value; ++ } ++ break; ++ case R_LARCH_SOP_PUSH_PLT_PCREL: ++ { ++ opri++; ++ oprs[opri]=(grub_uint64_t)(sym_value-(grub_uint64_t)addr); ++ } ++ break; ++ case R_LARCH_SOP_SUB: ++ { ++ grub_uint64_t opr2=oprs[opri]; ++ opri--; ++ grub_uint64_t opr1=oprs[opri]; ++ opri--; ++ opri++; ++ oprs[opri]=opr1 - opr2; ++ } ++ break; ++ case R_LARCH_SOP_SL: ++ { ++ grub_uint64_t opr2=oprs[opri]; ++ opri--; ++ grub_uint64_t opr1=oprs[opri]; ++ opri--; ++ opri++; ++ oprs[opri]=opr1 << opr2; ++ } ++ break; ++ case R_LARCH_SOP_SR: ++ { ++ grub_uint64_t opr2=oprs[opri]; ++ opri--; ++ grub_uint64_t opr1=oprs[opri]; ++ opri--; ++ opri++; ++ oprs[opri]=opr1 >> opr2; ++ } ++ break; ++ case R_LARCH_SOP_ADD: ++ { ++ grub_uint64_t opr2=oprs[opri]; ++ opri--; ++ grub_uint64_t opr1=oprs[opri]; ++ opri--; ++ opri++; ++ oprs[opri]=opr1 + opr2; ++ } ++ break; ++ case R_LARCH_SOP_AND: ++ { ++ grub_uint64_t opr2=oprs[opri]; ++ opri--; ++ grub_uint64_t opr1=oprs[opri]; ++ opri--; ++ opri++; ++ oprs[opri]=opr1 & opr2; ++ } ++ break; ++ case R_LARCH_SOP_IF_ELSE: ++ { ++ grub_uint64_t opr3=oprs[opri]; ++ opri--; ++ grub_uint64_t opr2=oprs[opri]; ++ opri--; ++ grub_uint64_t opr1=oprs[opri]; ++ opri--; ++ if(opr1){ ++ opri++; ++ oprs[opri]=opr2; ++ } else { ++ opri++; ++ oprs[opri]=opr3; ++ } ++ } ++ break; ++ case R_LARCH_SOP_POP_32_S_10_5: ++ { ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | ((opr1 & 0x1f) << 10); ++ } ++ break; ++ case R_LARCH_SOP_POP_32_U_10_12: ++ { ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | ((opr1 & 0xfff) << 10); ++ } ++ break; ++ case R_LARCH_SOP_POP_32_S_10_12: ++ { ++ if(la_abs==1) ++ la_abs=0; ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *(grub_uint64_t *)addr= (*(grub_uint64_t *)addr) | ((opr1 & 0xfff) << 10); ++ } ++ break; ++ case R_LARCH_SOP_POP_32_S_10_16: ++ { ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *(grub_uint64_t *)addr= (*(grub_uint64_t *)addr) | ((opr1 & 0xffff) << 10); ++ } ++ break; ++ case R_LARCH_SOP_POP_32_S_10_16_S2: ++ { ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *(grub_uint64_t *)addr= (*(grub_uint64_t *)addr) | (((opr1 >> 2) & 0xffff) << 10); ++ } ++ break; ++ case R_LARCH_SOP_POP_32_S_5_20: ++ { ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *(grub_uint64_t *)addr= (*(grub_uint64_t *)addr) | ((opr1 & 0xfffff)<<5) ; ++ } ++ break; ++ case R_LARCH_SOP_POP_32_S_0_5_10_16_S2: ++ { ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | (((opr1 >> 2) & 0xffff) << 10); ++ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | ((opr1 >> 18) & 0x1f); ++ } ++ break; ++ case R_LARCH_SOP_POP_32_S_0_10_10_16_S2: ++ { ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | (((opr1 >> 2) & 0xffff) << 10); ++ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | ((opr1 >> 18) & 0x3ff); ++ } ++ break; ++ default: ++ { ++ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ N_("relocation 0x%x is not implemented yet"), ++ ELF_R_TYPE (r_info)); ++ } ++ break; ++ } ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ +diff --git a/grub-core/kern/loongarch64/efi/init.c b/grub-core/kern/loongarch64/efi/init.c +new file mode 100644 +index 0000000..b21d4f1 +--- /dev/null ++++ b/grub-core/kern/loongarch64/efi/init.c +@@ -0,0 +1,76 @@ ++/* init.c - initialize an arm-based EFI system */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2013 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static grub_uint64_t tmr; ++static grub_efi_event_t tmr_evt; ++ ++static grub_uint64_t ++grub_efi_get_time_ms (void) ++{ ++ return tmr; ++} ++ ++static void ++grub_loongson_increment_timer (grub_efi_event_t event __attribute__ ((unused)), ++ void *context __attribute__ ((unused))) ++{ ++ tmr += 10; ++} ++ ++ ++ ++void ++grub_machine_init (void) ++{ ++ grub_efi_boot_services_t *b; ++ ++ grub_efi_init (); ++ ++ b = grub_efi_system_table->boot_services; ++ efi_call_5 (b->create_event, GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL, ++ GRUB_EFI_TPL_CALLBACK, grub_loongson_increment_timer, NULL, &tmr_evt); ++ efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 100000); ++ ++ grub_install_get_time_ms (grub_efi_get_time_ms); ++} ++ ++void ++grub_machine_fini (int flags) ++{ ++ grub_efi_boot_services_t *b; ++ ++ if (!(flags & GRUB_LOADER_FLAG_NORETURN)) ++ return; ++ ++ b = grub_efi_system_table->boot_services; ++ ++ efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_CANCEL, 0); ++ efi_call_1 (b->close_event, tmr_evt); ++ ++ grub_efi_fini (); ++} +diff --git a/grub-core/kern/loongarch64/efi/startup.S b/grub-core/kern/loongarch64/efi/startup.S +new file mode 100644 +index 0000000..1ffff08 +--- /dev/null ++++ b/grub-core/kern/loongarch64/efi/startup.S +@@ -0,0 +1,45 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2013 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++ ++ .file "startup.S" ++ .text ++ .globl start, _start ++ .align 4 ++ ++FUNCTION(start) ++FUNCTION(_start) ++ /* ++ * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in a1/a0. ++ */ ++ addi.d $sp, $sp, -16 ++ st.d $ra, $sp, 0 ++ ++ la $a2, grub_efi_image_handle ++ st.d $a0, $a2, 0 ++ la $a2, grub_efi_system_table ++ st.d $a1, $a2, 0 ++ ++ bl grub_main ++ ++1: ++ ld.d $ra, $sp, 0 ++ addi.d $sp, $sp, 16 ++ jr $ra ++ +diff --git a/grub-core/kern/loongarch64/init.c b/grub-core/kern/loongarch64/init.c +new file mode 100644 +index 0000000..b2de930 +--- /dev/null ++++ b/grub-core/kern/loongarch64/init.c +@@ -0,0 +1,47 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2009,2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++ ++grub_uint32_t grub_arch_cpuclock; ++ ++/* FIXME: use interrupt to count high. */ ++grub_uint64_t ++grub_get_rtc (void) ++{ ++ static grub_uint32_t high = 0; ++ static grub_uint32_t last = 0; ++ grub_uint32_t low; ++ ++ asm volatile ("csrrd %0, " GRUB_CPU_LOONGARCH_COP0_TIMER_COUNT : "=r" (low)); ++ if (low < last) ++ high++; ++ last = low; ++ ++ return (((grub_uint64_t) high) << 32) | low; ++} ++ ++void ++grub_timer_init (grub_uint32_t cpuclock) ++{ ++ grub_arch_cpuclock = cpuclock; ++ grub_install_get_time_ms (grub_rtc_get_time_ms); ++} +diff --git a/grub-core/lib/loongarch64/efi/loongson.c b/grub-core/lib/loongarch64/efi/loongson.c +new file mode 100644 +index 0000000..8b60d82 +--- /dev/null ++++ b/grub-core/lib/loongarch64/efi/loongson.c +@@ -0,0 +1,505 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define loongson_params (&loongson_boot_params->boot_params.efi.smbios.lp) ++#define loongson_boot_params_size ALIGN_UP (sizeof (*loongson_boot_params), 8) ++#define loongson_reset_code_size (&grub_efi_loongson_reset_end - &grub_efi_loongson_reset_start) ++ ++extern grub_uint8_t grub_efi_loongson_reset_start; ++extern grub_uint8_t grub_efi_loongson_reset_end; ++ ++static struct ++{ ++ grub_efi_loongson_boot_params boot_params; ++ grub_efi_loongson_memory_map memory_map; ++ grub_efi_loongson_cpu_info cpu_info; ++ grub_efi_loongson_system_info system_info; ++ grub_efi_loongson_irq_src_routing_table irq_src_routing_table; ++ grub_efi_loongson_interface_info interface_info; ++ grub_efi_loongson_special_attribute special_attribute; ++ grub_efi_loongson_board_devices board_devices; ++} GRUB_PACKED ++* loongson_boot_params; ++ ++static void ++grub_efi_loongson_init_reset_system (void) ++{ ++ grub_efi_loongson_boot_params *boot_params; ++ grub_uint8_t *reset_code_addr = (grub_uint8_t *) loongson_boot_params + ++ loongson_boot_params_size; ++ ++ boot_params = &loongson_boot_params->boot_params; ++ grub_efi_loongson_reset_system_addr = ++ (grub_uint64_t) grub_efi_system_table->runtime_services->reset_system; ++ grub_memcpy (reset_code_addr, &grub_efi_loongson_reset_start, loongson_reset_code_size); ++ grub_arch_sync_caches (reset_code_addr, loongson_reset_code_size); ++ ++ boot_params->reset_system.reset_cold = (grub_uint64_t) reset_code_addr + ++ ((grub_uint64_t) &grub_efi_loongson_reset_cold - ++ (grub_uint64_t) &grub_efi_loongson_reset_start); ++ boot_params->reset_system.reset_warm = (grub_uint64_t) reset_code_addr + ++ ((grub_uint64_t) &grub_efi_loongson_reset_warm - ++ (grub_uint64_t) &grub_efi_loongson_reset_start); ++ boot_params->reset_system.shutdown = (grub_uint64_t) reset_code_addr + ++ ((grub_uint64_t) &grub_efi_loongson_reset_shutdown - ++ (grub_uint64_t) &grub_efi_loongson_reset_start); ++ boot_params->reset_system.do_suspend = (grub_uint64_t) reset_code_addr + ++ ((grub_uint64_t) &grub_efi_loongson_reset_suspend - ++ (grub_uint64_t) &grub_efi_loongson_reset_start); ++} ++ ++static void ++grub_efi_loongson_init_smbios (grub_efi_loongson_smbios_table *smbios_table) ++{ ++ grub_efi_loongson_smbios_table *dst = &loongson_boot_params->boot_params.efi.smbios; ++ ++ dst->vers = smbios_table->vers; ++ dst->vga_bios = smbios_table->vga_bios; ++} ++ ++static void ++grub_efi_loongson_init_cpu_info (grub_efi_loongson_smbios_table *smbios_table) ++{ ++ grub_efi_loongson_cpu_info *src = (void *) smbios_table->lp.cpu_offset; ++ grub_efi_loongson_cpu_info *dst = &loongson_boot_params->cpu_info; ++ ++ if (!src) ++ return; ++ ++ grub_memcpy (dst, src, sizeof (grub_efi_loongson_cpu_info)); ++ loongson_params->cpu_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; ++} ++ ++static void ++grub_efi_loongson_init_system_info (grub_efi_loongson_smbios_table *smbios_table) ++{ ++ grub_efi_loongson_system_info *src = (void *) smbios_table->lp.system_offset; ++ grub_efi_loongson_system_info *dst = &loongson_boot_params->system_info; ++ ++ if (!src) ++ return; ++ ++ grub_memcpy (dst, src, sizeof (grub_efi_loongson_system_info)); ++ loongson_params->system_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; ++} ++ ++static void ++grub_efi_loongson_init_irq_src_routing_table (grub_efi_loongson_smbios_table *smbios_table) ++{ ++ grub_efi_loongson_irq_src_routing_table *src = (void *) smbios_table->lp.irq_offset; ++ grub_efi_loongson_irq_src_routing_table *dst = &loongson_boot_params->irq_src_routing_table; ++ ++ if (!src) ++ return; ++ ++ grub_memcpy (dst, src, sizeof (grub_efi_loongson_irq_src_routing_table)); ++ loongson_params->irq_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; ++} ++ ++static void ++grub_efi_loongson_init_interface_info (grub_efi_loongson_smbios_table *smbios_table) ++{ ++ grub_efi_loongson_interface_info *src = (void *) smbios_table->lp.interface_offset; ++ grub_efi_loongson_interface_info *dst = &loongson_boot_params->interface_info; ++ ++ if (!src) ++ return; ++ ++ grub_memcpy (dst, src, sizeof (grub_efi_loongson_interface_info)); ++ loongson_params->interface_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; ++} ++ ++static void ++grub_efi_loongson_init_special_attribute (grub_efi_loongson_smbios_table *smbios_table) ++{ ++ grub_efi_loongson_special_attribute *src = (void *) smbios_table->lp.special_offset; ++ grub_efi_loongson_special_attribute *dst = &loongson_boot_params->special_attribute; ++ ++ if (!src) ++ return; ++ ++ grub_memcpy (dst, src, sizeof (grub_efi_loongson_special_attribute)); ++ loongson_params->special_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; ++} ++ ++static void ++grub_efi_loongson_init_board_devices (grub_efi_loongson_smbios_table *smbios_table) ++{ ++ grub_efi_loongson_board_devices *src = (void *) smbios_table->lp.boarddev_table_offset; ++ grub_efi_loongson_board_devices *dst = &loongson_boot_params->board_devices; ++ ++ if (!src) ++ return; ++ ++ grub_memcpy (dst, src, sizeof (grub_efi_loongson_board_devices)); ++ loongson_params->boarddev_table_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; ++} ++ ++#define ADD_MEMORY_DESCRIPTOR(desc, size) \ ++ ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) ++ ++static void ++grub_efi_loongson_init_memory_map (grub_efi_loongson_smbios_table *smbios_table, ++ grub_efi_memory_descriptor_t *mmap_buf, ++ grub_efi_uintn_t mmap_size, ++ grub_efi_uintn_t desc_size) ++{ ++ grub_efi_loongson_memory_map *src = (void *) smbios_table->lp.memory_offset; ++ grub_efi_loongson_memory_map *dst = &loongson_boot_params->memory_map; ++ grub_efi_memory_descriptor_t *mmap_end; ++ grub_efi_memory_descriptor_t *desc; ++ grub_efi_memory_descriptor_t *desc_next; ++ grub_efi_uint32_t mem_types_reserved[] = ++ { ++ 1, // GRUB_EFI_RESERVED_MEMORY_TYPE ++ 0, // GRUB_EFI_LOADER_CODE ++ 0, // GRUB_EFI_LOADER_DATA ++ 0, // GRUB_EFI_BOOT_SERVICES_CODE ++ 0, // GRUB_EFI_BOOT_SERVICES_DATA ++ 1, // GRUB_EFI_RUNTIME_SERVICES_CODE ++ 1, // GRUB_EFI_RUNTIME_SERVICES_DATA ++ 0, // GRUB_EFI_CONVENTIONAL_MEMORY ++ 1, // GRUB_EFI_UNUSABLE_MEMORY ++ 0, // GRUB_EFI_ACPI_RECLAIM_MEMORY ++ 0, // GRUB_EFI_ACPI_MEMORY_NVS ++ 1, // GRUB_EFI_MEMORY_MAPPED_IO ++ 1, // GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE ++ 1, // GRUB_EFI_PAL_CODE ++ 1, // GRUB_EFI_PERSISTENT_MEMORY ++ }; ++ grub_uint32_t need_sort = 1; ++ ++ if (!src) ++ return; ++ ++ dst->vers = src->vers; ++ dst->nr_map = 0; ++ dst->mem_freq = src->mem_freq; ++ loongson_params->memory_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; ++ ++ if (!mmap_buf || !mmap_size || !desc_size) ++ return; ++ ++ mmap_end = ADD_MEMORY_DESCRIPTOR (mmap_buf, mmap_size); ++ ++ /* drop reserved */ ++ for (desc = mmap_buf, ++ desc_next = desc; ++ desc < mmap_end; ++ desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size)) ++ { ++ desc->type = mem_types_reserved[desc->type]; ++ if (desc->type) ++ continue; ++ ++ if (desc != desc_next) ++ *desc_next = *desc; ++ desc_next = ADD_MEMORY_DESCRIPTOR (desc_next, desc_size); ++ } ++ mmap_end = desc_next; ++ ++ /* sort: low->high */ ++ while (need_sort) ++ { ++ need_sort = 0; ++ ++ for (desc = mmap_buf, ++ desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size); ++ (desc < mmap_end) && (desc_next < mmap_end); ++ desc = desc_next, ++ desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size)) ++ { ++ grub_efi_memory_descriptor_t tmp; ++ ++ if (desc->physical_start <= desc_next->physical_start) ++ continue; ++ ++ tmp = *desc; ++ *desc = *desc_next; ++ *desc_next = tmp; ++ need_sort = 1; ++ } ++ } ++ ++ /* combine continuous memory map */ ++ for (desc = mmap_buf, ++ desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size); ++ desc_next < mmap_end; ++ desc_next = ADD_MEMORY_DESCRIPTOR (desc_next, desc_size)) ++ { ++ grub_efi_physical_address_t prev_end = desc->physical_start + (desc->num_pages << 12); ++ ++ if (prev_end == desc_next->physical_start) ++ { ++ desc->num_pages += desc_next->num_pages; ++ continue; ++ } ++ ++ desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size); ++ grub_memcpy (desc, desc_next, desc_size); ++ } ++ mmap_end = ADD_MEMORY_DESCRIPTOR (desc, desc_size); ++ ++ /* write to loongson memory map */ ++ for (desc = mmap_buf; ++ desc < mmap_end; ++ desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size)) ++ { ++ grub_efi_physical_address_t physical_start = grub_vtop ((void *) desc->physical_start); ++ grub_efi_physical_address_t physical_end = physical_start + (desc->num_pages << 12); ++ ++ physical_start = ALIGN_UP (physical_start, 0x100000); ++ physical_end = ALIGN_DOWN (physical_end, 0x100000); ++ ++ if (physical_start >= physical_end || (physical_end - physical_start) < 0x100000) ++ continue; ++ ++ dst->map[dst->nr_map].node_id = (desc->physical_start >> 44) & 0xf; ++ dst->map[dst->nr_map].mem_type = GRUB_EFI_LOONGSON_SYSTEM_RAM; ++ dst->map[dst->nr_map].mem_start = physical_start; ++ dst->map[dst->nr_map].mem_size = (physical_end - physical_start) >> 20; ++ ++ grub_dprintf ("loongson", "memory map %03u: 0x%016lx 0x%016lx @ %u\n", ++ dst->nr_map, physical_start, physical_end - physical_start, ++ dst->map[dst->nr_map].node_id); ++ ++ dst->nr_map ++; ++ } ++} ++ ++#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) ++#define SUB_MEMORY_DESCRIPTOR(desc, size) \ ++ ((grub_efi_memory_descriptor_t *) ((char *) (desc) - (size))) ++ ++void ++grub_efi_loongson_alloc_boot_params (void) ++{ ++ grub_efi_memory_descriptor_t *mmap_buf; ++ grub_efi_memory_descriptor_t *mmap_end; ++ grub_efi_memory_descriptor_t *desc; ++ grub_efi_uintn_t mmap_size; ++ grub_efi_uintn_t desc_size; ++ grub_efi_physical_address_t address; ++ grub_efi_allocate_type_t type; ++ grub_efi_uintn_t pages; ++ grub_efi_status_t status; ++ grub_efi_boot_services_t *b; ++ int mm_status; ++ ++ type = GRUB_EFI_ALLOCATE_ADDRESS; ++ pages = BYTES_TO_PAGES (loongson_boot_params_size + loongson_reset_code_size); ++ ++ mmap_size = (1 << 12); ++ mmap_buf = grub_malloc (mmap_size); ++ if (!mmap_buf) ++ grub_fatal ("out of memory!"); ++ ++ mm_status = grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0); ++ if (mm_status == 0) ++ { ++ grub_free (mmap_buf); ++ mmap_size += desc_size * 32; ++ ++ mmap_buf = grub_malloc (mmap_size); ++ if (!mmap_buf) ++ grub_fatal ("out of memory!"); ++ ++ mm_status = grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0); ++ } ++ ++ if (mm_status < 0) ++ grub_fatal ("cannot get memory map!"); ++ ++ mmap_end = ADD_MEMORY_DESCRIPTOR (mmap_buf, mmap_size); ++ ++ for (desc = SUB_MEMORY_DESCRIPTOR (mmap_end, desc_size); ++ desc >= mmap_buf; ++ desc = SUB_MEMORY_DESCRIPTOR (desc, desc_size)) ++ { ++ if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY) ++ continue; ++ if (desc->physical_start >= grub_efi_max_usable_address()) ++ continue; ++ if (desc->num_pages < pages) ++ continue; ++ ++ address = desc->physical_start; ++ break; ++ } ++ ++ grub_free (mmap_buf); ++ ++ b = grub_efi_system_table->boot_services; ++ status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_RUNTIME_SERVICES_DATA, pages, &address); ++ if (status != GRUB_EFI_SUCCESS) ++ grub_fatal ("cannot allocate Loongson boot parameters!"); ++ ++ loongson_boot_params = (void *) ((grub_addr_t) address); ++} ++ ++void ++grub_efi_loongson_free_boot_params (void) ++{ ++ grub_efi_free_pages ((grub_addr_t) loongson_boot_params, ++ BYTES_TO_PAGES (loongson_boot_params_size + loongson_reset_code_size)); ++} ++ ++void * ++grub_efi_loongson_get_smbios_table (void) ++{ ++ static grub_efi_loongson_smbios_table *smbios_table; ++ grub_efi_loongson_boot_params *old_boot_params; ++ struct bootparamsinterface* boot_params; ++ void * tmp_boot_params = NULL; ++ char * p = NULL; ++ if(smbios_table) ++ return smbios_table; ++ ++ tmp_boot_params = grub_efi_loongson_get_boot_params(); ++ if(tmp_boot_params == NULL) ++ { ++ grub_dprintf("loongson", "tmp_boot_params is NULL\n"); ++ return tmp_boot_params; ++ } ++ ++ boot_params = (struct bootparamsinterface *)tmp_boot_params; ++ p = (char *)&(boot_params->signature); ++ if(grub_strncmp(p, "BPI", 3) == 0) ++ { ++ grub_dprintf("loongson", "find new bpi\n"); ++ return boot_params ? boot_params : 0; ++ } ++ else ++ { ++ old_boot_params = (grub_efi_loongson_boot_params *)tmp_boot_params; ++ /* ++ { ++ grub_dprintf("loongson", "smbios addr%llx\n", &old_boot_params->efi.smbios); ++ grub_dprintf("loongson", "smbios vers%d\n", (grub_uint16_t)(&old_boot_params->efi.smbios.vers)); ++ grub_dprintf("loongson", "smbios vga_bios%d\n", &old_boot_params->efi.smbios.vga_bios); ++ grub_dprintf("loongson", "lp memory offset %llx\n", &old_boot_params->efi.smbios.lp.memory_offset); ++ grub_dprintf("loongson", "lp cpu offset %llx\n", &old_boot_params->efi.smbios.lp.cpu_offset); ++ grub_dprintf("loongson", "lp system offset %llx\n", &old_boot_params->efi.smbios.lp.system_offset); ++ grub_dprintf("loongson", "lp irq offset %llx\n", &old_boot_params->efi.smbios.lp.irq_offset); ++ grub_dprintf("loongson", "lp interface offset %llx\n", &old_boot_params->efi.smbios.p.interface_offset); ++ grub_dprintf("loongson", "lp special offset %llx\n", &old_boot_params->efi.smbios.lp.special_offset); ++ grub_dprintf("loongson", "lp boarddev table offset %llx\n", &old_boot_params->efi.smbios.lp.boarddev_table_offset); ++ } ++ */ ++ return old_boot_params ? &old_boot_params->efi.smbios : 0; ++ } ++ ++} ++ ++int ++grub_efi_is_loongson (void) ++{ ++ return grub_efi_loongson_get_smbios_table () ? 1 : 0; ++} ++ ++void * ++grub_efi_loongson_get_boot_params (void) ++{ ++ static void * boot_params = NULL; ++ grub_efi_configuration_table_t *tables; ++ grub_efi_guid_t smbios_guid = GRUB_EFI_LOONGSON_SMBIOS_TABLE_GUID; ++ unsigned int i; ++ ++ if (boot_params) ++ return boot_params; ++ ++ /* Look for Loongson SMBIOS in UEFI config tables. */ ++ tables = grub_efi_system_table->configuration_table; ++ ++ for (i = 0; i < grub_efi_system_table->num_table_entries; i++) ++ if (grub_memcmp (&tables[i].vendor_guid, &smbios_guid, sizeof (smbios_guid)) == 0) ++ { ++ boot_params= tables[i].vendor_table; ++ grub_dprintf ("loongson", "found registered SMBIOS @ %p\n", boot_params); ++ break; ++ } ++ return boot_params; ++} ++ ++grub_uint8_t ++grub_efi_loongson_calculatesum8 (const grub_uint8_t *buffer, grub_efi_uintn_t length) ++{ ++ grub_uint8_t sum; ++ grub_efi_uintn_t count; ++ ++ for (sum = 0, count = 0; count < length; count++) ++ { ++ sum = (grub_uint8_t) (sum + *(buffer + count)); ++ } ++ return sum; ++} ++ ++grub_uint8_t ++grub_efi_loongson_grub_calculatechecksum8 (const grub_uint8_t *buffer, grub_efi_uintn_t length) ++{ ++ grub_uint8_t checksum; ++ ++ checksum = grub_efi_loongson_calculatesum8(buffer, length); ++ ++ return (grub_uint8_t) (0x100 - checksum); ++} ++ ++ ++grub_uint32_t ++grub_efi_loongson_memmap_sort(struct memmap array[], grub_uint32_t length, mem_map * bpmem, grub_uint32_t index, grub_uint32_t memtype) ++{ ++ grub_uint64_t tempmemsize = 0; ++ grub_uint32_t j = 0; ++ grub_uint32_t t = 0; ++ ++ for(j = 0; j < length;) ++ { ++ tempmemsize = array[j].memsize; ++ for(t = j + 1; t < length; t++) ++ { ++ if(array[j].memstart + tempmemsize == array[t].memstart) ++ { ++ tempmemsize += array[t].memsize; ++ } ++ else ++ { ++ break; ++ } ++ } ++ bpmem->map[index].memtype = memtype; ++ bpmem->map[index].memstart = array[j].memstart; ++ bpmem->map[index].memsize = tempmemsize; ++ grub_dprintf("loongson", "map[%d]:type %x, start 0x%llx, end 0x%llx\n", ++ index, ++ bpmem->map[index].memtype, ++ bpmem->map[index].memstart, ++ bpmem->map[index].memstart+ bpmem->map[index].memsize ++ ); ++ j = t; ++ index++; ++ } ++ return index; ++} ++ +diff --git a/grub-core/lib/loongarch64/efi/loongson_asm.S b/grub-core/lib/loongarch64/efi/loongson_asm.S +new file mode 100644 +index 0000000..4a04d34 +--- /dev/null ++++ b/grub-core/lib/loongarch64/efi/loongson_asm.S +@@ -0,0 +1,58 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++ ++ .file "loongson_asm.S" ++ .text ++ ++ .align 4 ++ ++VARIABLE (grub_efi_loongson_reset_start) ++ ++VARIABLE (grub_efi_loongson_reset_system_addr) ++ .dword 0 ++ ++reset_system: ++ bl 1f ++ move $a1, $zero ++1: ++ ld.d $t8, $ra, -16 ++ move $a2, $zero ++ jr $t8 ++ move $a3, $zero ++ ++FUNCTION(grub_efi_loongson_reset_cold) ++ b reset_system ++ li.w $a0, 0 ++ ++FUNCTION(grub_efi_loongson_reset_warm) ++ b reset_system ++ li.w $a0, 1 ++ ++FUNCTION(grub_efi_loongson_reset_shutdown) ++ b reset_system ++ li.w $a0, 2 ++ ++FUNCTION(grub_efi_loongson_reset_suspend) ++ b reset_system ++ li.w $a0, 3 ++ ++VARIABLE (grub_efi_loongson_reset_end) ++ ++ +diff --git a/grub-core/lib/loongarch64/relocator.c b/grub-core/lib/loongarch64/relocator.c +new file mode 100644 +index 0000000..f6c1b01 +--- /dev/null ++++ b/grub-core/lib/loongarch64/relocator.c +@@ -0,0 +1,163 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++extern grub_uint8_t grub_relocator_forward_start; ++extern grub_uint8_t grub_relocator_forward_end; ++extern grub_uint8_t grub_relocator_backward_start; ++extern grub_uint8_t grub_relocator_backward_end; ++ ++#define REGW_SIZEOF (4 * sizeof (grub_uint32_t)) ++#define JUMP_SIZEOF (2 * sizeof (grub_uint32_t)) ++ ++#define RELOCATOR_SRC_SIZEOF(x) (&grub_relocator_##x##_end \ ++ - &grub_relocator_##x##_start) ++#define RELOCATOR_SIZEOF(x) (RELOCATOR_SRC_SIZEOF(x) \ ++ + REGW_SIZEOF * 3) ++grub_size_t grub_relocator_align = sizeof (grub_uint64_t); ++grub_size_t grub_relocator_forward_size; ++grub_size_t grub_relocator_backward_size; ++grub_size_t grub_relocator_jumper_size = JUMP_SIZEOF + REGW_SIZEOF; ++ ++void ++grub_cpu_relocator_init (void) ++{ ++ grub_relocator_forward_size = RELOCATOR_SIZEOF(forward); ++ grub_relocator_backward_size = RELOCATOR_SIZEOF(backward); ++} ++ ++static void ++write_reg (int regn, grub_uint64_t val, void **target) ++{ ++ grub_uint32_t lu12iw=0x14000000; ++ grub_uint32_t ori=0x03800000; ++ grub_uint32_t lu32id=0x16000000; ++ grub_uint32_t lu52id=0x03000000; ++ ++ *(grub_uint32_t *) *target = (lu12iw | (grub_uint32_t)((val & 0xfffff000)>>12<<5) | (grub_uint32_t)regn);; ++ *target = ((grub_uint32_t *) *target) + 1; ++ *(grub_uint32_t *) *target = (ori | (grub_uint32_t)((val & 0xfff)<<10) | (grub_uint32_t)(regn | regn<<5)); ++ *target = ((grub_uint32_t *) *target) + 1; ++ *(grub_uint32_t *) *target = (lu32id | (grub_uint32_t)((val & 0xfffff00000000)>>32<<5) | (grub_uint32_t)regn);; ++ *target = ((grub_uint32_t *) *target) + 1; ++ *(grub_uint32_t *) *target = (lu52id | (grub_uint32_t)((val & 0xfff0000000000000)>>52<<10) | (grub_uint32_t)(regn | regn<<5));; ++ *target = ((grub_uint32_t *) *target) + 1; ++} ++ ++static void ++write_jump (int regn, void **target) ++{ ++ grub_uint32_t andi=0x4c000000; ++ grub_uint32_t nop=0x03400000; ++ ++ *(grub_uint32_t *) *target = (andi | (grub_uint32_t)(regn<<5)); ++ *target = ((grub_uint32_t *) *target) + 1; ++ *(grub_uint32_t *) *target = nop; ++ *target = ((grub_uint32_t *) *target) + 1; ++} ++ ++void ++grub_cpu_relocator_jumper (void *rels, grub_addr_t addr) ++{ ++ write_reg (1, addr, &rels); ++ write_jump (1, &rels); ++} ++ ++void ++grub_cpu_relocator_backward (void *ptr0, void *src, void *dest, ++ grub_size_t size) ++{ ++ void *ptr = ptr0; ++ write_reg (8, (grub_uint64_t) src, &ptr); ++ write_reg (9, (grub_uint64_t) dest, &ptr); ++ write_reg (10, (grub_uint64_t) size, &ptr); ++ grub_memcpy (ptr, &grub_relocator_backward_start, ++ RELOCATOR_SRC_SIZEOF (backward)); ++} ++ ++void ++grub_cpu_relocator_forward (void *ptr0, void *src, void *dest, ++ grub_size_t size) ++{ ++ void *ptr = ptr0; ++ write_reg (8, (grub_uint64_t) src, &ptr); ++ write_reg (9, (grub_uint64_t) dest, &ptr); ++ write_reg (10, (grub_uint64_t) size, &ptr); ++ grub_memcpy (ptr, &grub_relocator_forward_start, ++ RELOCATOR_SRC_SIZEOF (forward)); ++} ++ ++grub_err_t ++grub_relocator64_boot (struct grub_relocator *rel, ++ struct grub_relocator64_state state) ++{ ++ grub_relocator_chunk_t ch; ++ void *ptr; ++ grub_err_t err; ++ void *relst; ++ grub_size_t relsize; ++ grub_size_t stateset_size = 31 * REGW_SIZEOF + JUMP_SIZEOF; ++ unsigned i; ++ grub_addr_t vtarget; ++ ++ err = grub_relocator_alloc_chunk_align (rel, &ch, 0, ++ (0xffffffff - stateset_size) ++ + 1, stateset_size, ++ grub_relocator_align, ++ GRUB_RELOCATOR_PREFERENCE_NONE, 0); ++ if (err) ++ return err; ++ ++ ptr = get_virtual_current_address (ch); ++ for (i = 1; i < 32; i++) ++ write_reg (i, state.gpr[i], &ptr); ++ write_jump (state.jumpreg, &ptr); ++ ++ vtarget = (grub_addr_t) grub_map_memory (get_physical_target_address (ch), ++ stateset_size); ++ ++ err = grub_relocator_prepare_relocs (rel, vtarget, &relst, &relsize); ++ if (err) ++ return err; ++ ++ grub_arch_sync_caches ((void *) relst, relsize); ++ ++ grub_uint64_t val; ++ __asm__ __volatile__( ++ "li.w %0, 0x4\n\t" ++ "csrxchg $r0, %0, 0x0\n\t" ++ : "=r"(val) ++ : ++ : ++ ); ++ ++ ((void (*) (void)) relst) (); ++ ++ /* Not reached. */ ++ return GRUB_ERR_NONE; ++} +diff --git a/grub-core/lib/loongarch64/relocator_asm.S b/grub-core/lib/loongarch64/relocator_asm.S +new file mode 100644 +index 0000000..cf1724d +--- /dev/null ++++ b/grub-core/lib/loongarch64/relocator_asm.S +@@ -0,0 +1,51 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++ ++ .p2align 4 /* force 16-byte alignment */ ++ ++VARIABLE (grub_relocator_forward_start) ++ ++copycont1: ++ ld.d $r11,$r8,0 ++ st.d $r11,$r9,0 ++ addi.d $r8, $r8, 8 ++ addi.d $r10, $r10, -8 ++ addi.d $r9, $r9, 8 ++ bne $r10, $r0, copycont1 ++ ++VARIABLE (grub_relocator_forward_end) ++ ++VARIABLE (grub_relocator_backward_start) ++ ++ add.d $r9, $r9, $r10 ++ add.d $r8, $r8, $r10 ++ /* Backward movsl is implicitly off-by-one. compensate that. */ ++ addi.d $r9, $r9, -8 ++ addi.d $r8, $r8, -8 ++copycont2: ++ ld.w $r11,$r8,0 ++ st.w $r11,$r9,0 ++ addi.d $r8, $r8, -8 ++ addi.d $r10, $r10, -8 ++ addi.d $r9, $r9, -8 ++ bne $r10, $r0, copycont2 ++ ++VARIABLE (grub_relocator_backward_end) ++ +diff --git a/grub-core/lib/loongarch64/setjmp.S b/grub-core/lib/loongarch64/setjmp.S +new file mode 100644 +index 0000000..47db814 +--- /dev/null ++++ b/grub-core/lib/loongarch64/setjmp.S +@@ -0,0 +1,74 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2003,2007,2009 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++ ++ .file "setjmp.S" ++ ++GRUB_MOD_LICENSE "GPLv3+" ++ ++ .text ++ ++/* ++ * int grub_setjmp (grub_jmp_buf env) ++ */ ++FUNCTION(grub_setjmp) ++ GRUB_ASM_REG_S $s0, $a0,0 ++ GRUB_ASM_REG_S $s1, $a0,8 ++ GRUB_ASM_REG_S $s2, $a0,16 ++ GRUB_ASM_REG_S $s3, $a0,24 ++ GRUB_ASM_REG_S $s4, $a0,32 ++ GRUB_ASM_REG_S $s5, $a0,40 ++ GRUB_ASM_REG_S $s6, $a0,48 ++ GRUB_ASM_REG_S $s7, $a0,56 ++ GRUB_ASM_REG_S $s8, $a0,64 ++ GRUB_ASM_REG_S $fp, $a0,72 ++ GRUB_ASM_REG_S $sp, $a0,80 ++ GRUB_ASM_REG_S $ra, $a0,88 ++ move $v0, $zero ++ move $v1, $zero ++ jr $ra ++ nop ++/* ++ * int grub_longjmp (grub_jmp_buf env, int val) ++ */ ++FUNCTION(grub_longjmp) ++ GRUB_ASM_REG_L $s0, $a0,0 ++ GRUB_ASM_REG_L $s1, $a0,8 ++ GRUB_ASM_REG_L $s2, $a0,16 ++ GRUB_ASM_REG_L $s3, $a0,24 ++ GRUB_ASM_REG_L $s4, $a0,32 ++ GRUB_ASM_REG_L $s5, $a0,40 ++ GRUB_ASM_REG_L $s6, $a0,48 ++ GRUB_ASM_REG_L $s7, $a0,56 ++ GRUB_ASM_REG_L $s8, $a0,64 ++ GRUB_ASM_REG_L $fp, $a0,72 ++ GRUB_ASM_REG_L $sp, $a0,80 ++ GRUB_ASM_REG_L $ra, $a0,88 ++ addi.w $v0, $zero, 1 ++ /* ++ * replace: movn $v0, $a1, $a1 ++ */ ++ bnez $a1, .ZW0 ++ addi.d $v0, $a1, 0 ++.ZW0: ++ addi.d $v1,$zero,0 ++ jr $ra ++ nop +diff --git a/grub-core/lib/loongson/reboot.c b/grub-core/lib/loongson/reboot.c +new file mode 100644 +index 0000000..107787a +--- /dev/null ++++ b/grub-core/lib/loongson/reboot.c +@@ -0,0 +1,33 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2011 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++void ++grub_la_reboot (void) ++{ ++ grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); ++ efi_call_4 (grub_efi_system_table->runtime_services->reset_system, ++ GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL); ++ for (;;) ; ++} +diff --git a/grub-core/lib/setjmp.S b/grub-core/lib/setjmp.S +index f6e4905..023dc90 100644 +--- a/grub-core/lib/setjmp.S ++++ b/grub-core/lib/setjmp.S +@@ -15,6 +15,8 @@ + #include "./arm/setjmp.S" + #elif defined(__aarch64__) + #include "./arm64/setjmp.S" ++#elif defined(__loongarch64) ++#include "./loongarch64/setjmp.S" + #else + #error "Unknown target cpu type" + #endif +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 29663f7..c0ca17d 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -332,6 +332,8 @@ static const grub_uint16_t machine_type __attribute__((__unused__)) = + GRUB_PE32_MACHINE_I386; + #elif defined(__ia64__) + GRUB_PE32_MACHINE_IA64; ++#elif defined(__loongarch64) ++ GRUB_PE32_MACHINE_LOONGARCH64; + #else + #error this architecture is not supported by grub2 + #endif +diff --git a/grub-core/loader/loongarch64/linux.c b/grub-core/loader/loongarch64/linux.c +new file mode 100644 +index 0000000..c769bb2 +--- /dev/null ++++ b/grub-core/loader/loongarch64/linux.c +@@ -0,0 +1,580 @@ ++/* linux.c - boot Linux */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2003,2004,2005,2007,2009,2010,2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++#pragma GCC diagnostic ignored "-Wcast-align" ++ ++typedef unsigned long size_t; ++ ++static grub_dl_t my_mod; ++ ++static int loaded; ++ ++static grub_uint32_t tmp_index = 0; ++static grub_size_t linux_size; ++ ++static struct grub_relocator *relocator; ++static grub_addr_t target_addr, entry_addr; ++static int linux_argc; ++static grub_uint8_t *linux_args_addr; ++static grub_off_t rd_addr_arg_off, rd_size_arg_off; ++static grub_off_t initrd_addr_arg_off; ++static int initrd_loaded = 0; ++ ++ ++static grub_uint32_t j = 0; ++static grub_uint32_t t = 0; ++grub_uint64_t tempMemsize = 0; ++grub_uint32_t free_index = 0; ++grub_uint32_t reserve_index = 0; ++grub_uint32_t acpi_table_index = 0; ++grub_uint32_t acpi_nvs_index = 0; ++ ++static inline grub_size_t ++page_align (grub_size_t size) ++{ ++ return (size + (1 << 12) - 1) & (~((1 << 12) - 1)); ++} ++ ++/* Find the optimal number of pages for the memory map. Is it better to ++ move this code to efi/mm.c? */ ++static grub_efi_uintn_t ++find_mmap_size (void) ++{ ++ static grub_efi_uintn_t mmap_size = 0; ++ ++ if (mmap_size != 0) ++ return mmap_size; ++ ++ mmap_size = (1 << 12); ++ while (1) ++ { ++ int ret; ++ grub_efi_memory_descriptor_t *mmap; ++ grub_efi_uintn_t desc_size; ++ ++ mmap = grub_malloc (mmap_size); ++ if (! mmap) ++ return 0; ++ ++ ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0); ++ grub_free (mmap); ++ ++ if (ret < 0) ++ { ++ grub_error (GRUB_ERR_IO, "cannot get memory map"); ++ return 0; ++ } ++ else if (ret > 0) ++ break; ++ ++ mmap_size += (1 << 12); ++ } ++ ++ ++ /* Increase the size a bit for safety, because GRUB allocates more on ++ later, and EFI itself may allocate more. */ ++ mmap_size += (1 << 12); ++ ++ return page_align (mmap_size); ++} ++ ++static grub_err_t ++grub_linux_boot (void) ++{ ++ struct grub_relocator64_state state; ++ grub_int8_t checksum = 0; ++ grub_efi_memory_descriptor_t * lsdesc = NULL; ++ ++ grub_memset (&state, 0, sizeof (state)); ++ ++ /* Boot the kernel. */ ++ state.gpr[1] = entry_addr; ++ grub_dprintf("loongson", "entry_addr is %p\n", state.gpr[1]); ++ state.gpr[4] = linux_argc; ++ grub_dprintf("loongson", "linux_argc is %d\n", state.gpr[4]); ++ state.gpr[5] = (grub_addr_t) linux_args_addr; ++ grub_dprintf("loongson", "args_addr is %p\n", state.gpr[5]); ++ ++ if(grub_efi_is_loongson ()) ++ { ++ grub_efi_uintn_t mmap_size; ++ grub_efi_uintn_t desc_size; ++ grub_efi_memory_descriptor_t *mmap_buf; ++ grub_err_t err; ++ struct bootparamsinterface * boot_params; ++ void * tmp_boot_params = NULL; ++ grub_efi_uint8_t new_interface_flag = 0; ++ mem_map * new_interface_mem = NULL; ++ char *p = NULL; ++ ++ struct memmap reserve_mem[GRUB_EFI_LOONGSON_MMAP_MAX]; ++ struct memmap free_mem[GRUB_EFI_LOONGSON_MMAP_MAX]; ++ struct memmap acpi_table_mem[GRUB_EFI_LOONGSON_MMAP_MAX]; ++ struct memmap acpi_nvs_mem[GRUB_EFI_LOONGSON_MMAP_MAX]; ++ ++ grub_memset(reserve_mem, 0, sizeof(struct memmap) * GRUB_EFI_LOONGSON_MMAP_MAX); ++ grub_memset(free_mem, 0, sizeof(struct memmap) * GRUB_EFI_LOONGSON_MMAP_MAX); ++ grub_memset(acpi_table_mem, 0, sizeof(struct memmap) * GRUB_EFI_LOONGSON_MMAP_MAX); ++ grub_memset(acpi_nvs_mem, 0, sizeof(struct memmap) * GRUB_EFI_LOONGSON_MMAP_MAX); ++ ++ tmp_boot_params = grub_efi_loongson_get_boot_params(); ++ if(tmp_boot_params == NULL) ++ { ++ grub_printf("not find param\n"); ++ return -1; ++ } ++ ++ boot_params = (struct bootparamsinterface *)tmp_boot_params; ++ p = (char *)&(boot_params->signature); ++ if(grub_strncmp(p, "BPI", 3) == 0) ++ { ++ /* Check extlist headers */ ++ ext_list * listpointer = NULL; ++ listpointer = boot_params->extlist; ++ for( ;listpointer != NULL; listpointer = listpointer->next) ++ { ++ char *pl= (char *)&(listpointer->signature); ++ if(grub_strncmp(pl, "MEM", 3) == 0) ++ { ++ new_interface_mem = (mem_map *)listpointer; ++ } ++ } ++ ++ new_interface_flag = 1; ++ grub_dprintf("loongson", "get new parameter interface\n"); ++ }else{ ++ new_interface_flag = 0; ++ grub_dprintf("loongson", "get old parameter interface\n"); ++ } ++ state.gpr[6] = (grub_uint64_t)tmp_boot_params; ++ grub_dprintf("loongson", "boot_params is %p\n", state.gpr[6]); ++ ++ mmap_size = find_mmap_size (); ++ if (! mmap_size) ++ return grub_errno; ++ mmap_buf = grub_efi_allocate_any_pages (page_align (mmap_size) >> 12); ++ if (! mmap_buf) ++ return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); ++ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, ++ &desc_size, NULL); ++ if (err) ++ return err; ++ ++ if(new_interface_flag) ++ { ++ if (!mmap_buf || !mmap_size || !desc_size) ++ return -1; ++ tmp_index = new_interface_mem -> mapcount; ++ ++ /* ++ According to UEFI SPEC,mmap_buf is the accurate Memory Map array \ ++ now we can fill platform specific memory structure. ++ */ ++ for(lsdesc = mmap_buf; lsdesc < (grub_efi_memory_descriptor_t *)((char *)mmap_buf + mmap_size); ++ lsdesc = (grub_efi_memory_descriptor_t *)((char *)lsdesc + desc_size)) ++ { ++ /* Recovery */ ++ if((lsdesc->type != GRUB_EFI_ACPI_RECLAIM_MEMORY) && \ ++ (lsdesc->type != GRUB_EFI_ACPI_MEMORY_NVS) && \ ++ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_DATA) && \ ++ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_CODE) && \ ++ (lsdesc->type != GRUB_EFI_RESERVED_MEMORY_TYPE) && \ ++ (lsdesc->type != GRUB_EFI_PAL_CODE)) ++ { ++ free_mem[free_index].memtype = GRUB_EFI_LOONGSON_SYSTEM_RAM; ++ free_mem[free_index].memstart = (lsdesc->physical_start) & 0xffffffffffff; ++ free_mem[free_index].memsize = lsdesc->num_pages * 4096; ++ free_index++; ++ ++ /*ACPI*/ ++ }else if((lsdesc->type == GRUB_EFI_ACPI_RECLAIM_MEMORY)){ ++ acpi_table_mem[acpi_table_index].memtype = GRUB_EFI_LOONGSON_ACPI_TABLE; ++ acpi_table_mem[acpi_table_index].memstart = (lsdesc->physical_start) & 0xffffffffffff; ++ acpi_table_mem[acpi_table_index].memsize = lsdesc->num_pages * 4096; ++ acpi_table_index++; ++ }else if((lsdesc->type == GRUB_EFI_ACPI_MEMORY_NVS)){ ++ acpi_nvs_mem[acpi_nvs_index].memtype = GRUB_EFI_LOONGSON_ACPI_NVS; ++ acpi_nvs_mem[acpi_nvs_index].memstart = (lsdesc->physical_start) & 0xffffffffffff; ++ acpi_nvs_mem[acpi_nvs_index].memsize = lsdesc->num_pages * 4096; ++ acpi_nvs_index++; ++ ++ /* Reserve */ ++ }else{ ++ reserve_mem[reserve_index].memtype = GRUB_EFI_LOONGSON_MEMORY_RESERVED; ++ reserve_mem[reserve_index].memstart = (lsdesc->physical_start) & 0xffffffffffff; ++ reserve_mem[reserve_index].memsize = lsdesc->num_pages * 4096; ++ reserve_index++; ++ } ++ } ++ ++ /* Recovery sort */ ++ for(j = 0; j < free_index;) ++ { ++ tempMemsize = free_mem[j].memsize; ++ for(t = j + 1; t < free_index; t++) ++ { ++ if((free_mem[j].memstart + tempMemsize == free_mem[t].memstart) && (free_mem[j].memtype == free_mem[t].memtype)) ++ { ++ tempMemsize += free_mem[t].memsize; ++ }else{ ++ break; ++ } ++ } ++ ++ new_interface_mem->map[tmp_index].memtype = GRUB_EFI_LOONGSON_SYSTEM_RAM; ++ new_interface_mem->map[tmp_index].memstart = free_mem[j].memstart; ++ new_interface_mem->map[tmp_index].memsize = tempMemsize; ++ grub_dprintf("loongson", "map[%d]:type %x, start 0x%llx, end 0x%llx\n", ++ tmp_index, ++ new_interface_mem->map[tmp_index].memtype, ++ new_interface_mem->map[tmp_index].memstart, ++ new_interface_mem->map[tmp_index].memstart+ new_interface_mem->map[tmp_index].memsize ++ ); ++ j = t; ++ tmp_index++; ++ } ++ /*ACPI Sort*/ ++ tmp_index = grub_efi_loongson_memmap_sort(acpi_table_mem, acpi_table_index, new_interface_mem, tmp_index, GRUB_EFI_LOONGSON_ACPI_TABLE); ++ tmp_index = grub_efi_loongson_memmap_sort(acpi_nvs_mem, acpi_nvs_index, new_interface_mem, tmp_index, GRUB_EFI_LOONGSON_ACPI_NVS); ++ /*Reserve Sort*/ ++ grub_uint64_t loongarch_addr; ++ asm volatile ("csrrd %0, 0x181" : "=r" (loongarch_addr)); ++ if((loongarch_addr & 0xff00000000000000) == 0x9000000000000000){ ++ tmp_index = grub_efi_loongson_memmap_sort(reserve_mem, reserve_index, new_interface_mem, tmp_index, GRUB_EFI_LOONGSON_MEMORY_RESERVED); ++ }else{ ++ tmp_index = grub_efi_loongson_memmap_sort(reserve_mem, reserve_index, new_interface_mem, tmp_index, GRUB_EFI_LOONGSON_MEMORY_RESERVED + 1); ++ } ++ ++ new_interface_mem->mapcount = tmp_index; ++ new_interface_mem->header.checksum = 0; ++ ++ checksum = grub_efi_loongson_grub_calculatechecksum8(new_interface_mem, new_interface_mem->header.length); ++ new_interface_mem->header.checksum = checksum; ++ } ++ } ++ ++ state.jumpreg = 1; ++ grub_relocator64_boot (relocator, state); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_linux_unload (void) ++{ ++ grub_relocator_unload (relocator); ++ grub_dl_unref (my_mod); ++ ++ loaded = 0; ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_linux_load32 (grub_elf_t elf, const char *filename) ++{ ++ Elf32_Addr base; ++ grub_err_t err; ++ grub_uint8_t *playground; ++ ++ /* Linux's entry point incorrectly contains a virtual address. */ ++ entry_addr = elf->ehdr.ehdr32.e_entry; ++ ++ linux_size = grub_elf32_size (elf, &base, 0); ++ if (linux_size == 0) ++ return grub_errno; ++ target_addr = base; ++ linux_size = ALIGN_UP (base + linux_size - base, 8); ++ ++ relocator = grub_relocator_new (); ++ if (!relocator) ++ return grub_errno; ++ ++ { ++ grub_relocator_chunk_t ch; ++ err = grub_relocator_alloc_chunk_addr (relocator, &ch, ++ grub_vtop ((void *) target_addr), ++ linux_size); ++ if (err) ++ return err; ++ playground = get_virtual_current_address (ch); ++ } ++ ++ /* Now load the segments into the area we claimed. */ ++ return grub_elf32_load (elf, filename, playground - base, GRUB_ELF_LOAD_FLAGS_NONE, 0, 0); ++} ++ ++static grub_err_t ++grub_linux_load64 (grub_elf_t elf, const char *filename) ++{ ++ Elf64_Addr base; ++ grub_err_t err; ++ grub_uint8_t *playground; ++ ++ /* Linux's entry point incorrectly contains a virtual address. */ ++ entry_addr = elf->ehdr.ehdr64.e_entry; ++ grub_dprintf("loongson", "entry address = %p\n", entry_addr); ++ ++ linux_size = grub_elf64_size (elf, &base, 0); ++ grub_dprintf("loongson", "base = %p\n", base); ++ ++ if (linux_size == 0) ++ return grub_errno; ++ target_addr = base; ++ linux_size = ALIGN_UP (base + linux_size - base, 8); ++ ++ relocator = grub_relocator_new (); ++ // linux_size=0x322fa80; ++ if (!relocator) ++ return grub_errno; ++ ++ { ++ grub_relocator_chunk_t ch; ++ err = grub_relocator_alloc_chunk_addr (relocator, &ch, ++ grub_vtop ((void *) target_addr), ++ linux_size); ++ if (err) ++ return err; ++ playground = get_virtual_current_address (ch); ++ } ++ ++ /* Now load the segments into the area we claimed. */ ++ return grub_elf64_load (elf, filename, playground - base, GRUB_ELF_LOAD_FLAGS_NONE, 0, 0); ++} ++ ++static grub_err_t ++grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char *argv[]) ++{ ++ grub_elf_t elf = 0; ++ int size; ++ int i; ++ grub_uint64_t *linux_argv; ++ char *linux_args; ++ grub_err_t err; ++ ++ if (argc == 0) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ ++ elf = grub_elf_open (argv[0],GRUB_FILE_TYPE_LINUX_KERNEL); ++ if (! elf) ++ return grub_errno; ++ ++ if (elf->ehdr.ehdr32.e_type != ET_EXEC) ++ { ++ grub_elf_close (elf); ++ return grub_error (GRUB_ERR_UNKNOWN_OS, ++ N_("this ELF file is not of the right type")); ++ } ++ ++ /* Release the previously used memory. */ ++ grub_loader_unset (); ++ loaded = 0; ++ ++ /* For arguments. */ ++ linux_argc = argc; ++ /* Main arguments. */ ++ size = (linux_argc) * sizeof (grub_uint64_t); ++ /* Initrd address and size. */ ++ size += 3 * sizeof (grub_uint64_t); ++ /* NULL terminator. */ ++ size += sizeof (grub_uint64_t); ++ /* First argument is always "a0". */ ++ size += ALIGN_UP (sizeof ("a0"), 4); ++ /* Normal arguments. */ ++ for (i = 1; i < argc; i++) ++ size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); ++ ++ /* rd arguments. */ ++ size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); ++ size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); ++ size += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); ++ ++ size = ALIGN_UP (size, 8); ++ ++ if (grub_elf_is_elf32 (elf)) ++ err = grub_linux_load32 (elf, argv[0]); ++ else ++ if (grub_elf_is_elf64 (elf)) ++ err = grub_linux_load64 (elf, argv[0]); ++ else ++ err = grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic")); ++ ++ grub_elf_close (elf); ++ ++ if (err) ++ return err; ++ ++ { ++ grub_relocator_chunk_t ch; ++ err = grub_relocator_alloc_chunk_align (relocator, &ch, ++ 0, (0xffffffff - size) + 1, ++ size, 8, ++ GRUB_RELOCATOR_PREFERENCE_HIGH, 0); ++ if (err) ++ return err; ++ linux_args_addr = get_virtual_current_address (ch); ++ } ++ ++ linux_argv = (grub_uint64_t *) linux_args_addr; ++ linux_args = (char *) (linux_argv + (linux_argc + 1 + 3)); ++ ++ grub_memcpy (linux_args, "a0", sizeof ("a0")); ++ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; ++ linux_argv++; ++ linux_args += ALIGN_UP (sizeof ("a0"), 4); ++ ++ for (i = 1; i < argc; i++) ++ { ++ grub_memcpy (linux_args, argv[i], grub_strlen (argv[i]) + 1); ++ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; ++ linux_argv++; ++ linux_args += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); ++ } ++ ++ /* Reserve space for rd arguments. */ ++ rd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; ++ linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); ++ *linux_argv = 0; ++ linux_argv++; ++ ++ rd_size_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; ++ linux_args += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); ++ *linux_argv = 0; ++ linux_argv++; ++ ++ /* Reserve space for initrd arguments. */ ++ initrd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; ++ linux_args += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); ++ *linux_argv = 0; ++ linux_argv++; ++ ++ *linux_argv = 0; ++ ++ grub_loader_set (grub_linux_boot, grub_linux_unload, 0); ++ initrd_loaded = 0; ++ loaded = 1; ++ grub_dl_ref (my_mod); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char *argv[]) ++{ ++ grub_size_t size = 0; ++ void *initrd_dest; ++ grub_err_t err; ++ struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 }; ++ ++ if (argc == 0) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ ++ if (!loaded) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); ++ ++ if (initrd_loaded) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "only one initrd command can be issued."); ++ ++ if (grub_initrd_init (argc, argv, &initrd_ctx)) ++ goto fail; ++ ++ size = grub_get_initrd_size (&initrd_ctx); ++ ++ { ++ grub_relocator_chunk_t ch; ++ err = grub_relocator_alloc_chunk_align (relocator, &ch, ++ 0, (0xffffffff - size) + 1, ++ size, 0x10000, ++ GRUB_RELOCATOR_PREFERENCE_HIGH, 0); ++ ++ if (err) ++ goto fail; ++ initrd_dest = get_virtual_current_address (ch); ++ } ++ ++ if (grub_initrd_load (&initrd_ctx, argv, initrd_dest)) ++ goto fail; ++ ++ grub_snprintf ((char *) linux_args_addr + rd_addr_arg_off, ++ sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), "rd_start=0x%lx", ++ (grub_uint64_t) initrd_dest); ++ ((grub_uint64_t *) linux_args_addr)[linux_argc] ++ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_addr_arg_off); ++ linux_argc++; ++ ++ grub_snprintf ((char *) linux_args_addr + rd_size_arg_off, ++ sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%lx", ++ (grub_uint64_t) size); ++ ((grub_uint64_t *) linux_args_addr)[linux_argc] ++ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_size_arg_off); ++ linux_argc++; ++ ++ ++ grub_snprintf ((char *) linux_args_addr + initrd_addr_arg_off, ++ sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), "initrd=0x%lx,0x%lx", ++ ((grub_uint64_t) initrd_dest & 0xffffffff), (grub_uint64_t) size); ++ ((grub_uint64_t *) linux_args_addr)[linux_argc] ++ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + initrd_addr_arg_off); ++ linux_argc++; ++ ++ initrd_loaded = 1; ++ ++ fail: ++ grub_initrd_close (&initrd_ctx); ++ ++ return grub_errno; ++} ++ ++static grub_command_t cmd_linux, cmd_initrd; ++ ++GRUB_MOD_INIT(linux) ++{ ++ cmd_linux = grub_register_command ("linux", grub_cmd_linux, ++ 0, N_("Load Linux.")); ++ cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, ++ 0, N_("Load initrd.")); ++ my_mod = mod; ++} ++ ++GRUB_MOD_FINI(linux) ++{ ++ grub_unregister_command (cmd_linux); ++ grub_unregister_command (cmd_initrd); ++} +diff --git a/include/grub/dl.h b/include/grub/dl.h +index 6a3e251..c1b6dd9 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -314,7 +314,7 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + #define GRUB_ARCH_DL_GOT_ALIGN 4 + #endif + +-#if defined (__aarch64__) || defined (__sparc__) ++#if defined (__aarch64__) || defined (__sparc__) || defined (__loongarch64) + #define GRUB_ARCH_DL_TRAMP_ALIGN 8 + #define GRUB_ARCH_DL_GOT_ALIGN 8 + #endif +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index 37e7b16..049326c 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -2087,7 +2087,8 @@ struct grub_efi_rng_protocol + typedef struct grub_efi_rng_protocol grub_efi_rng_protocol_t; + + #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ +- || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) ++ || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \ ++ || defined (__loongarch64) + + #define efi_call_0(func) func() + #define efi_call_1(func, a) func(a) +diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h +index c03cc59..be88c54 100644 +--- a/include/grub/efi/pe32.h ++++ b/include/grub/efi/pe32.h +@@ -66,6 +66,7 @@ struct grub_pe32_coff_header + }; + + #define GRUB_PE32_MACHINE_I386 0x14c ++#define GRUB_PE32_MACHINE_LOONGARCH64 0x6264 + #define GRUB_PE32_MACHINE_IA64 0x200 + #define GRUB_PE32_MACHINE_X86_64 0x8664 + #define GRUB_PE32_MACHINE_ARMTHUMB_MIXED 0x01c2 +@@ -329,6 +330,7 @@ struct grub_pe32_fixup_block + #define GRUB_PE32_REL_BASED_IA64_IMM64 9 + #define GRUB_PE32_REL_BASED_DIR64 10 + #define GRUB_PE32_REL_BASED_HIGH3ADJ 11 ++#define GRUB_PE32_REL_BASED_LOONGARCH64 8 + + struct grub_pe32_symbol + { +diff --git a/include/grub/elf.h b/include/grub/elf.h +index c8492f9..2c0b163 100644 +--- a/include/grub/elf.h ++++ b/include/grub/elf.h +@@ -247,6 +247,7 @@ typedef struct + #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ + #define EM_NUM 95 + #define EM_AARCH64 183 /* ARM 64-bit architecture */ ++#define EM_LOONGARCH64 258 /* LoongArch64 architecture */ + + /* If it is necessary to assign new unofficial EM_* values, please + pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the +@@ -1448,6 +1449,60 @@ typedef struct + #define OHWA0_R4KEOP_CHECKED 0x00000001 + #define OHWA1_R4KEOP_CLEAN 0x00000002 + ++/* LOONGARCH64 relocs. */ ++#define R_LARCH_NONE 0 ++#define R_LARCH_32 1 ++#define R_LARCH_64 2 ++#define R_LARCH_RELATIVE 3 ++#define R_LARCH_COPY 4 ++#define R_LARCH_JUMP_SLOT 5 ++#define R_LARCH_TLS_DTPMOD32 6 ++#define R_LARCH_TLS_DTPMOD64 7 ++#define R_LARCH_TLS_DTPREL32 8 ++#define R_LARCH_TLS_DTPREL64 9 ++#define R_LARCH_TLS_TPREL32 10 ++#define R_LARCH_TLS_TPREL64 11 ++#define R_LARCH_IRELATIVE 12 ++#define R_LARCH_MARK_LA 20 ++#define R_LARCH_MARK_PCREL 21 ++#define R_LARCH_SOP_PUSH_PCREL 22 ++#define R_LARCH_SOP_PUSH_ABSOLUTE 23 ++#define R_LARCH_SOP_PUSH_DUP 24 ++#define R_LARCH_SOP_PUSH_GPREL 25 ++#define R_LARCH_SOP_PUSH_TLS_TPREL 26 ++#define R_LARCH_SOP_PUSH_TLS_GOT 27 ++#define R_LARCH_SOP_PUSH_TLS_GD 28 ++#define R_LARCH_SOP_PUSH_PLT_PCREL 29 ++#define R_LARCH_SOP_ASSERT 30 ++#define R_LARCH_SOP_NOT 31 ++#define R_LARCH_SOP_SUB 32 ++#define R_LARCH_SOP_SL 33 ++#define R_LARCH_SOP_SR 34 ++#define R_LARCH_SOP_ADD 35 ++#define R_LARCH_SOP_AND 36 ++#define R_LARCH_SOP_IF_ELSE 37 ++#define R_LARCH_SOP_POP_32_S_10_5 38 ++#define R_LARCH_SOP_POP_32_U_10_12 39 ++#define R_LARCH_SOP_POP_32_S_10_12 40 ++#define R_LARCH_SOP_POP_32_S_10_16 41 ++#define R_LARCH_SOP_POP_32_S_10_16_S2 42 ++#define R_LARCH_SOP_POP_32_S_5_20 43 ++#define R_LARCH_SOP_POP_32_S_0_5_10_16_S2 44 ++#define R_LARCH_SOP_POP_32_S_0_10_10_16_S2 45 ++#define R_LARCH_SOP_POP_32_U 46 ++#define R_LARCH_ADD8 47 ++#define R_LARCH_ADD16 48 ++#define R_LARCH_ADD24 49 ++#define R_LARCH_ADD32 50 ++#define R_LARCH_ADD64 51 ++#define R_LARCH_SUB8 52 ++#define R_LARCH_SUB16 53 ++#define R_LARCH_SUB24 54 ++#define R_LARCH_SUB32 55 ++#define R_LARCH_SUB64 56 ++#define R_LARCH_GNU_VTINHERIT 57 ++#define R_LARCH_GNU_VTENTRY 58 ++ + /* MIPS relocs. */ + + #define R_MIPS_NONE 0 /* No reloc */ +diff --git a/include/grub/loongarch64/asm.h b/include/grub/loongarch64/asm.h +new file mode 100644 +index 0000000..c3e77e9 +--- /dev/null ++++ b/include/grub/loongarch64/asm.h +@@ -0,0 +1,10 @@ ++#ifndef GRUB_LOONGARCH64_ASM_HEADER ++#define GRUB_LOONGARCH64_ASM_HEADER 1 ++ ++#define GRUB_ASM_T4 $a4 ++#define GRUB_ASM_T5 $a5 ++#define GRUB_ASM_SZREG 8 ++#define GRUB_ASM_REG_S st.d ++#define GRUB_ASM_REG_L ld.d ++ ++#endif +diff --git a/include/grub/loongarch64/efi/boot.h b/include/grub/loongarch64/efi/boot.h +new file mode 100644 +index 0000000..e69de29 +diff --git a/include/grub/loongarch64/efi/loader.h b/include/grub/loongarch64/efi/loader.h +new file mode 100644 +index 0000000..71a0159 +--- /dev/null ++++ b/include/grub/loongarch64/efi/loader.h +@@ -0,0 +1,25 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2002,2003,2004,2006,2007,2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_LOADER_MACHINE_HEADER ++#define GRUB_LOADER_MACHINE_HEADER 1 ++ ++#include ++#include ++ ++#endif /* ! GRUB_LOADER_MACHINE_HEADER */ +diff --git a/include/grub/loongarch64/efi/loongson.h b/include/grub/loongarch64/efi/loongson.h +new file mode 100644 +index 0000000..fa32ef5 +--- /dev/null ++++ b/include/grub/loongarch64/efi/loongson.h +@@ -0,0 +1,290 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_EFI_LOONGSON_HEADER ++#define GRUB_EFI_LOONGSON_HEADER 1 ++ ++#include ++ ++#include ++ ++#define GRUB_EFI_LOONGSON_SMBIOS_TABLE_GUID \ ++ { 0x4660f721, 0x2ec5, 0x416a, \ ++ { 0x89, 0x9a, 0x43, 0x18, 0x02, 0x50, 0xa0, 0xc9 } \ ++ } ++ ++#define GRUB_EFI_LOONGSON_MMAP_MAX 128 ++typedef enum ++ { ++ GRUB_EFI_LOONGSON_SYSTEM_RAM = 1, ++ GRUB_EFI_LOONGSON_MEMORY_RESERVED, ++ GRUB_EFI_LOONGSON_ACPI_TABLE, ++ GRUB_EFI_LOONGSON_ACPI_NVS, ++ GRUB_EFI_LOONGSON_MAX_MEMORY_TYPE ++ } ++grub_efi_loongson_memory_type; ++ ++typedef struct ++{ ++ grub_uint16_t vers; /* version */ ++ grub_uint32_t nr_map; /* number of memory_maps */ ++ grub_uint32_t mem_freq; /* memory frequence */ ++ struct mem_map { ++ grub_uint32_t node_id; /* node_id which memory attached to */ ++ grub_uint32_t mem_type; /* system memory, pci memory, pci io, etc. */ ++ grub_uint64_t mem_start; /* memory map start address */ ++ grub_uint32_t mem_size; /* each memory_map size, not the total size */ ++ } map[GRUB_EFI_LOONGSON_MMAP_MAX]; ++} GRUB_PACKED ++grub_efi_loongson_memory_map; ++ ++/* ++ * Capability and feature descriptor structure for LOONGARCH CPU ++ */ ++typedef struct ++{ ++ grub_uint16_t vers; /* version */ ++ grub_uint32_t processor_id; /* PRID, e.g. 6305, 6306 */ ++ grub_uint32_t cputype; /* Loongson_3A/3B, etc. */ ++ grub_uint32_t total_node; /* num of total numa nodes */ ++ grub_uint16_t cpu_startup_core_id; /* Boot core id */ ++ grub_uint16_t reserved_cores_mask; ++ grub_uint32_t cpu_clock_freq; /* cpu_clock */ ++ grub_uint32_t nr_cpus; ++} GRUB_PACKED ++grub_efi_loongson_cpu_info; ++ ++#define GRUB_EFI_LOONGSON_MAX_UARTS 64 ++ ++typedef struct ++{ ++ grub_uint32_t iotype; /* see include/linux/serial_core.h */ ++ grub_uint32_t uartclk; ++ grub_uint32_t int_offset; ++ grub_uint64_t uart_base; ++} GRUB_PACKED ++grub_efi_loongson_uart_device; ++ ++#define GRUB_EFI_LOONGSON_MAX_SENSORS 64 ++ ++typedef struct ++{ ++ char name[32]; /* a formal name */ ++ char label[64]; /* a flexible description */ ++ grub_uint32_t type; /* SENSOR_* */ ++ grub_uint32_t id; /* instance id of a sensor-class */ ++ grub_uint32_t fan_policy; ++ grub_uint32_t fan_percent; /* only for constant speed policy */ ++ grub_uint64_t base_addr; /* base address of device registers */ ++} GRUB_PACKED ++grub_efi_loongson_sensor_device; ++ ++typedef struct ++{ ++ grub_uint16_t vers; /* version */ ++ grub_uint32_t ccnuma_smp; /* 0: no numa; 1: has numa */ ++ grub_uint32_t sing_double_channel; /* 1:single; 2:double */ ++ grub_uint32_t nr_uarts; ++ grub_efi_loongson_uart_device uarts[GRUB_EFI_LOONGSON_MAX_UARTS]; ++ grub_uint32_t nr_sensors; ++ grub_efi_loongson_sensor_device sensors[GRUB_EFI_LOONGSON_MAX_SENSORS]; ++ char has_ec; ++ char ec_name[32]; ++ grub_uint64_t ec_base_addr; ++ char has_tcm; ++ char tcm_name[32]; ++ grub_uint64_t tcm_base_addr; ++ grub_uint64_t workarounds; /* see workarounds.h */ ++} GRUB_PACKED ++grub_efi_loongson_system_info; ++ ++typedef struct ++{ ++ grub_uint16_t vers; ++ grub_uint16_t size; ++ grub_uint16_t rtr_bus; ++ grub_uint16_t rtr_devfn; ++ grub_uint32_t vendor; ++ grub_uint32_t device; ++ grub_uint32_t PIC_type; /* conform use HT or PCI to route to CPU-PIC */ ++ grub_uint64_t ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */ ++ grub_uint64_t ht_enable; /* irqs used in this PIC */ ++ grub_uint32_t node_id; /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */ ++ grub_uint64_t pci_mem_start_addr; ++ grub_uint64_t pci_mem_end_addr; ++ grub_uint64_t pci_io_start_addr; ++ grub_uint64_t pci_io_end_addr; ++ grub_uint64_t pci_config_addr; ++ grub_uint32_t dma_mask_bits; ++} GRUB_PACKED ++grub_efi_loongson_irq_src_routing_table; ++ ++typedef struct ++{ ++ grub_uint16_t vers; /* version */ ++ grub_uint16_t size; ++ grub_uint8_t flag; ++ char description[64]; ++} GRUB_PACKED ++grub_efi_loongson_interface_info; ++ ++#define GRUB_EFI_LOONGSON_MAX_RESOURCE_NUMBER 128 ++ ++typedef struct ++{ ++ grub_uint64_t start; /* resource start address */ ++ grub_uint64_t end; /* resource end address */ ++ char name[64]; ++ grub_uint32_t flags; ++} ++grub_efi_loongson_resource; ++ ++/* arch specific additions */ ++typedef struct ++{ ++} ++grub_efi_loongson_archdev_data; ++ ++typedef struct ++{ ++ char name[64]; /* hold the device name */ ++ grub_uint32_t num_resources; /* number of device_resource */ ++ /* for each device's resource */ ++ grub_efi_loongson_resource resource[GRUB_EFI_LOONGSON_MAX_RESOURCE_NUMBER]; ++ /* arch specific additions */ ++ grub_efi_loongson_archdev_data archdata; ++} ++grub_efi_loongson_board_devices; ++ ++typedef struct ++{ ++ grub_uint16_t vers; /* version */ ++ char special_name[64]; /* special_atribute_name */ ++ grub_uint32_t loongson_special_type; /* type of special device */ ++ /* for each device's resource */ ++ grub_efi_loongson_resource resource[GRUB_EFI_LOONGSON_MAX_RESOURCE_NUMBER]; ++} ++grub_efi_loongson_special_attribute; ++ ++typedef struct ++{ ++ grub_uint64_t memory_offset; /* efi_loongson_memory_map struct offset */ ++ grub_uint64_t cpu_offset; /* efi_loongson_cpuinfo struct offset */ ++ grub_uint64_t system_offset; /* efi_loongson_system_info struct offset */ ++ grub_uint64_t irq_offset; /* efi_loongson_irq_src_routing_table struct offset */ ++ grub_uint64_t interface_offset; /* interface_info struct offset */ ++ grub_uint64_t special_offset; /* efi_loongson_special_attribute struct offset */ ++ grub_uint64_t boarddev_table_offset; /* efi_loongson_board_devices offset */ ++} ++grub_efi_loongson_params; ++ ++typedef struct ++{ ++ grub_uint16_t vers; /* version */ ++ grub_uint64_t vga_bios; /* vga_bios address */ ++ grub_efi_loongson_params lp; ++} ++grub_efi_loongson_smbios_table; ++ ++typedef struct ++{ ++ grub_uint64_t reset_cold; ++ grub_uint64_t reset_warm; ++ grub_uint64_t reset_type; ++ grub_uint64_t shutdown; ++ grub_uint64_t do_suspend; /* NULL if not support */ ++} ++grub_efi_loongson_reset_system; ++ ++typedef struct ++{ ++ grub_uint64_t mps; /* MPS table */ ++ grub_uint64_t acpi; /* ACPI table (IA64 ext 0.71) */ ++ grub_uint64_t acpi20; /* ACPI table (ACPI 2.0) */ ++ grub_efi_loongson_smbios_table smbios; /* SM BIOS table */ ++ grub_uint64_t sal_systab; /* SAL system table */ ++ grub_uint64_t boot_info; /* boot info table */ ++} ++grub_efi_loongson; ++ ++typedef struct ++{ ++ grub_efi_loongson efi; ++ grub_efi_loongson_reset_system reset_system; ++} ++grub_efi_loongson_boot_params; ++ ++extern grub_uint64_t grub_efi_loongson_reset_system_addr; ++ ++extern void grub_efi_loongson_reset_cold (void); ++extern void grub_efi_loongson_reset_warm (void); ++extern void grub_efi_loongson_reset_shutdown (void); ++extern void grub_efi_loongson_reset_suspend (void); ++ ++void grub_efi_loongson_alloc_boot_params (void); ++void grub_efi_loongson_free_boot_params (void); ++void * grub_efi_loongson_get_smbios_table (void); ++ ++int EXPORT_FUNC(grub_efi_is_loongson) (void); ++ ++grub_uint8_t ++EXPORT_FUNC(grub_efi_loongson_calculatesum8) (const grub_uint8_t *Buffer, grub_efi_uintn_t Length); ++ ++grub_uint8_t ++EXPORT_FUNC(grub_efi_loongson_grub_calculatechecksum8) (const grub_uint8_t *Buffer, grub_efi_uintn_t Length); ++ ++ ++void * ++EXPORT_FUNC(grub_efi_loongson_get_boot_params) (void); ++ ++typedef struct _extention_list_hdr{ ++ grub_uint64_t signature; ++ grub_uint32_t length; ++ grub_uint8_t revision; ++ grub_uint8_t checksum; ++ struct _extention_list_hdr *next; ++}GRUB_PACKED ++ext_list; ++ ++typedef struct bootparamsinterface { ++ grub_uint64_t signature; //{'B', 'P', 'I', '_', '0', '_', '1'} ++ grub_efi_system_table_t *systemtable; ++ ext_list *extlist; ++}GRUB_PACKED ++bootparamsinterface; ++ ++typedef struct { ++ ext_list header; // {'M', 'E', 'M'} ++ grub_uint8_t mapcount; ++ struct GRUB_PACKED memmap { ++ grub_uint32_t memtype; ++ grub_uint64_t memstart; ++ grub_uint64_t memsize; ++ } map[GRUB_EFI_LOONGSON_MMAP_MAX]; ++}GRUB_PACKED ++mem_map; ++ ++typedef struct { ++ ext_list header; // {VBIOS} ++ grub_uint64_t vbiosaddr; ++}GRUB_PACKED ++vbios; ++ ++grub_uint32_t ++EXPORT_FUNC (grub_efi_loongson_memmap_sort) (struct memmap array[], grub_uint32_t length, mem_map * bpmem, grub_uint32_t index, grub_uint32_t memtype); ++#endif /* ! GRUB_EFI_LOONGSON_HEADER */ +diff --git a/include/grub/loongarch64/efi/memory.h b/include/grub/loongarch64/efi/memory.h +new file mode 100644 +index 0000000..b8556c7 +--- /dev/null ++++ b/include/grub/loongarch64/efi/memory.h +@@ -0,0 +1,14 @@ ++#ifndef GRUB_MEMORY_CPU_HEADER ++#include ++ ++#define GRUB_EFI_MAX_USABLE_ADDRESS 0x9800000fffffffffUL ++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS ++ ++static inline grub_uint64_t grub_efi_max_usable_address(void) ++{ ++ grub_uint64_t addr; ++ asm volatile ("csrrd %0, 0x181" : "=r" (addr)); ++ return addr |= 0xffffffffffUL; ++} ++ ++#endif /* ! GRUB_MEMORY_CPU_HEADER */ +diff --git a/include/grub/loongarch64/efi/time.h b/include/grub/loongarch64/efi/time.h +new file mode 100644 +index 0000000..e69de29 +diff --git a/include/grub/loongarch64/io.h b/include/grub/loongarch64/io.h +new file mode 100644 +index 0000000..5f34103 +--- /dev/null ++++ b/include/grub/loongarch64/io.h +@@ -0,0 +1,62 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2009,2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_IO_H ++#define GRUB_IO_H 1 ++ ++#include ++ ++typedef grub_addr_t grub_port_t; ++ ++static __inline unsigned char ++grub_inb (grub_port_t port) ++{ ++ return *(volatile grub_uint8_t *) port; ++} ++ ++static __inline unsigned short int ++grub_inw (grub_port_t port) ++{ ++ return *(volatile grub_uint16_t *) port; ++} ++ ++static __inline unsigned int ++grub_inl (grub_port_t port) ++{ ++ return *(volatile grub_uint32_t *) port; ++} ++ ++static __inline void ++grub_outb (unsigned char value, grub_port_t port) ++{ ++ *(volatile grub_uint8_t *) port = value; ++} ++ ++static __inline void ++grub_outw (unsigned short int value, grub_port_t port) ++{ ++ *(volatile grub_uint16_t *) port = value; ++} ++ ++static __inline void ++grub_outl (unsigned int value, grub_port_t port) ++{ ++ *(volatile grub_uint32_t *) port = value; ++} ++ ++#endif /* _SYS_IO_H */ +diff --git a/include/grub/loongarch64/kernel.h b/include/grub/loongarch64/kernel.h +new file mode 100644 +index 0000000..909d539 +--- /dev/null ++++ b/include/grub/loongarch64/kernel.h +@@ -0,0 +1,24 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2005,2006,2007,2008,2009,2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_KERNEL_CPU_HEADER ++#define GRUB_KERNEL_CPU_HEADER 1 ++ ++#include ++ ++#endif /* ! GRUB_KERNEL_MACHINE_HEADER */ +diff --git a/include/grub/loongarch64/linux.h b/include/grub/loongarch64/linux.h +new file mode 100644 +index 0000000..cbf8775 +--- /dev/null ++++ b/include/grub/loongarch64/linux.h +@@ -0,0 +1,22 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2013 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_LOONGARCH64_LINUX_HEADER ++#define GRUB_LOONGARCH64_LINUX_HEADER 1 ++ ++#endif /* ! GRUB_LOONGARCH64_LINUX_HEADER */ +diff --git a/include/grub/loongarch64/loongarch64.h b/include/grub/loongarch64/loongarch64.h +new file mode 100644 +index 0000000..ea3be3d +--- /dev/null ++++ b/include/grub/loongarch64/loongarch64.h +@@ -0,0 +1,30 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2010,2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_REGISTERS_CPU_HEADER ++#define GRUB_REGISTERS_CPU_HEADER 1 ++ ++#ifdef ASM_FILE ++#define GRUB_CPU_REGISTER_WRAP(x) x ++#else ++#define GRUB_CPU_REGISTER_WRAP(x) #x ++#endif ++ ++#define GRUB_CPU_LOONGARCH_COP0_TIMER_COUNT GRUB_CPU_REGISTER_WRAP(9) ++ ++#endif +diff --git a/include/grub/loongarch64/memory.h b/include/grub/loongarch64/memory.h +new file mode 100644 +index 0000000..03398b3 +--- /dev/null ++++ b/include/grub/loongarch64/memory.h +@@ -0,0 +1,57 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_MEMORY_CPU_HEADER ++#define GRUB_MEMORY_CPU_HEADER 1 ++ ++#ifndef ASM_FILE ++#include ++#include ++#include ++#endif ++ ++#ifndef ASM_FILE ++ ++typedef grub_addr_t grub_phys_addr_t; ++ ++static inline grub_phys_addr_t ++grub_vtop (void *a) ++{ ++ if (-1 == ((grub_int64_t) a >> 32)) ++ return ((grub_phys_addr_t) a) & 0x1fffffffUL; ++ return ((grub_phys_addr_t) a) & 0xffffffffffffUL; ++} ++ ++static inline void * ++grub_map_memory (grub_phys_addr_t a, grub_size_t size) ++{ ++ grub_uint64_t addr; ++ ++ asm volatile ("csrrd %0, 0x181" : "=r" (addr)); ++ return (void *) (a | (addr & 0xffffffffffffff00UL)); ++} ++ ++static inline void ++grub_unmap_memory (void *a __attribute__ ((unused)), ++ grub_size_t size __attribute__ ((unused))) ++{ ++} ++ ++#endif ++ ++#endif +diff --git a/include/grub/loongarch64/relocator.h b/include/grub/loongarch64/relocator.h +new file mode 100644 +index 0000000..8815314 +--- /dev/null ++++ b/include/grub/loongarch64/relocator.h +@@ -0,0 +1,38 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_RELOCATOR_CPU_HEADER ++#define GRUB_RELOCATOR_CPU_HEADER 1 ++ ++#include ++#include ++#include ++ ++struct grub_relocator64_state ++{ ++ /* gpr[0] is ignored since it's hardwired to 0. */ ++ grub_uint64_t gpr[32]; ++ /* Register holding target $pc. */ ++ int jumpreg; ++}; ++ ++grub_err_t ++grub_relocator64_boot (struct grub_relocator *rel, ++ struct grub_relocator64_state state); ++ ++#endif /* ! GRUB_RELOCATOR_CPU_HEADER */ +diff --git a/include/grub/loongarch64/setjmp.h b/include/grub/loongarch64/setjmp.h +new file mode 100644 +index 0000000..d9a0776 +--- /dev/null ++++ b/include/grub/loongarch64/setjmp.h +@@ -0,0 +1,27 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2002,2004,2006,2007,2009,2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_SETJMP_CPU_HEADER ++#define GRUB_SETJMP_CPU_HEADER 1 ++ ++typedef grub_uint64_t grub_jmp_buf[12]; ++ ++int grub_setjmp (grub_jmp_buf env) RETURNS_TWICE; ++void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn)); ++ ++#endif /* ! GRUB_SETJMP_CPU_HEADER */ +diff --git a/include/grub/loongarch64/time.h b/include/grub/loongarch64/time.h +new file mode 100644 +index 0000000..c9a7334 +--- /dev/null ++++ b/include/grub/loongarch64/time.h +@@ -0,0 +1,39 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2003,2004,2005,2007,2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef KERNEL_CPU_TIME_HEADER ++#define KERNEL_CPU_TIME_HEADER 1 ++ ++#ifndef GRUB_UTIL ++ ++#define GRUB_TICKS_PER_SECOND (grub_arch_cpuclock / 2) ++ ++void grub_timer_init (grub_uint32_t cpuclock); ++ ++/* Return the real time in ticks. */ ++grub_uint64_t grub_get_rtc (void); ++ ++extern grub_uint32_t grub_arch_cpuclock; ++#endif ++ ++static inline void ++grub_cpu_idle(void) ++{ ++} ++ ++#endif +diff --git a/include/grub/loongarch64/types.h b/include/grub/loongarch64/types.h +new file mode 100644 +index 0000000..5dc7f21 +--- /dev/null ++++ b/include/grub/loongarch64/types.h +@@ -0,0 +1,34 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2002,2006,2007,2009,2017 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_TYPES_CPU_HEADER ++#define GRUB_TYPES_CPU_HEADER 1 ++ ++/* The size of void *. */ ++#define GRUB_TARGET_SIZEOF_VOID_P 8 ++ ++/* The size of long. */ ++#define GRUB_TARGET_SIZEOF_LONG 8 ++ ++#ifdef GRUB_CPU_LOONGARCH ++/* loongarch is little-endian. */ ++#undef GRUB_TARGET_WORDS_BIGENDIAN ++ ++#endif /* ! GRUB_TYPES_CPU_HEADER */ ++ ++#endif +diff --git a/include/grub/util/install.h b/include/grub/util/install.h +index dad1756..33feae9 100644 +--- a/include/grub/util/install.h ++++ b/include/grub/util/install.h +@@ -107,6 +107,7 @@ enum grub_install_plat + GRUB_INSTALL_PLATFORM_X86_64_XEN, + GRUB_INSTALL_PLATFORM_ARM64_EFI, + GRUB_INSTALL_PLATFORM_ARM_COREBOOT, ++ GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI, + GRUB_INSTALL_PLATFORM_MAX + }; + +diff --git a/util/grub-install-common.c b/util/grub-install-common.c +index fde4ca7..6504637 100644 +--- a/util/grub-install-common.c ++++ b/util/grub-install-common.c +@@ -738,27 +738,28 @@ static struct + const char *platform; + } platforms[GRUB_INSTALL_PLATFORM_MAX] = + { +- [GRUB_INSTALL_PLATFORM_I386_PC] = { "i386", "pc" }, +- [GRUB_INSTALL_PLATFORM_I386_EFI] = { "i386", "efi" }, +- [GRUB_INSTALL_PLATFORM_I386_QEMU] = { "i386", "qemu" }, +- [GRUB_INSTALL_PLATFORM_I386_COREBOOT] = { "i386", "coreboot" }, +- [GRUB_INSTALL_PLATFORM_I386_MULTIBOOT] = { "i386", "multiboot" }, +- [GRUB_INSTALL_PLATFORM_I386_IEEE1275] = { "i386", "ieee1275" }, +- [GRUB_INSTALL_PLATFORM_X86_64_EFI] = { "x86_64", "efi" }, +- [GRUB_INSTALL_PLATFORM_I386_XEN] = { "i386", "xen" }, +- [GRUB_INSTALL_PLATFORM_X86_64_XEN] = { "x86_64", "xen" }, +- [GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON] = { "mipsel", "loongson" }, +- [GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS] = { "mipsel", "qemu_mips" }, +- [GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS] = { "mips", "qemu_mips" }, +- [GRUB_INSTALL_PLATFORM_MIPSEL_ARC] = { "mipsel", "arc" }, +- [GRUB_INSTALL_PLATFORM_MIPS_ARC] = { "mips", "arc" }, +- [GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275] = { "sparc64", "ieee1275" }, +- [GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275] = { "powerpc", "ieee1275" }, +- [GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64", "efi" }, +- [GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm", "efi" }, +- [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64", "efi" }, +- [GRUB_INSTALL_PLATFORM_ARM_UBOOT] = { "arm", "uboot" }, +- [GRUB_INSTALL_PLATFORM_ARM_COREBOOT] = { "arm", "coreboot" }, ++ [GRUB_INSTALL_PLATFORM_I386_PC] = { "i386", "pc" }, ++ [GRUB_INSTALL_PLATFORM_I386_EFI] = { "i386", "efi" }, ++ [GRUB_INSTALL_PLATFORM_I386_QEMU] = { "i386", "qemu" }, ++ [GRUB_INSTALL_PLATFORM_I386_COREBOOT] = { "i386", "coreboot" }, ++ [GRUB_INSTALL_PLATFORM_I386_MULTIBOOT] = { "i386", "multiboot" }, ++ [GRUB_INSTALL_PLATFORM_I386_IEEE1275] = { "i386", "ieee1275" }, ++ [GRUB_INSTALL_PLATFORM_X86_64_EFI] = { "x86_64", "efi" }, ++ [GRUB_INSTALL_PLATFORM_I386_XEN] = { "i386", "xen" }, ++ [GRUB_INSTALL_PLATFORM_X86_64_XEN] = { "x86_64", "xen" }, ++ [GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON] = { "mipsel", "loongson" }, ++ [GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS] = { "mipsel", "qemu_mips" }, ++ [GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS] = { "mips", "qemu_mips" }, ++ [GRUB_INSTALL_PLATFORM_MIPSEL_ARC] = { "mipsel", "arc" }, ++ [GRUB_INSTALL_PLATFORM_MIPS_ARC] = { "mips", "arc" }, ++ [GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275] = { "sparc64", "ieee1275" }, ++ [GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275] = { "powerpc", "ieee1275" }, ++ [GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64", "efi" }, ++ [GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm", "efi" }, ++ [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64", "efi" }, ++ [GRUB_INSTALL_PLATFORM_ARM_UBOOT] = { "arm", "uboot" }, ++ [GRUB_INSTALL_PLATFORM_ARM_COREBOOT] = { "arm", "coreboot" }, ++ [GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI] = { "loongarch64", "efi" }, + }; + + char * +diff --git a/util/grub-install.c b/util/grub-install.c +index 65bb2f9..28b5d74 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -322,6 +322,8 @@ get_default_platform (void) + return "arm-uboot"; + #elif defined (__aarch64__) + return "arm64-efi"; ++#elif defined (__loongarch64) ++ return "loongarch64-efi"; + #elif defined (__amd64__) || defined (__x86_64__) || defined (__i386__) + return grub_install_get_default_x86_platform (); + #else +@@ -477,6 +479,7 @@ have_bootdev (enum grub_install_plat pl) + case GRUB_INSTALL_PLATFORM_IA64_EFI: + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: ++ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: + case GRUB_INSTALL_PLATFORM_I386_IEEE1275: + case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: + case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275: +@@ -895,6 +898,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_I386_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + case GRUB_INSTALL_PLATFORM_X86_64_EFI: ++ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: + is_efi = 1; + grub_util_error (_("this utility cannot be used for EFI platforms" + " because it does not support UEFI Secure Boot")); +@@ -921,6 +925,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: ++ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: + case GRUB_INSTALL_PLATFORM_I386_IEEE1275: + case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: + case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275: +@@ -965,6 +970,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: ++ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: + case GRUB_INSTALL_PLATFORM_I386_IEEE1275: + case GRUB_INSTALL_PLATFORM_ARM_UBOOT: + case GRUB_INSTALL_PLATFORM_I386_QEMU: +@@ -1110,6 +1116,9 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + efi_file = "BOOTAA64.EFI"; + break; ++ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: ++ efi_file = "BOOTLOONGARCH64.EFI"; ++ break; + default: + grub_util_error ("%s", _("You've found a bug")); + break; +@@ -1137,6 +1146,9 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + efi_file = "grubaa64.efi"; + break; ++ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: ++ efi_file = "grubloongarch64.efi"; ++ break; + default: + efi_file = "grub.efi"; + break; +@@ -1440,6 +1452,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: ++ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: + g = grub_util_guess_efi_drive (*curdev); + break; + case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: +@@ -1581,6 +1594,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: ++ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: + core_name = "core.efi"; + snprintf (mkimage_target, sizeof (mkimage_target), + "%s-%s", +@@ -1683,6 +1697,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: ++ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: + case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS: + case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS: + case GRUB_INSTALL_PLATFORM_I386_COREBOOT: +@@ -1917,6 +1932,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: ++ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: + { + char *dst = grub_util_path_concat (2, efidir, efi_file); + grub_install_copy_file (imgfile, dst, 1); +diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c +index 1bb5eb8..240e193 100644 +--- a/util/grub-mkimagexx.c ++++ b/util/grub-mkimagexx.c +@@ -783,6 +783,9 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, + struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off); + grub_uint64_t *gpptr = (void *) (pe_target + got_off); + unsigned unmatched_adr_got_page = 0; ++ grub_uint64_t oprs[10240]= {0}; ++ int opri = -1; ++ grub_uint32_t la_abs = 0; + #define MASK19 ((1 << 19) - 1) + #else + grub_uint32_t *tr = (void *) (pe_target + tramp_off); +@@ -1122,6 +1125,173 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, + } + break; + } ++ case EM_LOONGARCH64: ++ { ++ sym_addr += addend; ++ switch (ELF_R_TYPE (info)) ++ { ++ case R_LARCH_64: ++ { ++ *target=(grub_uint64_t)sym_addr; ++ } ++ break; ++ case R_LARCH_MARK_LA: ++ { ++ la_abs=1; ++ } ++ break; ++ case R_LARCH_SOP_PUSH_PCREL: ++ { ++ opri++; ++ oprs[opri]=(grub_uint64_t)(sym_addr-(target_section_addr+offset+image_target->vaddr_offset)); ++ } ++ break; ++ case R_LARCH_SOP_PUSH_ABSOLUTE: ++ { ++ opri++; ++ oprs[opri]=(grub_uint64_t)sym_addr; ++ } ++ break; ++ case R_LARCH_SOP_PUSH_PLT_PCREL: ++ { ++ opri++; ++ oprs[opri]=(grub_uint64_t)(sym_addr-(target_section_addr+offset+image_target->vaddr_offset)); ++ } ++ break; ++ case R_LARCH_SOP_SUB: ++ { ++ grub_uint64_t opr2=oprs[opri]; ++ opri--; ++ grub_uint64_t opr1=oprs[opri]; ++ opri--; ++ opri++; ++ oprs[opri]=opr1 - opr2; ++ } ++ break; ++ case R_LARCH_SOP_SL: ++ { ++ grub_uint64_t opr2=oprs[opri]; ++ opri--; ++ grub_uint64_t opr1=oprs[opri]; ++ opri--; ++ opri++; ++ oprs[opri]=opr1 << opr2; ++ } ++ break; ++ case R_LARCH_SOP_SR: ++ { ++ grub_uint64_t opr2=oprs[opri]; ++ opri--; ++ grub_uint64_t opr1=oprs[opri]; ++ opri--; ++ opri++; ++ oprs[opri]=opr1 >> opr2; ++ } ++ break; ++ case R_LARCH_SOP_ADD: ++ { ++ grub_uint64_t opr2=oprs[opri]; ++ opri--; ++ grub_uint64_t opr1=oprs[opri]; ++ opri--; ++ opri++; ++ oprs[opri]=opr1 + opr2; ++ } ++ break; ++ case R_LARCH_SOP_AND: ++ { ++ grub_uint64_t opr2=oprs[opri]; ++ opri--; ++ grub_uint64_t opr1=oprs[opri]; ++ opri--; ++ opri++; ++ oprs[opri]=opr1 & opr2; ++ } ++ break; ++ case R_LARCH_SOP_IF_ELSE: ++ { ++ grub_uint64_t opr3=oprs[opri]; ++ opri--; ++ grub_uint64_t opr2=oprs[opri]; ++ opri--; ++ grub_uint64_t opr1=oprs[opri]; ++ opri--; ++ if(opr1){ ++ opri++; ++ oprs[opri]=opr2; ++ } else { ++ opri++; ++ oprs[opri]=opr3; ++ } ++ } ++ break; ++ case R_LARCH_SOP_POP_32_S_10_5: ++ { ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *target=(*target) | ((opr1 & 0x1f) << 10); ++ } ++ break; ++ case R_LARCH_SOP_POP_32_U_10_12: ++ { ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *target=(*target) | ((opr1 & 0xfff) << 10); ++ } ++ break; ++ case R_LARCH_SOP_POP_32_S_10_12: ++ { ++ if(la_abs==1) ++ la_abs=0; ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *target = (*target) | ((opr1 & 0xfff) << 10); ++ } ++ break; ++ case R_LARCH_SOP_POP_32_S_10_16: ++ { ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *target = (*target) | ((opr1 & 0xffff) << 10); ++ } ++ break; ++ case R_LARCH_SOP_POP_32_S_10_16_S2: ++ { ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *target = (*target) | (((opr1 >> 2) & 0xffff) << 10); ++ } ++ break; ++ case R_LARCH_SOP_POP_32_S_5_20: ++ { ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *target = (*target) | ((opr1 & 0xfffff)<<5) ; ++ } ++ break; ++ case R_LARCH_SOP_POP_32_S_0_5_10_16_S2: ++ { ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *target =(*target) | (((opr1 >> 2) & 0xffff) << 10); ++ *target =(*target) | ((opr1 >> 18) & 0x1f); ++ } ++ break; ++ case R_LARCH_SOP_POP_32_S_0_10_10_16_S2: ++ { ++ grub_uint64_t opr1 = oprs[opri]; ++ opri--; ++ *target =(*target) | (((opr1 >> 2) & 0xffff) << 10); ++ *target =(*target) | ((opr1 >> 18) & 0x3ff); ++ } ++ break; ++ default: ++ grub_util_error (_("relocation 0x%x is not implemented yet"), ++ (unsigned int) ELF_R_TYPE (info)); ++ break; ++ } ++ break; ++ } + #endif + #if defined(MKIMAGE_ELF32) + case EM_ARM: +@@ -1310,7 +1480,10 @@ add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type, + + /* The spec does not mention the requirement of a Page RVA. + Here, align the address with a 4K boundary for safety. */ +- b->page_rva = (addr & ~(0x1000 - 1)); ++#ifdef GRUB_CPU_LOONGARCH64 ++ if (type) ++#endif ++ b->page_rva = (addr & ~(0x1000 - 1)); + b->block_size = sizeof (*b); + } + +@@ -1320,7 +1493,11 @@ add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type, + + /* Add a new entry. */ + cur_index = ((b->block_size - sizeof (*b)) >> 1); ++#ifdef GRUB_CPU_LOONGARCH64 ++ entry = GRUB_PE32_FIXUP_ENTRY (type, type ? (addr - b->page_rva) : addr); ++#else + entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva); ++#endif + b->entries[cur_index] = grub_host_to_target16 (entry); + b->block_size += 2; + } +@@ -1366,6 +1543,10 @@ static void + translate_relocation_pe (struct translate_context *ctx, + Elf_Addr addr, + Elf_Addr info, ++#ifdef GRUB_CPU_LOONGARCH64 ++ Elf_Addr sym_addr, ++ Elf_Addr addend, ++#endif + const struct grub_install_image_target_desc *image_target) + { + /* Necessary to relocate only absolute addresses. */ +@@ -1477,6 +1658,133 @@ translate_relocation_pe (struct translate_context *ctx, + } + break; + break; ++ case EM_LOONGARCH64: ++ switch (ELF_R_TYPE (info)) ++ { ++ case R_LARCH_NONE: ++ break; ++ case R_LARCH_32: ++ break; ++ case R_LARCH_64: ++ { ++ ctx->current_address = add_fixup_entry ( ++ &ctx->lst, ++ GRUB_PE32_REL_BASED_DIR64, ++ addr, 0, ctx->current_address, ++ image_target); ++ } ++ break; ++ case R_LARCH_RELATIVE: ++ break; ++ case R_LARCH_COPY: ++ break; ++ case R_LARCH_JUMP_SLOT: ++ break; ++ case R_LARCH_TLS_DTPMOD32: ++ break; ++ case R_LARCH_TLS_DTPMOD64: ++ break; ++ case R_LARCH_TLS_DTPREL32: ++ break; ++ case R_LARCH_TLS_DTPREL64: ++ break; ++ case R_LARCH_TLS_TPREL32: ++ break; ++ case R_LARCH_TLS_TPREL64: ++ break; ++ case R_LARCH_IRELATIVE: ++ break; ++ case R_LARCH_MARK_LA: ++ { ++ ctx->current_address = add_fixup_entry ( ++ &ctx->lst, ++ GRUB_PE32_REL_BASED_LOONGARCH64, ++ addr, 0, ctx->current_address, ++ image_target); ++ } ++ break; ++ case R_LARCH_MARK_PCREL: ++ break; ++ case R_LARCH_SOP_PUSH_PCREL: ++ break; ++ case R_LARCH_SOP_PUSH_ABSOLUTE: ++ break; ++ case R_LARCH_SOP_PUSH_DUP: ++ break; ++ case R_LARCH_SOP_PUSH_GPREL: ++ break; ++ case R_LARCH_SOP_PUSH_TLS_TPREL: ++ break; ++ case R_LARCH_SOP_PUSH_TLS_GOT: ++ break; ++ case R_LARCH_SOP_PUSH_TLS_GD: ++ break; ++ case R_LARCH_SOP_PUSH_PLT_PCREL: ++ break; ++ case R_LARCH_SOP_ASSERT: ++ break; ++ case R_LARCH_SOP_NOT: ++ break; ++ case R_LARCH_SOP_SUB: ++ break; ++ case R_LARCH_SOP_SL: ++ break; ++ case R_LARCH_SOP_SR: ++ break; ++ case R_LARCH_SOP_ADD: ++ break; ++ case R_LARCH_SOP_AND: ++ break; ++ case R_LARCH_SOP_IF_ELSE: ++ break; ++ case R_LARCH_SOP_POP_32_S_10_5: ++ break; ++ case R_LARCH_SOP_POP_32_U_10_12: ++ break; ++ case R_LARCH_SOP_POP_32_S_10_12: ++ break; ++ case R_LARCH_SOP_POP_32_S_10_16: ++ break; ++ case R_LARCH_SOP_POP_32_S_10_16_S2: ++ break; ++ case R_LARCH_SOP_POP_32_S_5_20: ++ break; ++ case R_LARCH_SOP_POP_32_S_0_5_10_16_S2: ++ break; ++ case R_LARCH_SOP_POP_32_S_0_10_10_16_S2: ++ break; ++ case R_LARCH_SOP_POP_32_U: ++ break; ++ case R_LARCH_ADD8: ++ break; ++ case R_LARCH_ADD16: ++ break; ++ case R_LARCH_ADD24: ++ break; ++ case R_LARCH_ADD32: ++ break; ++ case R_LARCH_ADD64: ++ break; ++ case R_LARCH_SUB8: ++ break; ++ case R_LARCH_SUB16: ++ break; ++ case R_LARCH_SUB24: ++ break; ++ case R_LARCH_SUB32: ++ break; ++ case R_LARCH_SUB64: ++ break; ++ case R_LARCH_GNU_VTINHERIT: ++ break; ++ case R_LARCH_GNU_VTENTRY: ++ break; ++ default: ++ grub_util_error (_("relocation 0x%x is not implemented yet"), ++ (unsigned int) ELF_R_TYPE (info)); ++ break; ++ } ++ break; + #if defined(MKIMAGE_ELF32) + case EM_ARM: + switch (ELF_R_TYPE (info)) +@@ -1565,10 +1873,18 @@ static void + translate_relocation (struct translate_context *ctx, + Elf_Addr addr, + Elf_Addr info, ++#ifdef GRUB_CPU_LOONGARCH64 ++ Elf_Addr sym_addr, ++ Elf_Addr addend, ++#endif + const struct grub_install_image_target_desc *image_target) + { + if (image_target->id == IMAGE_EFI) ++#ifdef GRUB_CPU_LOONGARCH64 ++ translate_relocation_pe (ctx, addr, info, sym_addr, addend, image_target); ++#else + translate_relocation_pe (ctx, addr, info, image_target); ++#endif + else + translate_relocation_raw (ctx, addr, info, image_target); + } +@@ -1709,11 +2025,21 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout, + if ((grub_target_to_host32 (s->sh_type) == SHT_REL) || + (grub_target_to_host32 (s->sh_type) == SHT_RELA)) + { ++#ifdef GRUB_CPU_LOONGARCH64 ++ Elf_Rela *r; ++#else + Elf_Rel *r; ++#endif + Elf_Word rtab_size, r_size, num_rs; + Elf_Off rtab_offset; + Elf_Addr section_address; + Elf_Word j; ++#ifdef GRUB_CPU_LOONGARCH64 ++ Elf_Shdr *symtab_section; ++ ++ symtab_section = (Elf_Shdr *) ((char *) smd->sections ++ + (grub_target_to_host32 (s->sh_link) * smd->section_entsize)); ++#endif + + if (!SUFFIX (is_kept_reloc_section) (s, image_target, smd)) + { +@@ -1732,20 +2058,39 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout, + + section_address = smd->vaddrs[grub_le_to_cpu32 (s->sh_info)]; + ++#ifdef GRUB_CPU_LOONGARCH64 ++ for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset); ++ j < num_rs; ++ j++, r = (Elf_Rela *) ((char *) r + r_size)) ++#else + for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset); + j < num_rs; + j++, r = (Elf_Rel *) ((char *) r + r_size)) ++#endif + { + Elf_Addr info; + Elf_Addr offset; + Elf_Addr addr; ++#ifdef GRUB_CPU_LOONGARCH64 ++ Elf_Addr sym_addr; ++ Elf_Addr addend; ++#endif + + offset = grub_target_to_host (r->r_offset); + info = grub_target_to_host (r->r_info); +- ++#ifdef GRUB_CPU_LOONGARCH64 ++ sym_addr = SUFFIX (get_symbol_address) (e, symtab_section, ++ ELF_R_SYM (info), image_target); ++ addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ? ++ grub_target_to_host (r->r_addend) : 0; ++#endif + addr = section_address + offset; + ++#ifdef GRUB_CPU_LOONGARCH64 ++ translate_relocation (&ctx, addr, info, sym_addr, addend, image_target); ++#else + translate_relocation (&ctx, addr, info, image_target); ++#endif + } + } + +diff --git a/util/grub-mknetdir.c b/util/grub-mknetdir.c +index ae31271..c998850 100644 +--- a/util/grub-mknetdir.c ++++ b/util/grub-mknetdir.c +@@ -112,7 +112,8 @@ static struct + [GRUB_INSTALL_PLATFORM_X86_64_EFI] = { "x86_64-efi", "efinet", ".efi" }, + [GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64-efi", "efinet", ".efi" }, + [GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm-efi", "efinet", ".efi" }, +- [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64-efi", "efinet", ".efi" } ++ [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64-efi", "efinet", ".efi" }, ++ [GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI] = { "loongarch64-efi", "efinet", ".efi" } + }; + + static void +diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c +index 03ba1ab..4a9943a 100644 +--- a/util/grub-module-verifier.c ++++ b/util/grub-module-verifier.c +@@ -119,6 +119,52 @@ struct grub_module_verifier_arch archs[] = { + -1 + } + }, ++ { "loongarch64", 8, 0, EM_LOONGARCH64, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ ++ R_LARCH_NONE, ++ R_LARCH_32, ++ R_LARCH_64, ++ R_LARCH_RELATIVE, ++ R_LARCH_COPY, ++ R_LARCH_JUMP_SLOT, ++ R_LARCH_TLS_DTPMOD32, ++ R_LARCH_TLS_DTPMOD64, ++ R_LARCH_TLS_DTPREL32, ++ R_LARCH_TLS_DTPREL64, ++ R_LARCH_TLS_TPREL32, ++ R_LARCH_TLS_TPREL64, ++ R_LARCH_IRELATIVE, ++ R_LARCH_MARK_LA, ++ R_LARCH_MARK_PCREL, ++ R_LARCH_SOP_PUSH_PCREL, ++ R_LARCH_SOP_PUSH_ABSOLUTE, ++ R_LARCH_SOP_PUSH_DUP, ++ R_LARCH_SOP_PUSH_GPREL, ++ R_LARCH_SOP_PUSH_TLS_TPREL, ++ R_LARCH_SOP_PUSH_TLS_GOT, ++ R_LARCH_SOP_PUSH_TLS_GD, ++ R_LARCH_SOP_PUSH_PLT_PCREL, ++ R_LARCH_SOP_ASSERT, ++ R_LARCH_SOP_NOT, ++ R_LARCH_SOP_SUB, ++ R_LARCH_SOP_SL, ++ R_LARCH_SOP_SR, ++ R_LARCH_SOP_ADD, ++ R_LARCH_SOP_AND, ++ R_LARCH_SOP_IF_ELSE, ++ R_LARCH_SOP_POP_32_S_10_5, ++ R_LARCH_SOP_POP_32_U_10_12, ++ R_LARCH_SOP_POP_32_S_10_12, ++ R_LARCH_SOP_POP_32_S_10_16, ++ R_LARCH_SOP_POP_32_S_10_16_S2, ++ R_LARCH_SOP_POP_32_S_5_20, ++ R_LARCH_SOP_POP_32_S_0_5_10_16_S2, ++ R_LARCH_SOP_POP_32_S_0_10_10_16_S2, ++ R_LARCH_SOP_POP_32_U, ++ -1 ++ }, (int[]){ ++ -1 ++ } ++ }, + }; + + struct platform_whitelist { +diff --git a/util/mkimage.c b/util/mkimage.c +index 16418e2..0d39c07 100644 +--- a/util/mkimage.c ++++ b/util/mkimage.c +@@ -609,6 +609,22 @@ static const struct grub_install_image_target_desc image_targets[] = + .pe_target = GRUB_PE32_MACHINE_ARM64, + .elf_target = EM_AARCH64, + }, ++ { ++ .dirname = "loongarch64-efi", ++ .names = { "loongarch64-efi", NULL }, ++ .voidp_sizeof = 8, ++ .bigendian = 0, ++ .id = IMAGE_EFI, ++ .flags = PLATFORM_FLAGS_NONE, ++ .total_module_size = TARGET_NO_FIELD, ++ .decompressor_compressed_size = TARGET_NO_FIELD, ++ .decompressor_uncompressed_size = TARGET_NO_FIELD, ++ .decompressor_uncompressed_addr = TARGET_NO_FIELD, ++ .section_align = GRUB_PE32_SECTION_ALIGNMENT, ++ .vaddr_offset = EFI64_HEADER_SIZE, ++ .pe_target = GRUB_PE32_MACHINE_LOONGARCH64, ++ .elf_target = EM_LOONGARCH64, ++ }, + }; + + #include +-- +2.27.0 + diff --git a/grub.macros b/grub.macros index e55de53..07a0edd 100644 --- a/grub.macros +++ b/grub.macros @@ -92,7 +92,7 @@ %endif -%global efi_only aarch64 %{arm} +%global efi_only aarch64 %{arm} loongarch64 %global efi_arch x86_64 ia64 %{efi_only} %ifarch %{efi_arch} %global with_efi_arch 1 @@ -122,7 +122,7 @@ %global platform_modules " appendedsig " %endif -%ifarch aarch64 %{arm} +%ifarch aarch64 %{arm} loongarch64 %global platform_modules " " %endif @@ -187,6 +187,14 @@ )} %endif +%ifarch loongarch64 +%global with_emu_arch 0 +%global efiarch loongarch64 +%global target_cpu_name loongarch64 +%global grub_target_name loongarch64-efi +%global package_arch efi-loongarch64 +%endif + %global _target_platform %{target_cpu_name}-%{_vendor}-%{_target_os}%{?_gnu} %global _alt_target_platform %{alt_target_cpu_name}-%{_vendor}-%{_target_os}%{?_gnu} diff --git a/grub.patches b/grub.patches index a913b39..3c4c7e4 100644 --- a/grub.patches +++ b/grub.patches @@ -674,3 +674,5 @@ Patch0674: 0674-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch Patch0675: 0675-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch Patch0676: 0676-fs-xfs-fix-large-extent-counters-incompat-feature-su.patch Patch0677: 0677-fs-ext2-Rework-out-of-bounds-read-for-inline-and-ext.patch +# Support loongarch64 +#Patch1000: 1000-loongarch64-add-support.patch diff --git a/grub2.spec b/grub2.spec index 30e830c..1f1a1bb 100644 --- a/grub2.spec +++ b/grub2.spec @@ -5,6 +5,10 @@ %undefine _missing_build_ids_terminate_build %global _configure_gnuconfig_hack 0 +%ifarch loongarch64 +%global _configure_gnuconfig_hack 1 +%endif + Name: grub2 Epoch: 1 Version: 2.02 @@ -115,7 +119,7 @@ Requires(post): dracut %{desc} This subpackage provides tools for support of all platforms. -%ifarch x86_64 +%ifarch x86_64 loongarch64 %package tools-efi Summary: Support tools for GRUB. Group: System Environment/Base @@ -185,6 +189,11 @@ git add grub-%{grublegacyarch}-%{tarversion} %endif git commit -m "After making subdirs" +%ifarch loongarch64 +%_update_config_sub +%_update_config_guess +%endif + %build %if 0%{with_efi_arch} %{expand:%do_primary_efi_build %%{grubefiarch} %%{grubefiname} %%{grubeficdname} %%{_target_platform} %%{efi_target_cflags} %%{efi_host_cflags} %{old_sb_ca} %{old_sb_cer} %{old_sb_key} %{sb_ca} %{sb_cer} %{sb_key}} @@ -226,8 +235,11 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir ln -s %{name}-set-password ${RPM_BUILD_ROOT}/%{_sbindir}/%{name}-setpassword echo '.so man8/%{name}-set-password.8' > ${RPM_BUILD_ROOT}/%{_datadir}/man/man8/%{name}-setpassword.8 %ifnarch x86_64 -rm -vf ${RPM_BUILD_ROOT}/%{_bindir}/%{name}-render-label rm -vf ${RPM_BUILD_ROOT}/%{_sbindir}/%{name}-bios-setup +%endif + +%ifnarch x86_64 loongarch64 +rm -vf ${RPM_BUILD_ROOT}/%{_bindir}/%{name}-render-label rm -vf ${RPM_BUILD_ROOT}/%{_sbindir}/%{name}-macbless %endif @@ -400,7 +412,7 @@ fi %{_datadir}/man/man1/%{name}-editenv* %{_datadir}/man/man1/%{name}-mkpasswd-* -%ifarch x86_64 +%ifarch x86_64 loongarch64 %files tools-efi %{_sbindir}/%{name}-macbless %{_bindir}/%{name}-render-label @@ -526,6 +538,7 @@ fi %changelog * Wed Apr 30 2025 Bo Ren - 2.02-165.0.1 - Build pc-modules package on x86_64 (geliwei@openanolis.org) +- Add loongarch64 base support (zhangwenlong@loongson.cn)(chenguoqi@loongson.cn) * Thu Apr 17 2025 Nicolas Frayer - 2.02-165 - fs/ext2: Rework of OOB read patch -- Gitee From 3182d427018ba2e5ccb68bc0dedd95e1aec3c95f Mon Sep 17 00:00:00 2001 From: songmingliang Date: Thu, 19 May 2022 00:17:50 +0800 Subject: [PATCH 4/8] Fix a bug in bls_make_list, blscfg --- 1001-bls-make-list.patch | 119 +++++++++++++++++++++++++++++++++++++++ grub.patches | 1 + grub2.spec | 1 + 3 files changed, 121 insertions(+) create mode 100644 1001-bls-make-list.patch diff --git a/1001-bls-make-list.patch b/1001-bls-make-list.patch new file mode 100644 index 0000000..ac39162 --- /dev/null +++ b/1001-bls-make-list.patch @@ -0,0 +1,119 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhongling He +Date: Tue, 29 Mar 2022 17:27:13 +0800 +Subject: [PATCH] Fix a bug in bls_make_list, blscfg + +We have encountered a bug while running LifseaOS aarch64 version without +initrd. This commit fixes this bug. It may have fixed some potential +bugs as well. + +There are 4 partitions in a LifseaOS disk image: +- The 1st partition is for BIOS bootloader +- The 2nd partition is for UEFI booting, which contains grub binary + compiled from this source code, grubaa64.efi +- The 3rd partition contains grub.cfg files and + loader/entries/ostree-1-LifseaOS.conf +- The 4th partition contains rootfs + +Since x86_64 supports both BIOS and UEFI booting and we employ BIOS +booting for x86_64 (w/o initrd) image, we don't put the grub2 binary +compiled into the 2nd partition. As a result, this bug was not observed. +However, aarch64 only supports UEFI booting. In other words, we are +using this grub2 to boot LifseaOS (w/o initrd). + +grubaa64.efi from the 2nd partition will read `/grub2/grub.cfg` in the +3rd partition. + +``` +... + set ignition_firstboot="ignition.firstboot +${ignition_network_kcmdline}" +fi + +blscfg +``` + +`blscfg` is a command to convert `loader/entries/ostree-1-LifseaOS.conf` +into a typical grub.cfg. However, here comes the bug. While booting, an +error message will appear. + +``` +error: ../../grub-core/loader/arm64/linux.c:292:filename expected. +Press any key to continue. +``` + +This is because the bug in `blscfg` unexpectedly add a line, `initrd`, +into the generated grub.cfg file. Grub2 will expect an initrd file path +after `initrd`. As a result, the error occurs. + +In grub-core/command/blscfg.c:676, if `initrds` is a non-NULL pointer, +then `src` will contain a `initrd` line. + +``` +static void create_entry (struct bls_entry *entry){ + ... + initrds = bls_make_list (entry, "initrd", NULL); // + ... + if (initrds){ + ... + tmp = grub_stpcpy(initrd, "initrd "); + ... + } + ... + src = grub_xasprintf ("load_video\n" + "set gfx_payload=keep\n" + "insmod gzio\n" + "linux %s%s%s%s\n" + "%s", + GRUB_BOOT_DEVICE, clinux, options ? " " : "", options ? options +: "", + initrd ? initrd : ""); +``` + +In grub-core/command/blscfg.c:562, `bls_make_list` will always return a +non-NULL pointer except for a `grub_malloc` error. + +``` +static char **bls_make_list (struct bls_entry *entry, const char *key, +int *num) +{ + ... + list = grub_malloc (sizeof (char *)); + if (!list) + return NULL; + list[0] = NULL; + ... + return list; +} +``` + +Therefore, `initrd` like will be appended into the auto-generated +grub.cfg if `grub_malloc` succeed, regardless of whether initrd is +stated in config file. Our bug fix, same as upstream, modifies the +behaviour of `bls_make_list`. `bls_make_list` will now return a non-NULL +pointer only if the required field actually exists. + +--- + grub-core/commands/blscfg.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c +index 795a9f9..bf18270 100644 +--- a/grub-core/commands/blscfg.c ++++ b/grub-core/commands/blscfg.c +@@ -589,6 +589,12 @@ static char **bls_make_list (struct bls_entry *entry, const char *key, int *num) + list[nlist] = NULL; + } + ++ if (!nlist) ++ { ++ grub_free (list); ++ return NULL; ++ } ++ + if (num) + *num = nlist; + +-- +2.27.0 + diff --git a/grub.patches b/grub.patches index 3c4c7e4..1d6dc07 100644 --- a/grub.patches +++ b/grub.patches @@ -676,3 +676,4 @@ Patch0676: 0676-fs-xfs-fix-large-extent-counters-incompat-feature-su.patch Patch0677: 0677-fs-ext2-Rework-out-of-bounds-read-for-inline-and-ext.patch # Support loongarch64 #Patch1000: 1000-loongarch64-add-support.patch +Patch1001: 1001-bls-make-list.patch diff --git a/grub2.spec b/grub2.spec index 1f1a1bb..ede542e 100644 --- a/grub2.spec +++ b/grub2.spec @@ -539,6 +539,7 @@ fi * Wed Apr 30 2025 Bo Ren - 2.02-165.0.1 - Build pc-modules package on x86_64 (geliwei@openanolis.org) - Add loongarch64 base support (zhangwenlong@loongson.cn)(chenguoqi@loongson.cn) +- Fix a bug in bls_make_list, blscfg. (zhonglingh@linux.alibaba.com) * Thu Apr 17 2025 Nicolas Frayer - 2.02-165 - fs/ext2: Rework of OOB read patch -- Gitee From adbb6c5e96506cb6e2e8f2cdd6529780386a05c3 Mon Sep 17 00:00:00 2001 From: yangqiming Date: Wed, 6 Jul 2022 23:45:53 -0400 Subject: [PATCH 5/8] Add LoongArch64 support and update interface to v40 --- ...-support-and-update-interface-to-v40.patch | 1968 ++++++----------- grub.patches | 1 + grub2.spec | 3 + 3 files changed, 726 insertions(+), 1246 deletions(-) rename 1000-loongarch64-add-support.patch => 1002-Add-LoongArch64-support-and-update-interface-to-v40.patch (64%) diff --git a/1000-loongarch64-add-support.patch b/1002-Add-LoongArch64-support-and-update-interface-to-v40.patch similarity index 64% rename from 1000-loongarch64-add-support.patch rename to 1002-Add-LoongArch64-support-and-update-interface-to-v40.patch index 2d83c94..36750c1 100644 --- a/1000-loongarch64-add-support.patch +++ b/1002-Add-LoongArch64-support-and-update-interface-to-v40.patch @@ -1,87 +1,11 @@ -From febee03c70471fd2ce6f0b4cc0f365c32c106ab3 Mon Sep 17 00:00:00 2001 -From: Fedora Ninjas -Date: Wed, 18 May 2022 23:50:45 +0800 -Subject: [PATCH] add loongarch64 support +From 478205a88ea71b0c546987602cd879027819125e Mon Sep 17 00:00:00 2001 +From: yangqiming +Date: Thu, 7 Jul 2022 11:25:02 +0800 +Subject: [PATCH] Add LoongArch64 support and update interface to V40 ---- - conf/Makefile.common | 4 + - configure.ac | 9 + - gentpl.py | 5 +- - grub-core/Makefile.am | 7 + - grub-core/Makefile.core.def | 20 + - grub-core/kern/efi/mm.c | 29 +- - grub-core/kern/elfXX.c | 6 + - grub-core/kern/loongarch64/cache.S | 26 + - grub-core/kern/loongarch64/dl.c | 258 +++++++++ - grub-core/kern/loongarch64/efi/init.c | 76 +++ - grub-core/kern/loongarch64/efi/startup.S | 45 ++ - grub-core/kern/loongarch64/init.c | 47 ++ - grub-core/lib/loongarch64/efi/loongson.c | 505 ++++++++++++++++ - grub-core/lib/loongarch64/efi/loongson_asm.S | 58 ++ - grub-core/lib/loongarch64/relocator.c | 163 ++++++ - grub-core/lib/loongarch64/relocator_asm.S | 51 ++ - grub-core/lib/loongarch64/setjmp.S | 74 +++ - grub-core/lib/loongson/reboot.c | 33 ++ - grub-core/lib/setjmp.S | 2 + - grub-core/loader/efi/chainloader.c | 2 + - grub-core/loader/loongarch64/linux.c | 580 +++++++++++++++++++ - include/grub/dl.h | 2 +- - include/grub/efi/api.h | 3 +- - include/grub/efi/pe32.h | 2 + - include/grub/elf.h | 55 ++ - include/grub/loongarch64/asm.h | 10 + - include/grub/loongarch64/efi/boot.h | 0 - include/grub/loongarch64/efi/loader.h | 25 + - include/grub/loongarch64/efi/loongson.h | 290 ++++++++++ - include/grub/loongarch64/efi/memory.h | 14 + - include/grub/loongarch64/efi/time.h | 0 - include/grub/loongarch64/io.h | 62 ++ - include/grub/loongarch64/kernel.h | 24 + - include/grub/loongarch64/linux.h | 22 + - include/grub/loongarch64/loongarch64.h | 30 + - include/grub/loongarch64/memory.h | 57 ++ - include/grub/loongarch64/relocator.h | 38 ++ - include/grub/loongarch64/setjmp.h | 27 + - include/grub/loongarch64/time.h | 39 ++ - include/grub/loongarch64/types.h | 34 ++ - include/grub/util/install.h | 1 + - util/grub-install-common.c | 43 +- - util/grub-install.c | 16 + - util/grub-mkimagexx.c | 349 ++++++++++- - util/grub-mknetdir.c | 3 +- - util/grub-module-verifier.c | 46 ++ - util/mkimage.c | 16 + - 47 files changed, 3176 insertions(+), 32 deletions(-) - create mode 100644 grub-core/kern/loongarch64/cache.S - create mode 100644 grub-core/kern/loongarch64/dl.c - create mode 100644 grub-core/kern/loongarch64/efi/init.c - create mode 100644 grub-core/kern/loongarch64/efi/startup.S - create mode 100644 grub-core/kern/loongarch64/init.c - create mode 100644 grub-core/lib/loongarch64/efi/loongson.c - create mode 100644 grub-core/lib/loongarch64/efi/loongson_asm.S - create mode 100644 grub-core/lib/loongarch64/relocator.c - create mode 100644 grub-core/lib/loongarch64/relocator_asm.S - create mode 100644 grub-core/lib/loongarch64/setjmp.S - create mode 100644 grub-core/lib/loongson/reboot.c - create mode 100644 grub-core/loader/loongarch64/linux.c - create mode 100644 include/grub/loongarch64/asm.h - create mode 100644 include/grub/loongarch64/efi/boot.h - create mode 100644 include/grub/loongarch64/efi/loader.h - create mode 100644 include/grub/loongarch64/efi/loongson.h - create mode 100644 include/grub/loongarch64/efi/memory.h - create mode 100644 include/grub/loongarch64/efi/time.h - create mode 100644 include/grub/loongarch64/io.h - create mode 100644 include/grub/loongarch64/kernel.h - create mode 100644 include/grub/loongarch64/linux.h - create mode 100644 include/grub/loongarch64/loongarch64.h - create mode 100644 include/grub/loongarch64/memory.h - create mode 100644 include/grub/loongarch64/relocator.h - create mode 100644 include/grub/loongarch64/setjmp.h - create mode 100644 include/grub/loongarch64/time.h - create mode 100644 include/grub/loongarch64/types.h diff --git a/conf/Makefile.common b/conf/Makefile.common -index 521cdda..cc1d190 100644 +index 521cdda..d9f058b 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -20,6 +20,10 @@ endif @@ -89,8 +13,8 @@ index 521cdda..cc1d190 100644 CFLAGS_PLATFORM += -mcpu=powerpc endif +if COND_loongarch64 -+ CFLAGS_PLATFORM += -fno-strict-aliasing -march=loongarch64 -mabi=lp64 -fno-plt -Wa,-mla-global-with-pcrel -+ CPPFLAGS_PLATFORM = -fno-strict-aliasing -march=loongarch64 -mabi=lp64 -fno-plt -Wa,-mla-global-with-pcrel ++ CFLAGS_PLATFORM += -fno-strict-aliasing -march=loongarch64 -mabi=lp64 -fno-plt -Wa,-mla-global-with-abs -mcmodel=large ++ CPPFLAGS_PLATFORM = -fno-strict-aliasing -march=loongarch64 -mabi=lp64 -fno-plt -Wa,-mla-global-with-abs -mcmodel=large +endif # Other options @@ -173,10 +97,10 @@ index d662c30..3afd642 100644 GROUPS["uboot"] = [ "arm_uboot" ] GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ] diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am -index 308ad88..24e2ac3 100644 +index 308ad88..a976fad 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am -@@ -222,6 +222,13 @@ KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h +@@ -222,6 +222,14 @@ KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h endif @@ -184,6 +108,7 @@ index 308ad88..24e2ac3 100644 +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdt.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loongson.h +endif + @@ -191,7 +116,7 @@ index 308ad88..24e2ac3 100644 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index ef06f8c..74e66d3 100644 +index ef06f8c..54f6bf0 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -95,6 +95,9 @@ kernel = { @@ -212,7 +137,7 @@ index ef06f8c..74e66d3 100644 sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S; powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; arm_uboot_startup = kern/arm/startup.S; -@@ -295,6 +299,14 @@ kernel = { +@@ -295,6 +299,15 @@ kernel = { extra_dist = video/sis315_init.c; mips_loongson = commands/keylayouts.c; @@ -220,14 +145,15 @@ index ef06f8c..74e66d3 100644 + loongarch64 = kern/loongarch64/dl.c; + loongarch64 = kern/loongarch64/cache.S; + loongarch64 = kern/generic/rtc_get_time_ms.c; ++ loongarch64 = kern/efi/fdt.c; ++ loongarch64 = lib/fdt.c; + loongarch64_efi = kern/loongarch64/efi/init.c; + loongarch64_efi = lib/loongarch64/efi/loongson.c; -+ loongarch64_efi = lib/loongarch64/efi/loongson_asm.S; + powerpc_ieee1275 = kern/powerpc/cache.S; powerpc_ieee1275 = kern/powerpc/dl.c; powerpc_ieee1275 = kern/powerpc/compiler-rt.S; -@@ -810,6 +822,7 @@ module = { +@@ -810,6 +823,7 @@ module = { enable = sparc64_ieee1275; enable = powerpc_ieee1275; enable = mips_arc; @@ -235,7 +161,7 @@ index ef06f8c..74e66d3 100644 enable = ia64_efi; enable = arm_efi; enable = arm64_efi; -@@ -896,6 +909,7 @@ module = { +@@ -896,6 +910,7 @@ module = { i386_qemu = lib/i386/halt.c; xen = lib/xen/halt.c; efi = lib/efi/halt.c; @@ -243,7 +169,7 @@ index ef06f8c..74e66d3 100644 ieee1275 = lib/ieee1275/halt.c; emu = lib/emu/halt.c; uboot = lib/dummy/halt.c; -@@ -911,6 +925,7 @@ module = { +@@ -911,6 +926,7 @@ module = { mips_arc = lib/mips/arc/reboot.c; mips_loongson = lib/mips/loongson/reboot.c; mips_qemu_mips = lib/mips/qemu_mips/reboot.c; @@ -251,7 +177,7 @@ index ef06f8c..74e66d3 100644 xen = lib/xen/reboot.c; uboot = lib/uboot/reboot.c; arm_coreboot = lib/dummy/reboot.c; -@@ -1608,6 +1623,8 @@ module = { +@@ -1608,6 +1624,8 @@ module = { efi = lib/efi/relocator.c; mips = lib/mips/relocator_asm.S; mips = lib/mips/relocator.c; @@ -260,7 +186,7 @@ index ef06f8c..74e66d3 100644 powerpc = lib/powerpc/relocator_asm.S; powerpc = lib/powerpc/relocator.c; xen = lib/xen/relocator.c; -@@ -1620,6 +1637,7 @@ module = { +@@ -1620,6 +1638,7 @@ module = { extra_dist = kern/powerpc/cache_flush.S; enable = mips; @@ -268,7 +194,7 @@ index ef06f8c..74e66d3 100644 enable = powerpc; enable = x86; enable = xen; -@@ -1737,6 +1755,7 @@ module = { +@@ -1737,6 +1756,7 @@ module = { xen = loader/i386/xen.c; i386_pc = lib/i386/pc/vesa_modes_table.c; mips = loader/mips/linux.c; @@ -276,7 +202,7 @@ index ef06f8c..74e66d3 100644 powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c; sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c; ia64_efi = loader/ia64/efi/linux.c; -@@ -1838,6 +1857,7 @@ module = { +@@ -1838,6 +1858,7 @@ module = { enable = arm_efi; enable = arm64_efi; enable = mips; @@ -285,22 +211,42 @@ index ef06f8c..74e66d3 100644 module = { diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index 9e76f23..fb087e3 100644 +index 8a89614..0b5f158 100644 --- a/grub-core/kern/efi/mm.c +++ b/grub-core/kern/efi/mm.c -@@ -157,7 +157,11 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, +@@ -122,7 +122,11 @@ grub_efi_allocate_pages_max (grub_efi_physical_address_t max, + grub_efi_boot_services_t *b; + grub_efi_physical_address_t address = max; + ++#ifdef GRUB_CPU_LOONGARCH64 ++ if (max > grub_efi_max_usable_address()) ++#else + if (max > GRUB_EFI_MAX_USABLE_ADDRESS) ++#endif + return 0; + + b = grub_efi_system_table->boot_services; +@@ -157,11 +161,19 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, grub_efi_physical_address_t ret = address; /* Limit the memory access to less than 4GB for 32-bit platforms. */ +#ifdef GRUB_CPU_LOONGARCH64 + if (address > grub_efi_max_usable_address()) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("invalid memory address 0x%llx"), ++ address); +#else if (address > GRUB_EFI_MAX_USABLE_ADDRESS) -+#endif { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid memory address (0x%llx > 0x%llx)"), -@@ -177,7 +181,11 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, + address, GRUB_EFI_MAX_USABLE_ADDRESS); ++#endif + return NULL; + } + +@@ -177,7 +189,11 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, { /* Uggh, the address 0 was allocated... This is too annoying, so reallocate another one. */ @@ -312,23 +258,23 @@ index 9e76f23..fb087e3 100644 status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &ret); grub_efi_free_pages (0, pages); if (status != GRUB_EFI_SUCCESS) -@@ -195,9 +203,14 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, +@@ -195,9 +211,15 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, void * grub_efi_allocate_any_pages (grub_efi_uintn_t pages) { -- return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS, +#ifdef GRUB_CPU_LOONGARCH64 + return grub_efi_allocate_pages_real (grub_efi_max_usable_address(), ++ pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, ++ GRUB_EFI_LOADER_DATA); ++#else + return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS, pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA); -+#else -+ return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS, -+ pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, -+#endif GRUB_EFI_LOADER_DATA); ++#endif } void * -@@ -471,7 +484,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, +@@ -471,7 +493,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) { if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY @@ -339,11 +285,10 @@ index 9e76f23..fb087e3 100644 && desc->physical_start <= GRUB_EFI_MAX_ALLOCATION_ADDRESS #endif && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000 -@@ -486,8 +501,14 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, - - desc->physical_start); +@@ -487,7 +511,14 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, desc->physical_start = 0x100000; } -- + -#if 1 +#ifdef GRUB_CPU_LOONGARCH64 + if (BYTES_TO_PAGES (filtered_desc->physical_start) @@ -356,23 +301,43 @@ index 9e76f23..fb087e3 100644 if (BYTES_TO_PAGES (filtered_desc->physical_start) + filtered_desc->num_pages > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS)) -diff --git a/grub-core/kern/elfXX.c b/grub-core/kern/elfXX.c -index 1859d18..8b1dce9 100644 ---- a/grub-core/kern/elfXX.c -+++ b/grub-core/kern/elfXX.c -@@ -134,6 +134,12 @@ grub_elfXX_load (grub_elf_t elf, const char *filename, - load_addr &= 0x3FFFFFFFFFFFFFFFULL; - break; - } +@@ -765,7 +796,7 @@ grub_efi_mm_init (void) + 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + } + +-#if defined (__aarch64__) || defined (__arm__) ++#if defined (__aarch64__) || defined (__arm__) || defined (__loongarch__) + grub_err_t + grub_efi_get_ram_base(grub_addr_t *base_addr) + { +@@ -784,9 +815,15 @@ grub_efi_get_ram_base(grub_addr_t *base_addr) + if (ret < 1) + return GRUB_ERR_BUG; + ++#ifdef GRUB_CPU_LOONGARCH64 ++ for (desc = memory_map, *base_addr = grub_efi_max_usable_address(); ++ (grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size); ++ desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) ++#else + for (desc = memory_map, *base_addr = GRUB_EFI_MAX_USABLE_ADDRESS; + (grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size); + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) ++#endif + { + if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY && + (desc->attribute & GRUB_EFI_MEMORY_WB)) +@@ -800,7 +837,11 @@ grub_efi_get_ram_base(grub_addr_t *base_addr) + } + } + +#ifdef GRUB_CPU_LOONGARCH64 -+ grub_uint64_t addr; -+ asm volatile ("csrrd %0, 0x181" : "=r" (addr)); -+ if ((load_addr >> 48) != (addr >> 48)) -+ return grub_error (GRUB_ERR_BAD_OS, "bad address space"); ++ if (*base_addr == grub_efi_max_usable_address()) ++#else + if (*base_addr == GRUB_EFI_MAX_USABLE_ADDRESS) +#endif - load_addr += (grub_addr_t) load_offset; + grub_dprintf ("efi", "base_addr 0x%016lx is probably wrong.\n", *base_addr); - if (load_addr < load_base) + grub_free(memory_map); diff --git a/grub-core/kern/loongarch64/cache.S b/grub-core/kern/loongarch64/cache.S new file mode 100644 index 0000000..d291c67 @@ -407,10 +372,10 @@ index 0000000..d291c67 + diff --git a/grub-core/kern/loongarch64/dl.c b/grub-core/kern/loongarch64/dl.c new file mode 100644 -index 0000000..a6fd387 +index 0000000..7d9e2a1 --- /dev/null +++ b/grub-core/kern/loongarch64/dl.c -@@ -0,0 +1,258 @@ +@@ -0,0 +1,266 @@ +/* loongarch64/dl.c - arch-dependent part of loadable module support */ +/* + * GRUB -- GRand Unified Bootloader @@ -669,12 +634,20 @@ index 0000000..a6fd387 + return GRUB_ERR_NONE; +} + ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++ return 1; ++} diff --git a/grub-core/kern/loongarch64/efi/init.c b/grub-core/kern/loongarch64/efi/init.c new file mode 100644 -index 0000000..b21d4f1 +index 0000000..632c39a --- /dev/null +++ b/grub-core/kern/loongarch64/efi/init.c -@@ -0,0 +1,76 @@ +@@ -0,0 +1,74 @@ +/* init.c - initialize an arm-based EFI system */ +/* + * GRUB -- GRand Unified Bootloader @@ -698,7 +671,7 @@ index 0000000..b21d4f1 +#include +#include +#include -+#include ++#include +#include +#include +#include @@ -719,15 +692,13 @@ index 0000000..b21d4f1 + tmr += 10; +} + -+ -+ +void +grub_machine_init (void) +{ + grub_efi_boot_services_t *b; + + grub_efi_init (); -+ ++ + b = grub_efi_system_table->boot_services; + efi_call_5 (b->create_event, GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL, + GRUB_EFI_TPL_CALLBACK, grub_loongson_increment_timer, NULL, &tmr_evt); @@ -857,10 +828,10 @@ index 0000000..b2de930 +} diff --git a/grub-core/lib/loongarch64/efi/loongson.c b/grub-core/lib/loongarch64/efi/loongson.c new file mode 100644 -index 0000000..8b60d82 +index 0000000..eda1e1c --- /dev/null +++ b/grub-core/lib/loongarch64/efi/loongson.c -@@ -0,0 +1,505 @@ +@@ -0,0 +1,119 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2017 Free Software Foundation, Inc. @@ -886,400 +857,14 @@ index 0000000..8b60d82 +#include +#include + -+#define loongson_params (&loongson_boot_params->boot_params.efi.smbios.lp) -+#define loongson_boot_params_size ALIGN_UP (sizeof (*loongson_boot_params), 8) -+#define loongson_reset_code_size (&grub_efi_loongson_reset_end - &grub_efi_loongson_reset_start) -+ -+extern grub_uint8_t grub_efi_loongson_reset_start; -+extern grub_uint8_t grub_efi_loongson_reset_end; -+ -+static struct -+{ -+ grub_efi_loongson_boot_params boot_params; -+ grub_efi_loongson_memory_map memory_map; -+ grub_efi_loongson_cpu_info cpu_info; -+ grub_efi_loongson_system_info system_info; -+ grub_efi_loongson_irq_src_routing_table irq_src_routing_table; -+ grub_efi_loongson_interface_info interface_info; -+ grub_efi_loongson_special_attribute special_attribute; -+ grub_efi_loongson_board_devices board_devices; -+} GRUB_PACKED -+* loongson_boot_params; -+ -+static void -+grub_efi_loongson_init_reset_system (void) -+{ -+ grub_efi_loongson_boot_params *boot_params; -+ grub_uint8_t *reset_code_addr = (grub_uint8_t *) loongson_boot_params + -+ loongson_boot_params_size; -+ -+ boot_params = &loongson_boot_params->boot_params; -+ grub_efi_loongson_reset_system_addr = -+ (grub_uint64_t) grub_efi_system_table->runtime_services->reset_system; -+ grub_memcpy (reset_code_addr, &grub_efi_loongson_reset_start, loongson_reset_code_size); -+ grub_arch_sync_caches (reset_code_addr, loongson_reset_code_size); -+ -+ boot_params->reset_system.reset_cold = (grub_uint64_t) reset_code_addr + -+ ((grub_uint64_t) &grub_efi_loongson_reset_cold - -+ (grub_uint64_t) &grub_efi_loongson_reset_start); -+ boot_params->reset_system.reset_warm = (grub_uint64_t) reset_code_addr + -+ ((grub_uint64_t) &grub_efi_loongson_reset_warm - -+ (grub_uint64_t) &grub_efi_loongson_reset_start); -+ boot_params->reset_system.shutdown = (grub_uint64_t) reset_code_addr + -+ ((grub_uint64_t) &grub_efi_loongson_reset_shutdown - -+ (grub_uint64_t) &grub_efi_loongson_reset_start); -+ boot_params->reset_system.do_suspend = (grub_uint64_t) reset_code_addr + -+ ((grub_uint64_t) &grub_efi_loongson_reset_suspend - -+ (grub_uint64_t) &grub_efi_loongson_reset_start); -+} -+ -+static void -+grub_efi_loongson_init_smbios (grub_efi_loongson_smbios_table *smbios_table) -+{ -+ grub_efi_loongson_smbios_table *dst = &loongson_boot_params->boot_params.efi.smbios; -+ -+ dst->vers = smbios_table->vers; -+ dst->vga_bios = smbios_table->vga_bios; -+} -+ -+static void -+grub_efi_loongson_init_cpu_info (grub_efi_loongson_smbios_table *smbios_table) -+{ -+ grub_efi_loongson_cpu_info *src = (void *) smbios_table->lp.cpu_offset; -+ grub_efi_loongson_cpu_info *dst = &loongson_boot_params->cpu_info; -+ -+ if (!src) -+ return; -+ -+ grub_memcpy (dst, src, sizeof (grub_efi_loongson_cpu_info)); -+ loongson_params->cpu_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; -+} -+ -+static void -+grub_efi_loongson_init_system_info (grub_efi_loongson_smbios_table *smbios_table) -+{ -+ grub_efi_loongson_system_info *src = (void *) smbios_table->lp.system_offset; -+ grub_efi_loongson_system_info *dst = &loongson_boot_params->system_info; -+ -+ if (!src) -+ return; -+ -+ grub_memcpy (dst, src, sizeof (grub_efi_loongson_system_info)); -+ loongson_params->system_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; -+} -+ -+static void -+grub_efi_loongson_init_irq_src_routing_table (grub_efi_loongson_smbios_table *smbios_table) -+{ -+ grub_efi_loongson_irq_src_routing_table *src = (void *) smbios_table->lp.irq_offset; -+ grub_efi_loongson_irq_src_routing_table *dst = &loongson_boot_params->irq_src_routing_table; -+ -+ if (!src) -+ return; -+ -+ grub_memcpy (dst, src, sizeof (grub_efi_loongson_irq_src_routing_table)); -+ loongson_params->irq_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; -+} -+ -+static void -+grub_efi_loongson_init_interface_info (grub_efi_loongson_smbios_table *smbios_table) -+{ -+ grub_efi_loongson_interface_info *src = (void *) smbios_table->lp.interface_offset; -+ grub_efi_loongson_interface_info *dst = &loongson_boot_params->interface_info; -+ -+ if (!src) -+ return; -+ -+ grub_memcpy (dst, src, sizeof (grub_efi_loongson_interface_info)); -+ loongson_params->interface_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; -+} -+ -+static void -+grub_efi_loongson_init_special_attribute (grub_efi_loongson_smbios_table *smbios_table) -+{ -+ grub_efi_loongson_special_attribute *src = (void *) smbios_table->lp.special_offset; -+ grub_efi_loongson_special_attribute *dst = &loongson_boot_params->special_attribute; -+ -+ if (!src) -+ return; -+ -+ grub_memcpy (dst, src, sizeof (grub_efi_loongson_special_attribute)); -+ loongson_params->special_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; -+} -+ -+static void -+grub_efi_loongson_init_board_devices (grub_efi_loongson_smbios_table *smbios_table) -+{ -+ grub_efi_loongson_board_devices *src = (void *) smbios_table->lp.boarddev_table_offset; -+ grub_efi_loongson_board_devices *dst = &loongson_boot_params->board_devices; -+ -+ if (!src) -+ return; -+ -+ grub_memcpy (dst, src, sizeof (grub_efi_loongson_board_devices)); -+ loongson_params->boarddev_table_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; -+} -+ -+#define ADD_MEMORY_DESCRIPTOR(desc, size) \ -+ ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) -+ -+static void -+grub_efi_loongson_init_memory_map (grub_efi_loongson_smbios_table *smbios_table, -+ grub_efi_memory_descriptor_t *mmap_buf, -+ grub_efi_uintn_t mmap_size, -+ grub_efi_uintn_t desc_size) -+{ -+ grub_efi_loongson_memory_map *src = (void *) smbios_table->lp.memory_offset; -+ grub_efi_loongson_memory_map *dst = &loongson_boot_params->memory_map; -+ grub_efi_memory_descriptor_t *mmap_end; -+ grub_efi_memory_descriptor_t *desc; -+ grub_efi_memory_descriptor_t *desc_next; -+ grub_efi_uint32_t mem_types_reserved[] = -+ { -+ 1, // GRUB_EFI_RESERVED_MEMORY_TYPE -+ 0, // GRUB_EFI_LOADER_CODE -+ 0, // GRUB_EFI_LOADER_DATA -+ 0, // GRUB_EFI_BOOT_SERVICES_CODE -+ 0, // GRUB_EFI_BOOT_SERVICES_DATA -+ 1, // GRUB_EFI_RUNTIME_SERVICES_CODE -+ 1, // GRUB_EFI_RUNTIME_SERVICES_DATA -+ 0, // GRUB_EFI_CONVENTIONAL_MEMORY -+ 1, // GRUB_EFI_UNUSABLE_MEMORY -+ 0, // GRUB_EFI_ACPI_RECLAIM_MEMORY -+ 0, // GRUB_EFI_ACPI_MEMORY_NVS -+ 1, // GRUB_EFI_MEMORY_MAPPED_IO -+ 1, // GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE -+ 1, // GRUB_EFI_PAL_CODE -+ 1, // GRUB_EFI_PERSISTENT_MEMORY -+ }; -+ grub_uint32_t need_sort = 1; -+ -+ if (!src) -+ return; -+ -+ dst->vers = src->vers; -+ dst->nr_map = 0; -+ dst->mem_freq = src->mem_freq; -+ loongson_params->memory_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; -+ -+ if (!mmap_buf || !mmap_size || !desc_size) -+ return; -+ -+ mmap_end = ADD_MEMORY_DESCRIPTOR (mmap_buf, mmap_size); -+ -+ /* drop reserved */ -+ for (desc = mmap_buf, -+ desc_next = desc; -+ desc < mmap_end; -+ desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size)) -+ { -+ desc->type = mem_types_reserved[desc->type]; -+ if (desc->type) -+ continue; -+ -+ if (desc != desc_next) -+ *desc_next = *desc; -+ desc_next = ADD_MEMORY_DESCRIPTOR (desc_next, desc_size); -+ } -+ mmap_end = desc_next; -+ -+ /* sort: low->high */ -+ while (need_sort) -+ { -+ need_sort = 0; -+ -+ for (desc = mmap_buf, -+ desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size); -+ (desc < mmap_end) && (desc_next < mmap_end); -+ desc = desc_next, -+ desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size)) -+ { -+ grub_efi_memory_descriptor_t tmp; -+ -+ if (desc->physical_start <= desc_next->physical_start) -+ continue; -+ -+ tmp = *desc; -+ *desc = *desc_next; -+ *desc_next = tmp; -+ need_sort = 1; -+ } -+ } -+ -+ /* combine continuous memory map */ -+ for (desc = mmap_buf, -+ desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size); -+ desc_next < mmap_end; -+ desc_next = ADD_MEMORY_DESCRIPTOR (desc_next, desc_size)) -+ { -+ grub_efi_physical_address_t prev_end = desc->physical_start + (desc->num_pages << 12); -+ -+ if (prev_end == desc_next->physical_start) -+ { -+ desc->num_pages += desc_next->num_pages; -+ continue; -+ } -+ -+ desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size); -+ grub_memcpy (desc, desc_next, desc_size); -+ } -+ mmap_end = ADD_MEMORY_DESCRIPTOR (desc, desc_size); -+ -+ /* write to loongson memory map */ -+ for (desc = mmap_buf; -+ desc < mmap_end; -+ desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size)) -+ { -+ grub_efi_physical_address_t physical_start = grub_vtop ((void *) desc->physical_start); -+ grub_efi_physical_address_t physical_end = physical_start + (desc->num_pages << 12); -+ -+ physical_start = ALIGN_UP (physical_start, 0x100000); -+ physical_end = ALIGN_DOWN (physical_end, 0x100000); -+ -+ if (physical_start >= physical_end || (physical_end - physical_start) < 0x100000) -+ continue; -+ -+ dst->map[dst->nr_map].node_id = (desc->physical_start >> 44) & 0xf; -+ dst->map[dst->nr_map].mem_type = GRUB_EFI_LOONGSON_SYSTEM_RAM; -+ dst->map[dst->nr_map].mem_start = physical_start; -+ dst->map[dst->nr_map].mem_size = (physical_end - physical_start) >> 20; -+ -+ grub_dprintf ("loongson", "memory map %03u: 0x%016lx 0x%016lx @ %u\n", -+ dst->nr_map, physical_start, physical_end - physical_start, -+ dst->map[dst->nr_map].node_id); -+ -+ dst->nr_map ++; -+ } -+} -+ -+#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) -+#define SUB_MEMORY_DESCRIPTOR(desc, size) \ -+ ((grub_efi_memory_descriptor_t *) ((char *) (desc) - (size))) -+ -+void -+grub_efi_loongson_alloc_boot_params (void) -+{ -+ grub_efi_memory_descriptor_t *mmap_buf; -+ grub_efi_memory_descriptor_t *mmap_end; -+ grub_efi_memory_descriptor_t *desc; -+ grub_efi_uintn_t mmap_size; -+ grub_efi_uintn_t desc_size; -+ grub_efi_physical_address_t address; -+ grub_efi_allocate_type_t type; -+ grub_efi_uintn_t pages; -+ grub_efi_status_t status; -+ grub_efi_boot_services_t *b; -+ int mm_status; -+ -+ type = GRUB_EFI_ALLOCATE_ADDRESS; -+ pages = BYTES_TO_PAGES (loongson_boot_params_size + loongson_reset_code_size); -+ -+ mmap_size = (1 << 12); -+ mmap_buf = grub_malloc (mmap_size); -+ if (!mmap_buf) -+ grub_fatal ("out of memory!"); -+ -+ mm_status = grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0); -+ if (mm_status == 0) -+ { -+ grub_free (mmap_buf); -+ mmap_size += desc_size * 32; -+ -+ mmap_buf = grub_malloc (mmap_size); -+ if (!mmap_buf) -+ grub_fatal ("out of memory!"); -+ -+ mm_status = grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0); -+ } -+ -+ if (mm_status < 0) -+ grub_fatal ("cannot get memory map!"); -+ -+ mmap_end = ADD_MEMORY_DESCRIPTOR (mmap_buf, mmap_size); -+ -+ for (desc = SUB_MEMORY_DESCRIPTOR (mmap_end, desc_size); -+ desc >= mmap_buf; -+ desc = SUB_MEMORY_DESCRIPTOR (desc, desc_size)) -+ { -+ if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY) -+ continue; -+ if (desc->physical_start >= grub_efi_max_usable_address()) -+ continue; -+ if (desc->num_pages < pages) -+ continue; -+ -+ address = desc->physical_start; -+ break; -+ } -+ -+ grub_free (mmap_buf); -+ -+ b = grub_efi_system_table->boot_services; -+ status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_RUNTIME_SERVICES_DATA, pages, &address); -+ if (status != GRUB_EFI_SUCCESS) -+ grub_fatal ("cannot allocate Loongson boot parameters!"); -+ -+ loongson_boot_params = (void *) ((grub_addr_t) address); -+} -+ -+void -+grub_efi_loongson_free_boot_params (void) -+{ -+ grub_efi_free_pages ((grub_addr_t) loongson_boot_params, -+ BYTES_TO_PAGES (loongson_boot_params_size + loongson_reset_code_size)); -+} -+ -+void * -+grub_efi_loongson_get_smbios_table (void) ++unsigned long ++grub_efi_get_bpi_version (const char *str) +{ -+ static grub_efi_loongson_smbios_table *smbios_table; -+ grub_efi_loongson_boot_params *old_boot_params; -+ struct bootparamsinterface* boot_params; -+ void * tmp_boot_params = NULL; -+ char * p = NULL; -+ if(smbios_table) -+ return smbios_table; -+ -+ tmp_boot_params = grub_efi_loongson_get_boot_params(); -+ if(tmp_boot_params == NULL) -+ { -+ grub_dprintf("loongson", "tmp_boot_params is NULL\n"); -+ return tmp_boot_params; -+ } -+ -+ boot_params = (struct bootparamsinterface *)tmp_boot_params; -+ p = (char *)&(boot_params->signature); -+ if(grub_strncmp(p, "BPI", 3) == 0) -+ { -+ grub_dprintf("loongson", "find new bpi\n"); -+ return boot_params ? boot_params : 0; -+ } -+ else -+ { -+ old_boot_params = (grub_efi_loongson_boot_params *)tmp_boot_params; -+ /* -+ { -+ grub_dprintf("loongson", "smbios addr%llx\n", &old_boot_params->efi.smbios); -+ grub_dprintf("loongson", "smbios vers%d\n", (grub_uint16_t)(&old_boot_params->efi.smbios.vers)); -+ grub_dprintf("loongson", "smbios vga_bios%d\n", &old_boot_params->efi.smbios.vga_bios); -+ grub_dprintf("loongson", "lp memory offset %llx\n", &old_boot_params->efi.smbios.lp.memory_offset); -+ grub_dprintf("loongson", "lp cpu offset %llx\n", &old_boot_params->efi.smbios.lp.cpu_offset); -+ grub_dprintf("loongson", "lp system offset %llx\n", &old_boot_params->efi.smbios.lp.system_offset); -+ grub_dprintf("loongson", "lp irq offset %llx\n", &old_boot_params->efi.smbios.lp.irq_offset); -+ grub_dprintf("loongson", "lp interface offset %llx\n", &old_boot_params->efi.smbios.p.interface_offset); -+ grub_dprintf("loongson", "lp special offset %llx\n", &old_boot_params->efi.smbios.lp.special_offset); -+ grub_dprintf("loongson", "lp boarddev table offset %llx\n", &old_boot_params->efi.smbios.lp.boarddev_table_offset); -+ } -+ */ -+ return old_boot_params ? &old_boot_params->efi.smbios : 0; -+ } ++ unsigned long version = GRUB_EFI_BPI_VER_NONE; + -+} ++ version = grub_strtoul (str + 4, 0, 0); + -+int -+grub_efi_is_loongson (void) -+{ -+ return grub_efi_loongson_get_smbios_table () ? 1 : 0; ++ return version; +} + +void * @@ -1287,20 +872,20 @@ index 0000000..8b60d82 +{ + static void * boot_params = NULL; + grub_efi_configuration_table_t *tables; -+ grub_efi_guid_t smbios_guid = GRUB_EFI_LOONGSON_SMBIOS_TABLE_GUID; ++ grub_efi_guid_t loongson_bpi_guid = GRUB_EFI_LOONGSON_BPI_TABLE_GUID; + unsigned int i; + + if (boot_params) + return boot_params; + -+ /* Look for Loongson SMBIOS in UEFI config tables. */ ++ /* Look for Loongson boot params interface in UEFI config tables. */ + tables = grub_efi_system_table->configuration_table; + + for (i = 0; i < grub_efi_system_table->num_table_entries; i++) -+ if (grub_memcmp (&tables[i].vendor_guid, &smbios_guid, sizeof (smbios_guid)) == 0) ++ if (grub_memcmp (&tables[i].vendor_guid, &loongson_bpi_guid, sizeof (loongson_bpi_guid)) == 0) + { + boot_params= tables[i].vendor_table; -+ grub_dprintf ("loongson", "found registered SMBIOS @ %p\n", boot_params); ++ grub_dprintf ("loongson", "found registered BPI @ %p\n", boot_params); + break; + } + return boot_params; @@ -1330,8 +915,9 @@ index 0000000..8b60d82 +} + + -+grub_uint32_t -+grub_efi_loongson_memmap_sort(struct memmap array[], grub_uint32_t length, mem_map * bpmem, grub_uint32_t index, grub_uint32_t memtype) ++grub_uint32_t ++grub_efi_loongson_memmap_v1_sort(struct memmap_v1 array[], grub_uint32_t length, ++ mem_map_v1 * bpmem, grub_uint32_t index, grub_uint32_t memtype) +{ + grub_uint64_t tempmemsize = 0; + grub_uint32_t j = 0; @@ -1342,19 +928,19 @@ index 0000000..8b60d82 + tempmemsize = array[j].memsize; + for(t = j + 1; t < length; t++) + { -+ if(array[j].memstart + tempmemsize == array[t].memstart) ++ if(array[j].memstart + tempmemsize == array[t].memstart) + { + tempmemsize += array[t].memsize; + } + else -+ { ++ { + break; + } + } + bpmem->map[index].memtype = memtype; + bpmem->map[index].memstart = array[j].memstart; + bpmem->map[index].memsize = tempmemsize; -+ grub_dprintf("loongson", "map[%d]:type %x, start 0x%llx, end 0x%llx\n", ++ grub_dprintf("loongson", "v1 map[%d]:type %x, start 0x%lx, end 0x%lx\n", + index, + bpmem->map[index].memtype, + bpmem->map[index].memstart, @@ -1365,74 +951,9 @@ index 0000000..8b60d82 + } + return index; +} -+ -diff --git a/grub-core/lib/loongarch64/efi/loongson_asm.S b/grub-core/lib/loongarch64/efi/loongson_asm.S -new file mode 100644 -index 0000000..4a04d34 ---- /dev/null -+++ b/grub-core/lib/loongarch64/efi/loongson_asm.S -@@ -0,0 +1,58 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+ -+ .file "loongson_asm.S" -+ .text -+ -+ .align 4 -+ -+VARIABLE (grub_efi_loongson_reset_start) -+ -+VARIABLE (grub_efi_loongson_reset_system_addr) -+ .dword 0 -+ -+reset_system: -+ bl 1f -+ move $a1, $zero -+1: -+ ld.d $t8, $ra, -16 -+ move $a2, $zero -+ jr $t8 -+ move $a3, $zero -+ -+FUNCTION(grub_efi_loongson_reset_cold) -+ b reset_system -+ li.w $a0, 0 -+ -+FUNCTION(grub_efi_loongson_reset_warm) -+ b reset_system -+ li.w $a0, 1 -+ -+FUNCTION(grub_efi_loongson_reset_shutdown) -+ b reset_system -+ li.w $a0, 2 -+ -+FUNCTION(grub_efi_loongson_reset_suspend) -+ b reset_system -+ li.w $a0, 3 -+ -+VARIABLE (grub_efi_loongson_reset_end) -+ -+ diff --git a/grub-core/lib/loongarch64/relocator.c b/grub-core/lib/loongarch64/relocator.c new file mode 100644 -index 0000000..f6c1b01 +index 0000000..4b253ca --- /dev/null +++ b/grub-core/lib/loongarch64/relocator.c @@ -0,0 +1,163 @@ @@ -1510,12 +1031,9 @@ index 0000000..f6c1b01 +static void +write_jump (int regn, void **target) +{ -+ grub_uint32_t andi=0x4c000000; -+ grub_uint32_t nop=0x03400000; ++ grub_uint32_t jirl=0x4c000000; + -+ *(grub_uint32_t *) *target = (andi | (grub_uint32_t)(regn<<5)); -+ *target = ((grub_uint32_t *) *target) + 1; -+ *(grub_uint32_t *) *target = nop; ++ *(grub_uint32_t *) *target = (jirl | (grub_uint32_t)(regn<<5)); + *target = ((grub_uint32_t *) *target) + 1; +} + @@ -1585,6 +1103,9 @@ index 0000000..f6c1b01 + + grub_arch_sync_caches ((void *) relst, relsize); + ++ asm volatile ( ++ "ibar 0 \n"); ++ + grub_uint64_t val; + __asm__ __volatile__( + "li.w %0, 0x4\n\t" @@ -1789,10 +1310,10 @@ index f6e4905..023dc90 100644 #error "Unknown target cpu type" #endif diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index 29663f7..c0ca17d 100644 +index b72e6bd..f4066b5 100644 --- a/grub-core/loader/efi/chainloader.c +++ b/grub-core/loader/efi/chainloader.c -@@ -332,6 +332,8 @@ static const grub_uint16_t machine_type __attribute__((__unused__)) = +@@ -343,6 +343,8 @@ static const grub_uint16_t machine_type __attribute__((__unused__)) = GRUB_PE32_MACHINE_I386; #elif defined(__ia64__) GRUB_PE32_MACHINE_IA64; @@ -1803,10 +1324,10 @@ index 29663f7..c0ca17d 100644 #endif diff --git a/grub-core/loader/loongarch64/linux.c b/grub-core/loader/loongarch64/linux.c new file mode 100644 -index 0000000..c769bb2 +index 0000000..7594ca2 --- /dev/null +++ b/grub-core/loader/loongarch64/linux.c -@@ -0,0 +1,580 @@ +@@ -0,0 +1,690 @@ +/* linux.c - boot Linux */ +/* + * GRUB -- GRand Unified Bootloader @@ -1838,10 +1359,12 @@ index 0000000..c769bb2 +#include +#include +#include ++#include +#include +#include +#include -+ ++#include ++#include + +GRUB_MOD_LICENSE ("GPLv3+"); + @@ -1849,253 +1372,302 @@ index 0000000..c769bb2 + +typedef unsigned long size_t; + -+static grub_dl_t my_mod; ++#define FDT_ADDR_CELLS_STRING "#address-cells" ++#define FDT_SIZE_CELLS_STRING "#size-cells" ++#define FDT_ADDR_SIZE_EXTRA ((2 * grub_fdt_prop_entry_size (sizeof(grub_uint32_t))) + \ ++ sizeof (FDT_ADDR_CELLS_STRING) + \ ++ sizeof (FDT_SIZE_CELLS_STRING)) + ++static grub_dl_t my_mod; +static int loaded; -+ -+static grub_uint32_t tmp_index = 0; ++static int initrd_loaded = 0; +static grub_size_t linux_size; + +static struct grub_relocator *relocator; +static grub_addr_t target_addr, entry_addr; +static int linux_argc; +static grub_uint8_t *linux_args_addr; -+static grub_off_t rd_addr_arg_off, rd_size_arg_off; -+static grub_off_t initrd_addr_arg_off; -+static int initrd_loaded = 0; -+ ++static grub_off_t rd_addr_arg_off, rd_size_arg_off, initrd_addr_arg_off; + -+static grub_uint32_t j = 0; -+static grub_uint32_t t = 0; -+grub_uint64_t tempMemsize = 0; -+grub_uint32_t free_index = 0; -+grub_uint32_t reserve_index = 0; -+grub_uint32_t acpi_table_index = 0; -+grub_uint32_t acpi_nvs_index = 0; ++static void *fdt; ++static int is_fdt_boot; ++static grub_addr_t initrd_start, initrd_end; ++static char *fdt_linux_args; + -+static inline grub_size_t -+page_align (grub_size_t size) ++static grub_err_t ++allocate_fdt_and_exit_boot (void) +{ -+ return (size + (1 << 12) - 1) & (~((1 << 12) - 1)); -+} ++ int node, retval; ++ grub_err_t err; ++ unsigned int size; ++ grub_efi_uintn_t mmap_size; ++ grub_efi_uintn_t desc_size; ++ grub_efi_uint32_t desc_version; ++ grub_efi_memory_descriptor_t *mmap_buf; + -+/* Find the optimal number of pages for the memory map. Is it better to -+ move this code to efi/mm.c? */ -+static grub_efi_uintn_t -+find_mmap_size (void) -+{ -+ static grub_efi_uintn_t mmap_size = 0; ++ size = GRUB_FDT_EMPTY_TREE_SZ + FDT_ADDR_SIZE_EXTRA + GRUB_EFI_LINUX_FDT_EXTRA_SPACE; ++ ++ fdt = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (size)); ++ if (!fdt) ++ return GRUB_ERR_OUT_OF_MEMORY; ++ ++ grub_fdt_create_empty_tree (fdt, size); ++ grub_fdt_set_prop32 (fdt, 0, FDT_ADDR_CELLS_STRING, 2); ++ grub_fdt_set_prop32 (fdt, 0, FDT_SIZE_CELLS_STRING, 2); ++ ++ node = grub_fdt_find_subnode (fdt, 0, "chosen"); ++ if (node < 0) ++ node = grub_fdt_add_subnode (fdt, 0, "chosen"); ++ if (node < 1) ++ goto failure; ++ ++ grub_dprintf ("loongson", "command_line %s, len %ld\n", ++ fdt_linux_args, grub_strlen(fdt_linux_args) + 1); ++ if ((fdt_linux_args != NULL) && (grub_strlen(fdt_linux_args) > 0)) { ++ retval = grub_fdt_set_prop (fdt, node, "bootargs", fdt_linux_args, ++ grub_strlen(fdt_linux_args) + 1); ++ if (retval) ++ goto failure; ++ } + -+ if (mmap_size != 0) -+ return mmap_size; ++ /* Set initrd info */ ++ if (initrd_start && initrd_end > initrd_start) ++ { ++ grub_dprintf ("linux", "Initrd @ %p-%p\n", ++ (void *) initrd_start, (void *) initrd_end); ++ ++ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start", ++ initrd_start); ++ if (retval) ++ goto failure; ++ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end", ++ initrd_end); ++ if (retval) ++ goto failure; ++ } + -+ mmap_size = (1 << 12); -+ while (1) -+ { -+ int ret; -+ grub_efi_memory_descriptor_t *mmap; -+ grub_efi_uintn_t desc_size; ++ node = grub_fdt_find_subnode (fdt, 0, "chosen"); ++ retval = grub_fdt_set_prop64 (fdt, node, "linux,uefi-system-table", ++ (grub_uint64_t)grub_efi_system_table); ++ if (retval) ++ goto failure; + -+ mmap = grub_malloc (mmap_size); -+ if (! mmap) -+ return 0; ++ mmap_size = grub_efi_find_mmap_size (); ++ if (! mmap_size) ++ return grub_errno; ++ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); ++ if (! mmap_buf) ++ return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); ++ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, ++ &desc_size, &desc_version); ++ if (err) ++ return err; + -+ ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0); -+ grub_free (mmap); ++ if (!mmap_buf || !mmap_size || !desc_size) ++ return GRUB_ERR_BAD_ARGUMENT; + -+ if (ret < 0) -+ { -+ grub_error (GRUB_ERR_IO, "cannot get memory map"); -+ return 0; -+ } -+ else if (ret > 0) -+ break; ++ retval = grub_fdt_set_prop64 (fdt, node, "linux,uefi-mmap-start", ++ (grub_uint64_t)mmap_buf); ++ if (retval) ++ goto failure; + -+ mmap_size += (1 << 12); -+ } ++ retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-size", ++ mmap_size); ++ if (retval) ++ goto failure; ++ ++ retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-desc-size", ++ desc_size); ++ if (retval) ++ goto failure; + ++ retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-desc-ver", ++ desc_version); ++ if (retval) ++ goto failure; + -+ /* Increase the size a bit for safety, because GRUB allocates more on -+ later, and EFI itself may allocate more. */ -+ mmap_size += (1 << 12); ++ return GRUB_ERR_NONE; + -+ return page_align (mmap_size); ++failure: ++ if (!fdt) { ++ return GRUB_ERR_BAD_OS; ++ } ++ grub_efi_free_pages ((grub_addr_t) fdt, ++ GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt))); ++ fdt = NULL; ++ return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); +} + +static grub_err_t -+grub_linux_boot (void) ++allocate_boot_params_and_exit_boot (void) +{ -+ struct grub_relocator64_state state; -+ grub_int8_t checksum = 0; ++ grub_efi_uintn_t mmap_size; ++ grub_efi_uintn_t desc_size; ++ grub_efi_uint32_t desc_version; ++ grub_efi_memory_descriptor_t *mmap_buf; + grub_efi_memory_descriptor_t * lsdesc = NULL; -+ -+ grub_memset (&state, 0, sizeof (state)); -+ -+ /* Boot the kernel. */ -+ state.gpr[1] = entry_addr; -+ grub_dprintf("loongson", "entry_addr is %p\n", state.gpr[1]); -+ state.gpr[4] = linux_argc; -+ grub_dprintf("loongson", "linux_argc is %d\n", state.gpr[4]); -+ state.gpr[5] = (grub_addr_t) linux_args_addr; -+ grub_dprintf("loongson", "args_addr is %p\n", state.gpr[5]); -+ -+ if(grub_efi_is_loongson ()) -+ { -+ grub_efi_uintn_t mmap_size; -+ grub_efi_uintn_t desc_size; -+ grub_efi_memory_descriptor_t *mmap_buf; -+ grub_err_t err; -+ struct bootparamsinterface * boot_params; -+ void * tmp_boot_params = NULL; -+ grub_efi_uint8_t new_interface_flag = 0; -+ mem_map * new_interface_mem = NULL; -+ char *p = NULL; -+ -+ struct memmap reserve_mem[GRUB_EFI_LOONGSON_MMAP_MAX]; -+ struct memmap free_mem[GRUB_EFI_LOONGSON_MMAP_MAX]; -+ struct memmap acpi_table_mem[GRUB_EFI_LOONGSON_MMAP_MAX]; -+ struct memmap acpi_nvs_mem[GRUB_EFI_LOONGSON_MMAP_MAX]; -+ -+ grub_memset(reserve_mem, 0, sizeof(struct memmap) * GRUB_EFI_LOONGSON_MMAP_MAX); -+ grub_memset(free_mem, 0, sizeof(struct memmap) * GRUB_EFI_LOONGSON_MMAP_MAX); -+ grub_memset(acpi_table_mem, 0, sizeof(struct memmap) * GRUB_EFI_LOONGSON_MMAP_MAX); -+ grub_memset(acpi_nvs_mem, 0, sizeof(struct memmap) * GRUB_EFI_LOONGSON_MMAP_MAX); -+ -+ tmp_boot_params = grub_efi_loongson_get_boot_params(); -+ if(tmp_boot_params == NULL) -+ { -+ grub_printf("not find param\n"); -+ return -1; -+ } -+ -+ boot_params = (struct bootparamsinterface *)tmp_boot_params; -+ p = (char *)&(boot_params->signature); -+ if(grub_strncmp(p, "BPI", 3) == 0) ++ grub_err_t err; ++ struct boot_params_interface * boot_params; ++ mem_map_v1 * mem_map_v1_table = NULL; ++ unsigned long bpi_version = 0; ++ grub_int8_t checksum = 0; ++ grub_uint32_t tmp_index = 0; ++ grub_uint32_t free_index = 0; ++ grub_uint32_t reserve_index = 0; ++ grub_uint32_t acpi_table_index = 0; ++ grub_uint32_t acpi_nvs_index = 0; ++ ++ struct memmap_v1 reserve_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; ++ struct memmap_v1 free_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; ++ struct memmap_v1 acpi_table_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; ++ struct memmap_v1 acpi_nvs_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; ++ ++ grub_memset(reserve_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); ++ grub_memset(free_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); ++ grub_memset(acpi_table_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); ++ grub_memset(acpi_nvs_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); ++ ++ boot_params = (struct boot_params_interface *)grub_efi_loongson_get_boot_params(); ++ ++ ext_list * listpointer = NULL; ++ /* Check extlist headers */ ++ listpointer = boot_params->extlist; ++ for( ;listpointer != NULL; listpointer = listpointer->next) + { -+ /* Check extlist headers */ -+ ext_list * listpointer = NULL; -+ listpointer = boot_params->extlist; -+ for( ;listpointer != NULL; listpointer = listpointer->next) ++ char *pl= (char *)&(listpointer->signature); ++ if(grub_strncmp(pl, "MEM", 3) == 0) + { -+ char *pl= (char *)&(listpointer->signature); -+ if(grub_strncmp(pl, "MEM", 3) == 0) -+ { -+ new_interface_mem = (mem_map *)listpointer; -+ } ++ mem_map_v1_table = (mem_map_v1 *)listpointer; ++ break; + } -+ -+ new_interface_flag = 1; -+ grub_dprintf("loongson", "get new parameter interface\n"); -+ }else{ -+ new_interface_flag = 0; -+ grub_dprintf("loongson", "get old parameter interface\n"); + } -+ state.gpr[6] = (grub_uint64_t)tmp_boot_params; -+ grub_dprintf("loongson", "boot_params is %p\n", state.gpr[6]); + -+ mmap_size = find_mmap_size (); -+ if (! mmap_size) -+ return grub_errno; -+ mmap_buf = grub_efi_allocate_any_pages (page_align (mmap_size) >> 12); -+ if (! mmap_buf) -+ return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); -+ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, -+ &desc_size, NULL); -+ if (err) -+ return err; ++ mmap_size = grub_efi_find_mmap_size (); ++ if (! mmap_size) ++ return grub_errno; ++ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); ++ if (! mmap_buf) ++ return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); ++ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, ++ &desc_size, &desc_version); ++ if (err) ++ return err; + -+ if(new_interface_flag) -+ { -+ if (!mmap_buf || !mmap_size || !desc_size) -+ return -1; -+ tmp_index = new_interface_mem -> mapcount; ++ if (!mmap_buf || !mmap_size || !desc_size) ++ return GRUB_ERR_BAD_ARGUMENT; + ++ char *p = (char *)&(boot_params->signature); ++ bpi_version = grub_efi_get_bpi_version(p); ++ grub_dprintf("loongson", "get bpi version:%ld\n", bpi_version); ++ ++ if (bpi_version <= GRUB_EFI_BPI_VER_V2) ++ { + /* -+ According to UEFI SPEC,mmap_buf is the accurate Memory Map array \ -+ now we can fill platform specific memory structure. -+ */ ++ According to UEFI SPEC,mmap_buf is the accurate Memory Map array \ ++ now we can fill platform specific memory structure. ++ */ + for(lsdesc = mmap_buf; lsdesc < (grub_efi_memory_descriptor_t *)((char *)mmap_buf + mmap_size); -+ lsdesc = (grub_efi_memory_descriptor_t *)((char *)lsdesc + desc_size)) ++ lsdesc = (grub_efi_memory_descriptor_t *)((char *)lsdesc + desc_size)) + { -+ /* Recovery */ -+ if((lsdesc->type != GRUB_EFI_ACPI_RECLAIM_MEMORY) && \ -+ (lsdesc->type != GRUB_EFI_ACPI_MEMORY_NVS) && \ -+ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_DATA) && \ -+ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_CODE) && \ -+ (lsdesc->type != GRUB_EFI_RESERVED_MEMORY_TYPE) && \ -+ (lsdesc->type != GRUB_EFI_PAL_CODE)) ++ grub_dprintf("loongson", "type:%d, phy_start:0x%lx, phy_end:0x%lx\n", lsdesc->type, ++ lsdesc->physical_start, lsdesc->physical_start + lsdesc->num_pages * GRUB_EFI_PAGE_SIZE); ++ ++ /* System RAM */ ++ if ((lsdesc->type != GRUB_EFI_ACPI_RECLAIM_MEMORY) && \ ++ (lsdesc->type != GRUB_EFI_ACPI_MEMORY_NVS) && \ ++ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_DATA) && \ ++ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_CODE) && \ ++ (lsdesc->type != GRUB_EFI_RESERVED_MEMORY_TYPE) && \ ++ (lsdesc->type != GRUB_EFI_PAL_CODE)) + { -+ free_mem[free_index].memtype = GRUB_EFI_LOONGSON_SYSTEM_RAM; -+ free_mem[free_index].memstart = (lsdesc->physical_start) & 0xffffffffffff; -+ free_mem[free_index].memsize = lsdesc->num_pages * 4096; ++ free_mem_v1[free_index].memtype = GRUB_EFI_LOONGSON_SYSTEM_RAM; ++ free_mem_v1[free_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; ++ free_mem_v1[free_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; + free_index++; + + /*ACPI*/ -+ }else if((lsdesc->type == GRUB_EFI_ACPI_RECLAIM_MEMORY)){ -+ acpi_table_mem[acpi_table_index].memtype = GRUB_EFI_LOONGSON_ACPI_TABLE; -+ acpi_table_mem[acpi_table_index].memstart = (lsdesc->physical_start) & 0xffffffffffff; -+ acpi_table_mem[acpi_table_index].memsize = lsdesc->num_pages * 4096; ++ } else if ((lsdesc->type == GRUB_EFI_ACPI_RECLAIM_MEMORY)){ ++ acpi_table_mem_v1[acpi_table_index].memtype = GRUB_EFI_LOONGSON_ACPI_TABLE; ++ acpi_table_mem_v1[acpi_table_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; ++ acpi_table_mem_v1[acpi_table_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; + acpi_table_index++; -+ }else if((lsdesc->type == GRUB_EFI_ACPI_MEMORY_NVS)){ -+ acpi_nvs_mem[acpi_nvs_index].memtype = GRUB_EFI_LOONGSON_ACPI_NVS; -+ acpi_nvs_mem[acpi_nvs_index].memstart = (lsdesc->physical_start) & 0xffffffffffff; -+ acpi_nvs_mem[acpi_nvs_index].memsize = lsdesc->num_pages * 4096; ++ } else if ((lsdesc->type == GRUB_EFI_ACPI_MEMORY_NVS)){ ++ acpi_nvs_mem_v1[acpi_nvs_index].memtype = GRUB_EFI_LOONGSON_ACPI_NVS; ++ acpi_nvs_mem_v1[acpi_nvs_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; ++ acpi_nvs_mem_v1[acpi_nvs_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; + acpi_nvs_index++; + + /* Reserve */ -+ }else{ -+ reserve_mem[reserve_index].memtype = GRUB_EFI_LOONGSON_MEMORY_RESERVED; -+ reserve_mem[reserve_index].memstart = (lsdesc->physical_start) & 0xffffffffffff; -+ reserve_mem[reserve_index].memsize = lsdesc->num_pages * 4096; ++ } else { ++ reserve_mem_v1[reserve_index].memtype = GRUB_EFI_LOONGSON_MEMORY_RESERVED; ++ reserve_mem_v1[reserve_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; ++ reserve_mem_v1[reserve_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; + reserve_index++; + } + } + -+ /* Recovery sort */ -+ for(j = 0; j < free_index;) -+ { -+ tempMemsize = free_mem[j].memsize; -+ for(t = j + 1; t < free_index; t++) -+ { -+ if((free_mem[j].memstart + tempMemsize == free_mem[t].memstart) && (free_mem[j].memtype == free_mem[t].memtype)) -+ { -+ tempMemsize += free_mem[t].memsize; -+ }else{ -+ break; -+ } -+ } -+ -+ new_interface_mem->map[tmp_index].memtype = GRUB_EFI_LOONGSON_SYSTEM_RAM; -+ new_interface_mem->map[tmp_index].memstart = free_mem[j].memstart; -+ new_interface_mem->map[tmp_index].memsize = tempMemsize; -+ grub_dprintf("loongson", "map[%d]:type %x, start 0x%llx, end 0x%llx\n", -+ tmp_index, -+ new_interface_mem->map[tmp_index].memtype, -+ new_interface_mem->map[tmp_index].memstart, -+ new_interface_mem->map[tmp_index].memstart+ new_interface_mem->map[tmp_index].memsize -+ ); -+ j = t; -+ tmp_index++; -+ } ++ tmp_index = mem_map_v1_table->mapcount; ++ /*System RAM Sort*/ ++ tmp_index = grub_efi_loongson_memmap_v1_sort(free_mem_v1, free_index, mem_map_v1_table, ++ tmp_index, GRUB_EFI_LOONGSON_SYSTEM_RAM); + /*ACPI Sort*/ -+ tmp_index = grub_efi_loongson_memmap_sort(acpi_table_mem, acpi_table_index, new_interface_mem, tmp_index, GRUB_EFI_LOONGSON_ACPI_TABLE); -+ tmp_index = grub_efi_loongson_memmap_sort(acpi_nvs_mem, acpi_nvs_index, new_interface_mem, tmp_index, GRUB_EFI_LOONGSON_ACPI_NVS); ++ tmp_index = grub_efi_loongson_memmap_v1_sort(acpi_table_mem_v1, acpi_table_index, ++ mem_map_v1_table, tmp_index, GRUB_EFI_LOONGSON_ACPI_TABLE); ++ tmp_index = grub_efi_loongson_memmap_v1_sort(acpi_nvs_mem_v1, acpi_nvs_index, ++ mem_map_v1_table, tmp_index, GRUB_EFI_LOONGSON_ACPI_NVS); + /*Reserve Sort*/ -+ grub_uint64_t loongarch_addr; -+ asm volatile ("csrrd %0, 0x181" : "=r" (loongarch_addr)); -+ if((loongarch_addr & 0xff00000000000000) == 0x9000000000000000){ -+ tmp_index = grub_efi_loongson_memmap_sort(reserve_mem, reserve_index, new_interface_mem, tmp_index, GRUB_EFI_LOONGSON_MEMORY_RESERVED); -+ }else{ -+ tmp_index = grub_efi_loongson_memmap_sort(reserve_mem, reserve_index, new_interface_mem, tmp_index, GRUB_EFI_LOONGSON_MEMORY_RESERVED + 1); -+ } -+ -+ new_interface_mem->mapcount = tmp_index; -+ new_interface_mem->header.checksum = 0; ++ { ++ grub_uint64_t loongarch_addr; ++ asm volatile ("csrrd %0, 0x181" : "=r" (loongarch_addr)); ++ if ((loongarch_addr & 0xff00000000000000) == 0x9000000000000000) ++ tmp_index = grub_efi_loongson_memmap_v1_sort(reserve_mem_v1, reserve_index, ++ mem_map_v1_table, tmp_index, ++ GRUB_EFI_LOONGSON_MEMORY_RESERVED); ++ else ++ tmp_index = grub_efi_loongson_memmap_v1_sort(reserve_mem_v1, reserve_index, ++ mem_map_v1_table, tmp_index, ++ GRUB_EFI_LOONGSON_MEMORY_RESERVED + 1); ++ } ++ mem_map_v1_table->mapcount = tmp_index; ++ mem_map_v1_table->header.checksum = 0; + -+ checksum = grub_efi_loongson_grub_calculatechecksum8(new_interface_mem, new_interface_mem->header.length); -+ new_interface_mem->header.checksum = checksum; ++ checksum = grub_efi_loongson_grub_calculatechecksum8((grub_uint8_t *)mem_map_v1_table, ++ mem_map_v1_table->header.length); ++ mem_map_v1_table->header.checksum = checksum; + } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_linux_boot (void) ++{ ++ struct grub_relocator64_state state; ++ ++ grub_memset (&state, 0, sizeof (state)); ++ ++ /* Boot the kernel. */ ++ state.gpr[1] = entry_addr; ++ grub_dprintf("loongson", "entry_addr is 0x%lx\n", state.gpr[1]); ++ ++ if (is_fdt_boot == 1) ++ { ++ if (allocate_fdt_and_exit_boot () != GRUB_ERR_NONE) ++ return grub_errno; ++ ++ state.gpr[4] = 1 << FLAGS_EFI_SUPPORT_BIT; ++ state.gpr[5] = (grub_uint64_t)fdt; ++ state.gpr[6] = 0; ++ } else { ++ state.gpr[4] = linux_argc; ++ state.gpr[5] = (grub_addr_t) linux_args_addr; ++ state.gpr[6] = (grub_uint64_t)grub_efi_loongson_get_boot_params(); ++ ++ if (allocate_boot_params_and_exit_boot () != GRUB_ERR_NONE) ++ return grub_errno; + } ++ grub_dprintf("loongson", "gpr[4]:%ld, gpr[5]:0x%lx, gpr[6]:0x%lx\n", ++ state.gpr[4], state.gpr[5], state.gpr[6]); + + state.jumpreg = 1; + grub_relocator64_boot (relocator, state); @@ -2108,67 +1680,42 @@ index 0000000..c769bb2 +{ + grub_relocator_unload (relocator); + grub_dl_unref (my_mod); -+ + loaded = 0; + + return GRUB_ERR_NONE; +} + +static grub_err_t -+grub_linux_load32 (grub_elf_t elf, const char *filename) -+{ -+ Elf32_Addr base; -+ grub_err_t err; -+ grub_uint8_t *playground; -+ -+ /* Linux's entry point incorrectly contains a virtual address. */ -+ entry_addr = elf->ehdr.ehdr32.e_entry; -+ -+ linux_size = grub_elf32_size (elf, &base, 0); -+ if (linux_size == 0) -+ return grub_errno; -+ target_addr = base; -+ linux_size = ALIGN_UP (base + linux_size - base, 8); -+ -+ relocator = grub_relocator_new (); -+ if (!relocator) -+ return grub_errno; -+ -+ { -+ grub_relocator_chunk_t ch; -+ err = grub_relocator_alloc_chunk_addr (relocator, &ch, -+ grub_vtop ((void *) target_addr), -+ linux_size); -+ if (err) -+ return err; -+ playground = get_virtual_current_address (ch); -+ } -+ -+ /* Now load the segments into the area we claimed. */ -+ return grub_elf32_load (elf, filename, playground - base, GRUB_ELF_LOAD_FLAGS_NONE, 0, 0); -+} -+ -+static grub_err_t +grub_linux_load64 (grub_elf_t elf, const char *filename) +{ + Elf64_Addr base; + grub_err_t err; + grub_uint8_t *playground; ++ grub_uint64_t addr; ++ int flag; + + /* Linux's entry point incorrectly contains a virtual address. */ + entry_addr = elf->ehdr.ehdr64.e_entry; -+ grub_dprintf("loongson", "entry address = %p\n", entry_addr); ++ grub_dprintf("loongson", "entry address = 0x%lx\n", entry_addr); + + linux_size = grub_elf64_size (elf, &base, 0); -+ grub_dprintf("loongson", "base = %p\n", base); ++ grub_dprintf("loongson", "base = 0x%lx\n", base); + + if (linux_size == 0) + return grub_errno; + target_addr = base; + linux_size = ALIGN_UP (base + linux_size - base, 8); + ++ asm volatile ("csrrd %0, 0x181" : "=r" (addr)); ++ if (addr & 0x1) { ++ flag = GRUB_ELF_LOAD_FLAGS_NONE; ++ } else { ++ flag = GRUB_ELF_LOAD_FLAGS_30BITS; ++ base &= ~ELF64_LOADMASK; ++ entry_addr &= ~ELF64_LOADMASK; ++ } ++ + relocator = grub_relocator_new (); -+ // linux_size=0x322fa80; + if (!relocator) + return grub_errno; + @@ -2183,7 +1730,7 @@ index 0000000..c769bb2 + } + + /* Now load the segments into the area we claimed. */ -+ return grub_elf64_load (elf, filename, playground - base, GRUB_ELF_LOAD_FLAGS_NONE, 0, 0); ++ return grub_elf64_load (elf, filename, playground - base, flag, 0, 0); +} + +static grub_err_t @@ -2191,20 +1738,21 @@ index 0000000..c769bb2 + int argc, char *argv[]) +{ + grub_elf_t elf = 0; -+ int size; -+ int i; -+ grub_uint64_t *linux_argv; -+ char *linux_args; + grub_err_t err; ++ int args_size = 0; ++ ++ grub_dl_ref (my_mod); + + if (argc == 0) ++ { + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ } + -+ elf = grub_elf_open (argv[0],GRUB_FILE_TYPE_LINUX_KERNEL); ++ elf = grub_elf_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL); + if (! elf) + return grub_errno; + -+ if (elf->ehdr.ehdr32.e_type != ET_EXEC) ++ if (elf->ehdr.ehdr64.e_type != ET_EXEC) + { + grub_elf_close (elf); + return grub_error (GRUB_ERR_UNKNOWN_OS, @@ -2215,30 +1763,6 @@ index 0000000..c769bb2 + grub_loader_unset (); + loaded = 0; + -+ /* For arguments. */ -+ linux_argc = argc; -+ /* Main arguments. */ -+ size = (linux_argc) * sizeof (grub_uint64_t); -+ /* Initrd address and size. */ -+ size += 3 * sizeof (grub_uint64_t); -+ /* NULL terminator. */ -+ size += sizeof (grub_uint64_t); -+ /* First argument is always "a0". */ -+ size += ALIGN_UP (sizeof ("a0"), 4); -+ /* Normal arguments. */ -+ for (i = 1; i < argc; i++) -+ size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); -+ -+ /* rd arguments. */ -+ size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); -+ size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); -+ size += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); -+ -+ size = ALIGN_UP (size, 8); -+ -+ if (grub_elf_is_elf32 (elf)) -+ err = grub_linux_load32 (elf, argv[0]); -+ else + if (grub_elf_is_elf64 (elf)) + err = grub_linux_load64 (elf, argv[0]); + else @@ -2249,26 +1773,71 @@ index 0000000..c769bb2 + if (err) + return err; + -+ { -+ grub_relocator_chunk_t ch; -+ err = grub_relocator_alloc_chunk_align (relocator, &ch, -+ 0, (0xffffffff - size) + 1, -+ size, 8, -+ GRUB_RELOCATOR_PREFERENCE_HIGH, 0); -+ if (err) -+ return err; -+ linux_args_addr = get_virtual_current_address (ch); -+ } ++ if (grub_efi_loongson_get_boot_params() == NULL) { ++ grub_size_t cmdline_size; + -+ linux_argv = (grub_uint64_t *) linux_args_addr; -+ linux_args = (char *) (linux_argv + (linux_argc + 1 + 3)); ++ is_fdt_boot = 1; ++ cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); ++ fdt_linux_args = grub_malloc (cmdline_size); ++ if (!fdt_linux_args) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto fail; ++ } ++ grub_memcpy (fdt_linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); ++ err = grub_create_loader_cmdline (argc, argv, ++ fdt_linux_args + sizeof (LINUX_IMAGE) - 1, ++ cmdline_size, ++ GRUB_VERIFY_KERNEL_CMDLINE); ++ if (err) ++ goto fail; ++ grub_dprintf("loongson", "fdt linux args:%s\n", ++ fdt_linux_args + sizeof (LINUX_IMAGE) - 1); ++ ++ } else { ++ int i; ++ grub_uint64_t *linux_argv; ++ char *linux_args; ++ ++ is_fdt_boot = 0; ++ /* For arguments. */ ++ linux_argc = argc; ++ /* Main arguments. */ ++ args_size = (linux_argc) * sizeof (grub_uint64_t); ++ /* Initrd address/size and initrd */ ++ args_size += 3 * sizeof (grub_uint64_t); ++ /* NULL terminator. */ ++ args_size += sizeof (grub_uint64_t); ++ /* First argument is always "a0". */ ++ args_size += ALIGN_UP (sizeof ("a0"), 4); ++ /* Normal arguments. */ ++ for (i = 1; i < argc; i++) ++ args_size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); ++ ++ /* rd arguments. */ ++ args_size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); ++ args_size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); ++ args_size += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); ++ ++ args_size = ALIGN_UP (args_size, 8); ++ ++ linux_args_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (args_size)); ++ grub_dprintf ("linux", "linux args numpages: %lld\n", ++ (long long) GRUB_EFI_BYTES_TO_PAGES (args_size)); ++ if (!linux_args_addr) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto fail; ++ } ++ linux_argv = (grub_uint64_t *) linux_args_addr; ++ linux_args = (char *) (linux_argv + (linux_argc + 1 + 3)); + -+ grub_memcpy (linux_args, "a0", sizeof ("a0")); -+ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; -+ linux_argv++; -+ linux_args += ALIGN_UP (sizeof ("a0"), 4); ++ grub_memcpy (linux_args, "a0", sizeof ("a0")); ++ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; ++ linux_argv++; ++ linux_args += ALIGN_UP (sizeof ("a0"), 4); + -+ for (i = 1; i < argc; i++) ++ for (i = 1; i < argc; i++) + { + grub_memcpy (linux_args, argv[i], grub_strlen (argv[i]) + 1); + *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; @@ -2276,40 +1845,80 @@ index 0000000..c769bb2 + linux_args += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); + } + -+ /* Reserve space for rd arguments. */ -+ rd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; -+ linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); -+ *linux_argv = 0; -+ linux_argv++; ++ /* Reserve space for rd arguments. */ ++ rd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; ++ linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); ++ *linux_argv = 0; ++ linux_argv++; ++ ++ rd_size_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; ++ linux_args += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); ++ *linux_argv = 0; ++ linux_argv++; + -+ rd_size_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; -+ linux_args += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); -+ *linux_argv = 0; -+ linux_argv++; ++ /* Reserve space for initrd arguments. */ ++ initrd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; ++ linux_args += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); ++ *linux_argv = 0; ++ linux_argv++; + -+ /* Reserve space for initrd arguments. */ -+ initrd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; -+ linux_args += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); -+ *linux_argv = 0; -+ linux_argv++; ++ *linux_argv = 0; ++ } + -+ *linux_argv = 0; ++ if (grub_errno == GRUB_ERR_NONE) ++ { ++ grub_loader_set (grub_linux_boot, grub_linux_unload, 0); ++ loaded = 1; ++ } + -+ grub_loader_set (grub_linux_boot, grub_linux_unload, 0); + initrd_loaded = 0; -+ loaded = 1; -+ grub_dl_ref (my_mod); + -+ return GRUB_ERR_NONE; ++fail: ++ if (grub_errno != GRUB_ERR_NONE) ++ { ++ grub_dl_unref (my_mod); ++ loaded = 0; ++ } ++ ++ if (fdt_linux_args && !loaded) ++ grub_free (fdt_linux_args); ++ ++ if (linux_args_addr && !loaded) ++ grub_efi_free_pages ((grub_addr_t) linux_args_addr, ++ GRUB_EFI_BYTES_TO_PAGES (args_size)); ++ ++ return grub_errno; ++} ++ ++#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024) ++ ++/* ++ * This function returns a pointer to a legally allocated initrd buffer, ++ * or NULL if unsuccessful ++ */ ++static void * ++allocate_initrd_mem (int initrd_pages) ++{ ++ grub_addr_t max_addr; ++ ++ if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE) ++ return NULL; ++ ++ max_addr += INITRD_MAX_ADDRESS_OFFSET - 1; ++ ++ return grub_efi_allocate_pages_real (max_addr, initrd_pages, ++ GRUB_EFI_ALLOCATE_MAX_ADDRESS, ++ GRUB_EFI_LOADER_DATA); +} + ++ +static grub_err_t +grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ -+ grub_size_t size = 0; -+ void *initrd_dest; ++ grub_size_t initrd_size, initrd_pages; + grub_err_t err; ++ void *initrd_mem = NULL; + struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 }; + + if (argc == 0) @@ -2324,49 +1933,71 @@ index 0000000..c769bb2 + if (grub_initrd_init (argc, argv, &initrd_ctx)) + goto fail; + -+ size = grub_get_initrd_size (&initrd_ctx); ++ initrd_size = grub_get_initrd_size (&initrd_ctx); + ++ if (is_fdt_boot == 1) //fdt + { ++ initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size)); ++ initrd_mem = allocate_initrd_mem (initrd_pages); ++ if (!initrd_mem) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto fail; ++ } ++ } else { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (relocator, &ch, -+ 0, (0xffffffff - size) + 1, -+ size, 0x10000, -+ GRUB_RELOCATOR_PREFERENCE_HIGH, 0); ++ 0, (0xffffffff - initrd_size) + 1, ++ initrd_size, 0x10000, ++ GRUB_RELOCATOR_PREFERENCE_HIGH, 0); + + if (err) -+ goto fail; -+ initrd_dest = get_virtual_current_address (ch); ++ return err; ++ initrd_mem = get_virtual_current_address (ch); + } + -+ if (grub_initrd_load (&initrd_ctx, argv, initrd_dest)) ++ if (grub_initrd_load (&initrd_ctx, argv, initrd_mem)) + goto fail; + -+ grub_snprintf ((char *) linux_args_addr + rd_addr_arg_off, -+ sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), "rd_start=0x%lx", -+ (grub_uint64_t) initrd_dest); -+ ((grub_uint64_t *) linux_args_addr)[linux_argc] -+ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_addr_arg_off); -+ linux_argc++; -+ -+ grub_snprintf ((char *) linux_args_addr + rd_size_arg_off, -+ sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%lx", -+ (grub_uint64_t) size); -+ ((grub_uint64_t *) linux_args_addr)[linux_argc] -+ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_size_arg_off); -+ linux_argc++; -+ ++ initrd_start = (grub_addr_t) initrd_mem; ++ initrd_end = initrd_start + initrd_size; ++ grub_dprintf ("linux", "[addr=%p, size=0x%lx]\n", ++ (void *) initrd_start, initrd_size); + -+ grub_snprintf ((char *) linux_args_addr + initrd_addr_arg_off, -+ sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), "initrd=0x%lx,0x%lx", -+ ((grub_uint64_t) initrd_dest & 0xffffffff), (grub_uint64_t) size); -+ ((grub_uint64_t *) linux_args_addr)[linux_argc] -+ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + initrd_addr_arg_off); -+ linux_argc++; ++ if (is_fdt_boot == 0) //bpi ++ { ++ grub_snprintf ((char *) linux_args_addr + rd_addr_arg_off, ++ sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), ++ "rd_start=0x%lx", ++ (grub_uint64_t) initrd_mem); ++ ((grub_uint64_t *) linux_args_addr)[linux_argc] ++ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_addr_arg_off); ++ linux_argc++; ++ ++ grub_snprintf ((char *) linux_args_addr + rd_size_arg_off, ++ sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%lx", ++ (grub_uint64_t) initrd_size); ++ ((grub_uint64_t *) linux_args_addr)[linux_argc] ++ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_size_arg_off); ++ linux_argc++; ++ ++ grub_snprintf ((char *) linux_args_addr + initrd_addr_arg_off, ++ sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), ++ "initrd=0x%lx,0x%lx", ++ ((grub_uint64_t) initrd_mem & GRUB_EFI_MAX_PHY_ADDRESS), ++ (grub_uint64_t) initrd_size); ++ ((grub_uint64_t *) linux_args_addr)[linux_argc] ++ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + initrd_addr_arg_off); ++ linux_argc++; ++ } + + initrd_loaded = 1; + + fail: + grub_initrd_close (&initrd_ctx); ++ if (is_fdt_boot == 1) ++ if (initrd_mem && !initrd_start) ++ grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages); + + return grub_errno; +} @@ -2388,10 +2019,10 @@ index 0000000..c769bb2 + grub_unregister_command (cmd_initrd); +} diff --git a/include/grub/dl.h b/include/grub/dl.h -index 6a3e251..c1b6dd9 100644 +index 6f46b7e..50e04ac 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h -@@ -314,7 +314,7 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, +@@ -360,7 +360,7 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, #define GRUB_ARCH_DL_GOT_ALIGN 4 #endif @@ -2401,11 +2032,11 @@ index 6a3e251..c1b6dd9 100644 #define GRUB_ARCH_DL_GOT_ALIGN 8 #endif diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h -index 37e7b16..049326c 100644 +index 510a403..a57187f 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h -@@ -2087,7 +2087,8 @@ struct grub_efi_rng_protocol - typedef struct grub_efi_rng_protocol grub_efi_rng_protocol_t; +@@ -2117,7 +2117,8 @@ struct grub_efi_memory_attribute_protocol + typedef struct grub_efi_memory_attribute_protocol grub_efi_memory_attribute_protocol_t; #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ - || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) @@ -2414,11 +2045,24 @@ index 37e7b16..049326c 100644 #define efi_call_0(func) func() #define efi_call_1(func, a) func(a) +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index 8ca8c38..fe1df9d 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -138,7 +138,7 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, + extern grub_addr_t EXPORT_VAR(grub_stack_addr); + extern grub_size_t EXPORT_VAR(grub_stack_size); + +-#if defined(__arm__) || defined(__aarch64__) ++#if defined(__arm__) || defined(__aarch64__) || defined (__loongarch__) + void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void); + grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *); + #include diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h -index c03cc59..be88c54 100644 +index 45c9f8b..f612a55 100644 --- a/include/grub/efi/pe32.h +++ b/include/grub/efi/pe32.h -@@ -66,6 +66,7 @@ struct grub_pe32_coff_header +@@ -89,6 +89,7 @@ struct grub_pe32_coff_header }; #define GRUB_PE32_MACHINE_I386 0x14c @@ -2426,7 +2070,7 @@ index c03cc59..be88c54 100644 #define GRUB_PE32_MACHINE_IA64 0x200 #define GRUB_PE32_MACHINE_X86_64 0x8664 #define GRUB_PE32_MACHINE_ARMTHUMB_MIXED 0x01c2 -@@ -329,6 +330,7 @@ struct grub_pe32_fixup_block +@@ -355,6 +356,7 @@ struct grub_pe32_fixup_block #define GRUB_PE32_REL_BASED_IA64_IMM64 9 #define GRUB_PE32_REL_BASED_DIR64 10 #define GRUB_PE32_REL_BASED_HIGH3ADJ 11 @@ -2507,6 +2151,26 @@ index c8492f9..2c0b163 100644 /* MIPS relocs. */ #define R_MIPS_NONE 0 /* No reloc */ +diff --git a/include/grub/fdt.h b/include/grub/fdt.h +index 6ee57e1..a0710ab 100644 +--- a/include/grub/fdt.h ++++ b/include/grub/fdt.h +@@ -19,11 +19,14 @@ + #ifndef GRUB_FDT_HEADER + #define GRUB_FDT_HEADER 1 + +-#if defined(__arm__) || defined(__aarch64__) ++#if defined(__arm__) || defined(__aarch64__) || defined (__loongarch__) + + #include + #include + ++/* Space required when preparing the /chosen node after boot has been called. */ ++#define GRUB_EFI_LINUX_FDT_EXTRA_SPACE 0x400 ++ + #define FDT_MAGIC 0xD00DFEED + + typedef struct { diff --git a/include/grub/loongarch64/asm.h b/include/grub/loongarch64/asm.h new file mode 100644 index 0000000..c3e77e9 @@ -2523,46 +2187,12 @@ index 0000000..c3e77e9 +#define GRUB_ASM_REG_L ld.d + +#endif -diff --git a/include/grub/loongarch64/efi/boot.h b/include/grub/loongarch64/efi/boot.h -new file mode 100644 -index 0000000..e69de29 -diff --git a/include/grub/loongarch64/efi/loader.h b/include/grub/loongarch64/efi/loader.h -new file mode 100644 -index 0000000..71a0159 ---- /dev/null -+++ b/include/grub/loongarch64/efi/loader.h -@@ -0,0 +1,25 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2002,2003,2004,2006,2007,2017 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_LOADER_MACHINE_HEADER -+#define GRUB_LOADER_MACHINE_HEADER 1 -+ -+#include -+#include -+ -+#endif /* ! GRUB_LOADER_MACHINE_HEADER */ diff --git a/include/grub/loongarch64/efi/loongson.h b/include/grub/loongarch64/efi/loongson.h new file mode 100644 -index 0000000..fa32ef5 +index 0000000..7a9ccb4 --- /dev/null +++ b/include/grub/loongarch64/efi/loongson.h -@@ -0,0 +1,290 @@ +@@ -0,0 +1,113 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2017 Free Software Foundation, Inc. @@ -2588,12 +2218,17 @@ index 0000000..fa32ef5 + +#include + -+#define GRUB_EFI_LOONGSON_SMBIOS_TABLE_GUID \ ++#define GRUB_EFI_LOONGSON_BPI_TABLE_GUID \ + { 0x4660f721, 0x2ec5, 0x416a, \ + { 0x89, 0x9a, 0x43, 0x18, 0x02, 0x50, 0xa0, 0xc9 } \ + } + ++#define GRUB_EFI_MAX_PHY_ADDRESS 0xffffffffffffULL ++#define ELF32_LOADMASK (0xf0000000UL) ++#define ELF64_LOADMASK (0xf000000000000000ULL) ++#define FLAGS_EFI_SUPPORT_BIT 0 +#define GRUB_EFI_LOONGSON_MMAP_MAX 128 ++ +typedef enum + { + GRUB_EFI_LOONGSON_SYSTEM_RAM = 1, @@ -2604,272 +2239,88 @@ index 0000000..fa32ef5 + } +grub_efi_loongson_memory_type; + -+typedef struct -+{ -+ grub_uint16_t vers; /* version */ -+ grub_uint32_t nr_map; /* number of memory_maps */ -+ grub_uint32_t mem_freq; /* memory frequence */ -+ struct mem_map { -+ grub_uint32_t node_id; /* node_id which memory attached to */ -+ grub_uint32_t mem_type; /* system memory, pci memory, pci io, etc. */ -+ grub_uint64_t mem_start; /* memory map start address */ -+ grub_uint32_t mem_size; /* each memory_map size, not the total size */ -+ } map[GRUB_EFI_LOONGSON_MMAP_MAX]; -+} GRUB_PACKED -+grub_efi_loongson_memory_map; -+ -+/* -+ * Capability and feature descriptor structure for LOONGARCH CPU -+ */ -+typedef struct -+{ -+ grub_uint16_t vers; /* version */ -+ grub_uint32_t processor_id; /* PRID, e.g. 6305, 6306 */ -+ grub_uint32_t cputype; /* Loongson_3A/3B, etc. */ -+ grub_uint32_t total_node; /* num of total numa nodes */ -+ grub_uint16_t cpu_startup_core_id; /* Boot core id */ -+ grub_uint16_t reserved_cores_mask; -+ grub_uint32_t cpu_clock_freq; /* cpu_clock */ -+ grub_uint32_t nr_cpus; -+} GRUB_PACKED -+grub_efi_loongson_cpu_info; -+ -+#define GRUB_EFI_LOONGSON_MAX_UARTS 64 -+ -+typedef struct -+{ -+ grub_uint32_t iotype; /* see include/linux/serial_core.h */ -+ grub_uint32_t uartclk; -+ grub_uint32_t int_offset; -+ grub_uint64_t uart_base; -+} GRUB_PACKED -+grub_efi_loongson_uart_device; -+ -+#define GRUB_EFI_LOONGSON_MAX_SENSORS 64 -+ -+typedef struct -+{ -+ char name[32]; /* a formal name */ -+ char label[64]; /* a flexible description */ -+ grub_uint32_t type; /* SENSOR_* */ -+ grub_uint32_t id; /* instance id of a sensor-class */ -+ grub_uint32_t fan_policy; -+ grub_uint32_t fan_percent; /* only for constant speed policy */ -+ grub_uint64_t base_addr; /* base address of device registers */ -+} GRUB_PACKED -+grub_efi_loongson_sensor_device; -+ -+typedef struct -+{ -+ grub_uint16_t vers; /* version */ -+ grub_uint32_t ccnuma_smp; /* 0: no numa; 1: has numa */ -+ grub_uint32_t sing_double_channel; /* 1:single; 2:double */ -+ grub_uint32_t nr_uarts; -+ grub_efi_loongson_uart_device uarts[GRUB_EFI_LOONGSON_MAX_UARTS]; -+ grub_uint32_t nr_sensors; -+ grub_efi_loongson_sensor_device sensors[GRUB_EFI_LOONGSON_MAX_SENSORS]; -+ char has_ec; -+ char ec_name[32]; -+ grub_uint64_t ec_base_addr; -+ char has_tcm; -+ char tcm_name[32]; -+ grub_uint64_t tcm_base_addr; -+ grub_uint64_t workarounds; /* see workarounds.h */ -+} GRUB_PACKED -+grub_efi_loongson_system_info; -+ -+typedef struct -+{ -+ grub_uint16_t vers; -+ grub_uint16_t size; -+ grub_uint16_t rtr_bus; -+ grub_uint16_t rtr_devfn; -+ grub_uint32_t vendor; -+ grub_uint32_t device; -+ grub_uint32_t PIC_type; /* conform use HT or PCI to route to CPU-PIC */ -+ grub_uint64_t ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */ -+ grub_uint64_t ht_enable; /* irqs used in this PIC */ -+ grub_uint32_t node_id; /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */ -+ grub_uint64_t pci_mem_start_addr; -+ grub_uint64_t pci_mem_end_addr; -+ grub_uint64_t pci_io_start_addr; -+ grub_uint64_t pci_io_end_addr; -+ grub_uint64_t pci_config_addr; -+ grub_uint32_t dma_mask_bits; -+} GRUB_PACKED -+grub_efi_loongson_irq_src_routing_table; -+ -+typedef struct -+{ -+ grub_uint16_t vers; /* version */ -+ grub_uint16_t size; -+ grub_uint8_t flag; -+ char description[64]; -+} GRUB_PACKED -+grub_efi_loongson_interface_info; -+ -+#define GRUB_EFI_LOONGSON_MAX_RESOURCE_NUMBER 128 -+ -+typedef struct -+{ -+ grub_uint64_t start; /* resource start address */ -+ grub_uint64_t end; /* resource end address */ -+ char name[64]; -+ grub_uint32_t flags; -+} -+grub_efi_loongson_resource; -+ -+/* arch specific additions */ -+typedef struct -+{ -+} -+grub_efi_loongson_archdev_data; -+ -+typedef struct -+{ -+ char name[64]; /* hold the device name */ -+ grub_uint32_t num_resources; /* number of device_resource */ -+ /* for each device's resource */ -+ grub_efi_loongson_resource resource[GRUB_EFI_LOONGSON_MAX_RESOURCE_NUMBER]; -+ /* arch specific additions */ -+ grub_efi_loongson_archdev_data archdata; -+} -+grub_efi_loongson_board_devices; -+ -+typedef struct -+{ -+ grub_uint16_t vers; /* version */ -+ char special_name[64]; /* special_atribute_name */ -+ grub_uint32_t loongson_special_type; /* type of special device */ -+ /* for each device's resource */ -+ grub_efi_loongson_resource resource[GRUB_EFI_LOONGSON_MAX_RESOURCE_NUMBER]; -+} -+grub_efi_loongson_special_attribute; -+ -+typedef struct -+{ -+ grub_uint64_t memory_offset; /* efi_loongson_memory_map struct offset */ -+ grub_uint64_t cpu_offset; /* efi_loongson_cpuinfo struct offset */ -+ grub_uint64_t system_offset; /* efi_loongson_system_info struct offset */ -+ grub_uint64_t irq_offset; /* efi_loongson_irq_src_routing_table struct offset */ -+ grub_uint64_t interface_offset; /* interface_info struct offset */ -+ grub_uint64_t special_offset; /* efi_loongson_special_attribute struct offset */ -+ grub_uint64_t boarddev_table_offset; /* efi_loongson_board_devices offset */ -+} -+grub_efi_loongson_params; -+ -+typedef struct -+{ -+ grub_uint16_t vers; /* version */ -+ grub_uint64_t vga_bios; /* vga_bios address */ -+ grub_efi_loongson_params lp; -+} -+grub_efi_loongson_smbios_table; -+ -+typedef struct -+{ -+ grub_uint64_t reset_cold; -+ grub_uint64_t reset_warm; -+ grub_uint64_t reset_type; -+ grub_uint64_t shutdown; -+ grub_uint64_t do_suspend; /* NULL if not support */ -+} -+grub_efi_loongson_reset_system; -+ -+typedef struct -+{ -+ grub_uint64_t mps; /* MPS table */ -+ grub_uint64_t acpi; /* ACPI table (IA64 ext 0.71) */ -+ grub_uint64_t acpi20; /* ACPI table (ACPI 2.0) */ -+ grub_efi_loongson_smbios_table smbios; /* SM BIOS table */ -+ grub_uint64_t sal_systab; /* SAL system table */ -+ grub_uint64_t boot_info; /* boot info table */ -+} -+grub_efi_loongson; -+ -+typedef struct -+{ -+ grub_efi_loongson efi; -+ grub_efi_loongson_reset_system reset_system; -+} -+grub_efi_loongson_boot_params; -+ -+extern grub_uint64_t grub_efi_loongson_reset_system_addr; -+ -+extern void grub_efi_loongson_reset_cold (void); -+extern void grub_efi_loongson_reset_warm (void); -+extern void grub_efi_loongson_reset_shutdown (void); -+extern void grub_efi_loongson_reset_suspend (void); -+ -+void grub_efi_loongson_alloc_boot_params (void); -+void grub_efi_loongson_free_boot_params (void); -+void * grub_efi_loongson_get_smbios_table (void); -+ -+int EXPORT_FUNC(grub_efi_is_loongson) (void); ++typedef enum ++ { ++ GRUB_EFI_BPI_VER_NONE = 0, ++ GRUB_EFI_BPI_VER_V1 = 1000, ++ GRUB_EFI_BPI_VER_V2 = 1001, ++ } ++ grub_efi_loongson_bpi_version; + +grub_uint8_t -+EXPORT_FUNC(grub_efi_loongson_calculatesum8) (const grub_uint8_t *Buffer, grub_efi_uintn_t Length); ++EXPORT_FUNC(grub_efi_loongson_calculatesum8) (const grub_uint8_t *Buffer, ++ grub_efi_uintn_t Length); + +grub_uint8_t -+EXPORT_FUNC(grub_efi_loongson_grub_calculatechecksum8) (const grub_uint8_t *Buffer, grub_efi_uintn_t Length); ++EXPORT_FUNC(grub_efi_loongson_grub_calculatechecksum8) (const grub_uint8_t *Buffer, ++ grub_efi_uintn_t Length); + ++unsigned long ++EXPORT_FUNC(grub_efi_get_bpi_version) (const char *str); + +void * +EXPORT_FUNC(grub_efi_loongson_get_boot_params) (void); + -+typedef struct _extention_list_hdr{ ++typedef struct _extention_list_hdr { + grub_uint64_t signature; + grub_uint32_t length; + grub_uint8_t revision; + grub_uint8_t checksum; -+ struct _extention_list_hdr *next; ++ union { ++ struct _extention_list_hdr *next; ++ grub_uint64_t next_offset; ++ }; +}GRUB_PACKED +ext_list; + -+typedef struct bootparamsinterface { -+ grub_uint64_t signature; //{'B', 'P', 'I', '_', '0', '_', '1'} ++typedef struct boot_params_interface { ++ grub_uint64_t signature; //{'B', 'P', 'I', 'x', 'x', 'x', 'x', 'x'} + grub_efi_system_table_t *systemtable; -+ ext_list *extlist; ++ union { ++ ext_list *extlist; ++ grub_uint64_t extlist_offset; ++ }; ++ grub_uint64_t flags; +}GRUB_PACKED -+bootparamsinterface; ++boot_params_interface; + +typedef struct { -+ ext_list header; // {'M', 'E', 'M'} ++ ext_list header; //{MEM} + grub_uint8_t mapcount; -+ struct GRUB_PACKED memmap { ++ struct GRUB_PACKED memmap_v1 { + grub_uint32_t memtype; + grub_uint64_t memstart; + grub_uint64_t memsize; + } map[GRUB_EFI_LOONGSON_MMAP_MAX]; +}GRUB_PACKED -+mem_map; ++mem_map_v1; + +typedef struct { -+ ext_list header; // {VBIOS} ++ ext_list header; //{VBIOS} + grub_uint64_t vbiosaddr; +}GRUB_PACKED +vbios; + -+grub_uint32_t -+EXPORT_FUNC (grub_efi_loongson_memmap_sort) (struct memmap array[], grub_uint32_t length, mem_map * bpmem, grub_uint32_t index, grub_uint32_t memtype); ++grub_uint32_t ++EXPORT_FUNC (grub_efi_loongson_memmap_v1_sort) (struct memmap_v1 array[], ++ grub_uint32_t length, mem_map_v1 * mem, ++ grub_uint32_t index, grub_uint32_t memtype); +#endif /* ! GRUB_EFI_LOONGSON_HEADER */ diff --git a/include/grub/loongarch64/efi/memory.h b/include/grub/loongarch64/efi/memory.h new file mode 100644 -index 0000000..b8556c7 +index 0000000..73641a1 --- /dev/null +++ b/include/grub/loongarch64/efi/memory.h -@@ -0,0 +1,14 @@ +@@ -0,0 +1,12 @@ +#ifndef GRUB_MEMORY_CPU_HEADER +#include + -+#define GRUB_EFI_MAX_USABLE_ADDRESS 0x9800000fffffffffUL -+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS -+ -+static inline grub_uint64_t grub_efi_max_usable_address(void) ++static inline grub_uint64_t ++grub_efi_max_usable_address(void) +{ -+ grub_uint64_t addr; -+ asm volatile ("csrrd %0, 0x181" : "=r" (addr)); -+ return addr |= 0xffffffffffUL; ++ grub_uint64_t addr; ++ asm volatile ("csrrd %0, 0x181" : "=r" (addr)); ++ return addr |= 0xffffffffffUL; +} + +#endif /* ! GRUB_MEMORY_CPU_HEADER */ @@ -2944,15 +2395,15 @@ index 0000000..5f34103 +} + +#endif /* _SYS_IO_H */ -diff --git a/include/grub/loongarch64/kernel.h b/include/grub/loongarch64/kernel.h +diff --git a/include/grub/loongarch64/linux.h b/include/grub/loongarch64/linux.h new file mode 100644 -index 0000000..909d539 +index 0000000..3c6cf65 --- /dev/null -+++ b/include/grub/loongarch64/kernel.h -@@ -0,0 +1,24 @@ ++++ b/include/grub/loongarch64/linux.h +@@ -0,0 +1,74 @@ +/* + * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2005,2006,2007,2008,2009,2017 Free Software Foundation, Inc. ++ * Copyright (C) 2021 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -2968,38 +2419,60 @@ index 0000000..909d539 + * along with GRUB. If not, see . + */ + -+#ifndef GRUB_KERNEL_CPU_HEADER -+#define GRUB_KERNEL_CPU_HEADER 1 ++#ifndef GRUB_LOONGARCH64_LINUX_HEADER ++#define GRUB_LOONGARCH64_LINUX_HEADER 1 + -+#include ++#include + -+#endif /* ! GRUB_KERNEL_MACHINE_HEADER */ -diff --git a/include/grub/loongarch64/linux.h b/include/grub/loongarch64/linux.h -new file mode 100644 -index 0000000..cbf8775 ---- /dev/null -+++ b/include/grub/loongarch64/linux.h -@@ -0,0 +1,22 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2013 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. ++/* LoongArch linux kernel type */ ++#define GRUB_LOONGARCH_LINUX_BAD 0 ++#define GRUB_LOONGARCH_LINUX_ELF 1 ++#define GRUB_LOONGARCH_LINUX_EFI 2 ++ ++#define GRUB_LOONGSON3_BOOT_MEM_MAP_MAX 128 ++ ++#define GRUB_LINUX_LOONGARCH_MAGIC_SIGNATURE 0x4C6F6F6E67417263 /* 'LoongArc' */ ++#define GRUB_LINUX_LOONGARCH_MAGIC_SIGNATURE2 0x68 /* 'h' */ ++#define linux_arch_kernel_header linux_loongarch64_kernel_header ++ ++/* From linux/Documentation/loongarch/booting.txt + * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . ++ * 0-1: MZ ++ * 0x28: LoongArch\0 ++ * 0x3c: PE/COFF头偏移 ++ * 0x20e:内核版本号偏移-512 ++ * riscv的version字段在0x20偏移处,现在LoongArch没有使用,是0 + */ ++struct linux_loongarch64_kernel_header ++{ ++ grub_uint32_t code0; /* Executable code */ ++ grub_uint32_t code1; /* Executable code */ ++ grub_uint64_t text_offset; /* Image load offset */ ++ grub_uint64_t res0; /* reserved */ ++ grub_uint64_t res1; /* reserved */ ++ grub_uint64_t res2; /* reserved */ ++ grub_uint64_t magic; /* Magic number, little endian, "LoongArc" */ ++ grub_uint32_t magic1; /* Magic number, little endian, "h" */ ++ grub_uint64_t res3; /* reserved */ ++ grub_uint32_t hdr_offset; /* Offset of PE/COFF header */ ++}; + -+#ifndef GRUB_LOONGARCH64_LINUX_HEADER -+#define GRUB_LOONGARCH64_LINUX_HEADER 1 ++struct linux_loongarch64_kernel_params ++{ ++ grub_addr_t kernel_addr; /* kernel entry address */ ++ grub_size_t kernel_size; /* kernel size */ ++ grub_addr_t ramdisk_addr; /* initrd load address */ ++ grub_size_t ramdisk_size; /* initrd size */ ++ int linux_argc; ++ grub_addr_t linux_argv; ++ void* linux_args; ++}; ++ ++#include ++#include ++ ++#define ELF32_LOADMASK (0xf0000000UL) ++#define ELF64_LOADMASK (0xf000000000000000ULL) + +#endif /* ! GRUB_LOONGARCH64_LINUX_HEADER */ diff --git a/include/grub/loongarch64/loongarch64.h b/include/grub/loongarch64/loongarch64.h @@ -3040,10 +2513,10 @@ index 0000000..ea3be3d +#endif diff --git a/include/grub/loongarch64/memory.h b/include/grub/loongarch64/memory.h new file mode 100644 -index 0000000..03398b3 +index 0000000..8281dab --- /dev/null +++ b/include/grub/loongarch64/memory.h -@@ -0,0 +1,57 @@ +@@ -0,0 +1,60 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2017 Free Software Foundation, Inc. @@ -3084,12 +2557,15 @@ index 0000000..03398b3 +} + +static inline void * -+grub_map_memory (grub_phys_addr_t a, grub_size_t size) ++grub_map_memory (grub_phys_addr_t a, ++ grub_size_t size __attribute__ ((unused))) +{ + grub_uint64_t addr; -+ + asm volatile ("csrrd %0, 0x181" : "=r" (addr)); -+ return (void *) (a | (addr & 0xffffffffffffff00UL)); ++ if (addr & 0x1) ++ return (void *) (a | (addr & 0xffffffffffffff00UL)); ++ else ++ return (void *) a; +} + +static inline void @@ -3937,7 +3413,7 @@ index 03ba1ab..4a9943a 100644 struct platform_whitelist { diff --git a/util/mkimage.c b/util/mkimage.c -index 16418e2..0d39c07 100644 +index c770259..250ca81 100644 --- a/util/mkimage.c +++ b/util/mkimage.c @@ -609,6 +609,22 @@ static const struct grub_install_image_target_desc image_targets[] = @@ -3964,5 +3440,5 @@ index 16418e2..0d39c07 100644 #include -- -2.27.0 +2.1.0 diff --git a/grub.patches b/grub.patches index 1d6dc07..c6bf593 100644 --- a/grub.patches +++ b/grub.patches @@ -677,3 +677,4 @@ Patch0677: 0677-fs-ext2-Rework-out-of-bounds-read-for-inline-and-ext.patch # Support loongarch64 #Patch1000: 1000-loongarch64-add-support.patch Patch1001: 1001-bls-make-list.patch +Patch1002: 1002-Add-LoongArch64-support-and-update-interface-to-v40.patch diff --git a/grub2.spec b/grub2.spec index ede542e..29879c6 100644 --- a/grub2.spec +++ b/grub2.spec @@ -540,6 +540,9 @@ fi - Build pc-modules package on x86_64 (geliwei@openanolis.org) - Add loongarch64 base support (zhangwenlong@loongson.cn)(chenguoqi@loongson.cn) - Fix a bug in bls_make_list, blscfg. (zhonglingh@linux.alibaba.com) +- Delete LoongArch64 support old version due to compile error(yangqiming@loongson.cn) +- Add LoongArch64 support(yangqiming@loongson.cn) +- LoongArch64 support fdt and phy-addr BIOS(yangqiming@loongson.cn) * Thu Apr 17 2025 Nicolas Frayer - 2.02-165 - fs/ext2: Rework of OOB read patch -- Gitee From 9fe1a59cd415bc4a78fe32991fd23552c042bbfe Mon Sep 17 00:00:00 2001 From: Liwei Ge Date: Thu, 18 Aug 2022 16:47:48 +0800 Subject: [PATCH 6/8] kernel-install: remove dtb dir with correct rm argument --- 20-grub.install | 2 +- grub2.spec | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/20-grub.install b/20-grub.install index 0ecf1e2..40a437c 100755 --- a/20-grub.install +++ b/20-grub.install @@ -62,7 +62,7 @@ case "$COMMAND" in "$KERNEL_DIR"/dtb do [[ -e "$i" ]] || continue - rm -f "/boot/${i##*/}-${KERNEL_VERSION}" + rm -rf "/boot/${i##*/}-${KERNEL_VERSION}" cp -aT "$i" "/boot/${i##*/}-${KERNEL_VERSION}" command -v restorecon &>/dev/null && \ restorecon -R "/boot/${i##*/}-${KERNEL_VERSION}" diff --git a/grub2.spec b/grub2.spec index 29879c6..5273af0 100644 --- a/grub2.spec +++ b/grub2.spec @@ -543,6 +543,7 @@ fi - Delete LoongArch64 support old version due to compile error(yangqiming@loongson.cn) - Add LoongArch64 support(yangqiming@loongson.cn) - LoongArch64 support fdt and phy-addr BIOS(yangqiming@loongson.cn) +- Remove dtb dir with correct argument (Liwei Ge) * Thu Apr 17 2025 Nicolas Frayer - 2.02-165 - fs/ext2: Rework of OOB read patch -- Gitee From 37da38b0445c4a994f20f4c12d76650014c90eab Mon Sep 17 00:00:00 2001 From: hanliyang Date: Thu, 2 Jan 2025 09:36:13 +0000 Subject: [PATCH 7/8] [Feature]Hygon: Support use confidential computing provisioned secrets for disk decryption to #bug13129 The code of this functionality is cherry-picked from https://lists.gnu.org/archive/html/grub-devel/2020-12/msg00257.html. project: Signed-off-by: hanliyang --- ...the-password-getter-and-additional-a.patch | 173 ++++++++++++++ ...odisk-add-OS-provided-secret-support.patch | 206 +++++++++++++++++ ...retrieving-the-EFI-secret-for-crypto.patch | 217 ++++++++++++++++++ grub.patches | 3 + grub2.spec | 1 + 5 files changed, 600 insertions(+) create mode 100644 1003-cryptodisk-make-the-password-getter-and-additional-a.patch create mode 100644 1004-cryptodisk-add-OS-provided-secret-support.patch create mode 100644 1005-efi-Add-API-for-retrieving-the-EFI-secret-for-crypto.patch diff --git a/1003-cryptodisk-make-the-password-getter-and-additional-a.patch b/1003-cryptodisk-make-the-password-getter-and-additional-a.patch new file mode 100644 index 0000000..bf6e451 --- /dev/null +++ b/1003-cryptodisk-make-the-password-getter-and-additional-a.patch @@ -0,0 +1,173 @@ +From 6503036b4adfcb078dc33b23a61969d914f7449b Mon Sep 17 00:00:00 2001 +From: James Bottomley +Date: Thu, 31 Dec 2020 09:36:16 -0800 +Subject: [PATCH 1/3] cryptodisk: make the password getter and additional + argument to recover_key + +cherry-picked from https://lists.gnu.org/archive/html/grub-devel/2020-12/msg00258.html. + +For AMD SEV environments, the grub boot password has to be retrieved +from a given memory location rather than prompted for. This means +that the standard password getter needs to be replaced with one that +gets the passphrase from the SEV area and uses that instead. Adding +the password getter as a passed in argument to recover_key() makes +this possible. + +Signed-off-by: James Bottomley +--- + grub-core/disk/cryptodisk.c | 2 +- + grub-core/disk/geli.c | 12 +++++++----- + grub-core/disk/luks.c | 12 +++++++----- + grub-core/lib/crypto.c | 4 ++++ + grub-core/osdep/unix/password.c | 4 ++++ + grub-core/osdep/windows/password.c | 4 ++++ + include/grub/cryptodisk.h | 6 +++++- + 7 files changed, 32 insertions(+), 12 deletions(-) + +diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c +index 78a9025..133d36d 100644 +--- a/grub-core/disk/cryptodisk.c ++++ b/grub-core/disk/cryptodisk.c +@@ -839,7 +839,7 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source) + if (!dev) + continue; + +- err = cr->recover_key (source, dev); ++ err = cr->recover_key (source, dev, grub_password_get); + if (err) + { + cryptodisk_close (dev); +diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c +index e9d2329..ed43047 100644 +--- a/grub-core/disk/geli.c ++++ b/grub-core/disk/geli.c +@@ -398,7 +398,8 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, + } + + static grub_err_t +-recover_key (grub_disk_t source, grub_cryptodisk_t dev) ++recover_key (grub_disk_t source, grub_cryptodisk_t dev, ++ grub_passwd_cb *password_get) + { + grub_size_t keysize; + grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN]; +@@ -438,11 +439,12 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) + tmp = NULL; + if (source->partition) + tmp = grub_partition_get_name (source->partition); +- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, +- source->partition ? "," : "", tmp ? : "", +- dev->uuid); ++ if (password_get (NULL, 0)) ++ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, ++ source->partition ? "," : "", tmp ? : "", ++ dev->uuid); + grub_free (tmp); +- if (!grub_password_get (passphrase, MAX_PASSPHRASE)) ++ if (!password_get (passphrase, MAX_PASSPHRASE)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); + + /* Calculate the PBKDF2 of the user supplied passphrase. */ +diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c +index 18b3a8b..037d20d 100644 +--- a/grub-core/disk/luks.c ++++ b/grub-core/disk/luks.c +@@ -309,7 +309,8 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, + + static grub_err_t + luks_recover_key (grub_disk_t source, +- grub_cryptodisk_t dev) ++ grub_cryptodisk_t dev, ++ grub_passwd_cb *password_get) + { + struct grub_luks_phdr header; + grub_size_t keysize; +@@ -344,11 +345,12 @@ luks_recover_key (grub_disk_t source, + tmp = NULL; + if (source->partition) + tmp = grub_partition_get_name (source->partition); +- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, +- source->partition ? "," : "", tmp ? : "", +- dev->uuid); ++ if (password_get (NULL, 0)) ++ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, ++ source->partition ? "," : "", tmp ? : "", ++ dev->uuid); + grub_free (tmp); +- if (!grub_password_get (passphrase, MAX_PASSPHRASE)) ++ if (!password_get (passphrase, MAX_PASSPHRASE)) + { + grub_free (split_key); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); +diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c +index ff62fa3..07c4400 100644 +--- a/grub-core/lib/crypto.c ++++ b/grub-core/lib/crypto.c +@@ -460,6 +460,10 @@ grub_password_get (char buf[], unsigned buf_size) + unsigned cur_len = 0; + int key; + ++ if (!buf) ++ /* want prompt */ ++ return 1; ++ + while (1) + { + key = grub_getkey (); +diff --git a/grub-core/osdep/unix/password.c b/grub-core/osdep/unix/password.c +index 9996b24..365ac4b 100644 +--- a/grub-core/osdep/unix/password.c ++++ b/grub-core/osdep/unix/password.c +@@ -34,6 +34,10 @@ grub_password_get (char buf[], unsigned buf_size) + int tty_changed = 0; + char *ptr; + ++ if (!buf) ++ /* want prompt */ ++ return 1; ++ + grub_refresh (); + + /* Disable echoing. Based on glibc. */ +diff --git a/grub-core/osdep/windows/password.c b/grub-core/osdep/windows/password.c +index 1d3af0c..2a66156 100644 +--- a/grub-core/osdep/windows/password.c ++++ b/grub-core/osdep/windows/password.c +@@ -33,6 +33,10 @@ grub_password_get (char buf[], unsigned buf_size) + DWORD mode = 0; + char *ptr; + ++ if (!buf) ++ /* want prompt */ ++ return 1; ++ + grub_refresh (); + + GetConsoleMode (hStdin, &mode); +diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h +index 32f564a..33c86ad 100644 +--- a/include/grub/cryptodisk.h ++++ b/include/grub/cryptodisk.h +@@ -101,6 +101,9 @@ struct grub_cryptodisk + }; + typedef struct grub_cryptodisk *grub_cryptodisk_t; + ++/* must match prototype for grub_password_get */ ++typedef int (grub_passwd_cb)(char buf[], unsigned buf_size); ++ + struct grub_cryptodisk_dev + { + struct grub_cryptodisk_dev *next; +@@ -108,7 +111,8 @@ struct grub_cryptodisk_dev + + grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid, + int boot_only); +- grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev); ++ grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev, ++ grub_passwd_cb *get_passwd); + }; + typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t; + +-- +2.43.5 + diff --git a/1004-cryptodisk-add-OS-provided-secret-support.patch b/1004-cryptodisk-add-OS-provided-secret-support.patch new file mode 100644 index 0000000..958a745 --- /dev/null +++ b/1004-cryptodisk-add-OS-provided-secret-support.patch @@ -0,0 +1,206 @@ +From a6d7988415f1ff7e3977b7e15aacaf1e7f854aac Mon Sep 17 00:00:00 2001 +From: James Bottomley +Date: Thu, 31 Dec 2020 09:36:17 -0800 +Subject: [PATCH 2/3] cryptodisk: add OS provided secret support + +cherry-picked from https://lists.gnu.org/archive/html/grub-devel/2020-12/msg00259.html. + +Make use of the new OS provided secrets API so that if the new '-s' +option is passed in we try to extract the secret from the API rather +than prompting for it. + +The primary consumer of this is AMD SEV, which has been programmed to +provide an injectable secret to the encrypted virtual machine. OVMF +provides the secret area and passes it into the EFI Configuration +Tables. The grub EFI layer pulls the secret out and primes the +secrets API with it. The upshot of all of this is that a SEV +protected VM can do an encrypted boot with a protected boot secret. + +Signed-off-by: James Bottomley +--- + grub-core/disk/cryptodisk.c | 77 +++++++++++++++++++++++++++++++++++-- + include/grub/cryptodisk.h | 14 +++++++ + 2 files changed, 87 insertions(+), 4 deletions(-) + +diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c +index 133d36d..d2b1617 100644 +--- a/grub-core/disk/cryptodisk.c ++++ b/grub-core/disk/cryptodisk.c +@@ -41,6 +41,7 @@ static const struct grub_arg_option options[] = + /* TRANSLATORS: It's still restricted to cryptodisks only. */ + {"all", 'a', 0, N_("Mount all."), 0, 0}, + {"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0}, ++ {"secret", 's', 0, N_("Get secret passphrase from named module and optional identifier"), 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + +@@ -809,6 +810,10 @@ grub_util_cryptodisk_get_uuid (grub_disk_t disk) + + static int check_boot, have_it; + static char *search_uuid; ++static char *os_passwd; ++ ++/* variable to hold the list of secret providers */ ++static struct grub_secret_entry *secret_providers; + + static void + cryptodisk_close (grub_cryptodisk_t dev) +@@ -819,6 +824,21 @@ cryptodisk_close (grub_cryptodisk_t dev) + grub_free (dev); + } + ++static int ++os_password_get(char buf[], unsigned len) ++{ ++ if (!buf) ++ /* we're not interactive so no prompt */ ++ return 0; ++ ++ /* os_passwd should be null terminated, so just copy everything */ ++ grub_strncpy(buf, os_passwd, len); ++ /* and add a terminator just in case */ ++ buf[len - 1] = 0; ++ ++ return 1; ++} ++ + static grub_err_t + grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source) + { +@@ -838,8 +858,17 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source) + return grub_errno; + if (!dev) + continue; +- +- err = cr->recover_key (source, dev, grub_password_get); ++ ++ if (os_passwd) ++ { ++ err = cr->recover_key (source, dev, os_password_get); ++ if (err) ++ /* if the key doesn't work ignore the access denied error */ ++ grub_error_pop(); ++ } ++ else ++ err = cr->recover_key (source, dev, grub_password_get); ++ + if (err) + { + cryptodisk_close (dev); +@@ -855,6 +884,18 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source) + return GRUB_ERR_NONE; + } + ++void ++grub_cryptodisk_add_secret_provider (struct grub_secret_entry *e) ++{ ++ grub_list_push(GRUB_AS_LIST_P (&secret_providers), GRUB_AS_LIST (e)); ++} ++ ++void ++grub_cryptodisk_remove_secret_provider (struct grub_secret_entry *e) ++{ ++ grub_list_remove (GRUB_AS_LIST (e)); ++} ++ + #ifdef GRUB_UTIL + #include + grub_err_t +@@ -931,7 +972,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) + { + struct grub_arg_list *state = ctxt->state; + +- if (argc < 1 && !state[1].set && !state[2].set) ++ if (argc < 1 && !state[1].set && !state[2].set && !state[3].set) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); + + have_it = 0; +@@ -949,6 +990,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) + + check_boot = state[2].set; + search_uuid = args[0]; ++ os_passwd = NULL; + grub_device_iterate (&grub_cryptodisk_scan_device, NULL); + search_uuid = NULL; + +@@ -959,11 +1001,37 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) + else if (state[1].set || (argc == 0 && state[2].set)) + { + search_uuid = NULL; ++ os_passwd = NULL; + check_boot = state[2].set; + grub_device_iterate (&grub_cryptodisk_scan_device, NULL); + search_uuid = NULL; + return GRUB_ERR_NONE; + } ++ else if (state[3].set) ++ { ++ struct grub_secret_entry *se; ++ grub_err_t rc; ++ ++ if (argc < 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "secret module must be specified"); ++#ifndef GRUB_UTIL ++ grub_dl_load (args[0]); ++#endif ++ se = grub_named_list_find (GRUB_AS_NAMED_LIST (secret_providers), args[0]); ++ if (se == NULL) ++ return grub_error (GRUB_ERR_INVALID_COMMAND, "No secret provider is found"); ++ ++ rc = se->get (args[1], &os_passwd); ++ if (rc) ++ return rc; ++ ++ search_uuid = NULL; ++ grub_device_iterate (&grub_cryptodisk_scan_device, NULL); ++ rc = se->put (args[1], have_it, &os_passwd); ++ os_passwd = NULL; ++ ++ return rc; ++ } + else + { + grub_err_t err; +@@ -974,6 +1042,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) + grub_size_t len; + + search_uuid = NULL; ++ os_passwd = NULL; + check_boot = state[2].set; + diskname = args[0]; + len = grub_strlen (diskname); +@@ -1141,7 +1210,7 @@ GRUB_MOD_INIT (cryptodisk) + { + grub_disk_dev_register (&grub_cryptodisk_dev); + cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0, +- N_("SOURCE|-u UUID|-a|-b"), ++ N_("SOURCE|-u UUID|-a|-b|-s MOD [ID]"), + N_("Mount a crypto device."), options); + grub_procfs_register ("luks_script", &luks_script); + } +diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h +index 33c86ad..6a93c56 100644 +--- a/include/grub/cryptodisk.h ++++ b/include/grub/cryptodisk.h +@@ -160,4 +160,18 @@ grub_util_get_geli_uuid (const char *dev); + grub_cryptodisk_t grub_cryptodisk_get_by_uuid (const char *uuid); + grub_cryptodisk_t grub_cryptodisk_get_by_source_disk (grub_disk_t disk); + ++struct grub_secret_entry { ++ /* as named list */ ++ struct grub_secret_entry *next; ++ struct grub_secret_entry **prev; ++ const char *name; ++ ++ /* additional entries */ ++ grub_err_t (*get)(const char *arg, char **secret); ++ grub_err_t (*put)(const char *arg, int have_it, char **secret); ++}; ++ ++void grub_cryptodisk_add_secret_provider (struct grub_secret_entry *e); ++void grub_cryptodisk_remove_secret_provider (struct grub_secret_entry *e); ++ + #endif +-- +2.43.5 + diff --git a/1005-efi-Add-API-for-retrieving-the-EFI-secret-for-crypto.patch b/1005-efi-Add-API-for-retrieving-the-EFI-secret-for-crypto.patch new file mode 100644 index 0000000..cf51219 --- /dev/null +++ b/1005-efi-Add-API-for-retrieving-the-EFI-secret-for-crypto.patch @@ -0,0 +1,217 @@ +From 9711568e6dce36a6245fada1509e9477c0268e30 Mon Sep 17 00:00:00 2001 +From: James Bottomley +Date: Thu, 31 Dec 2020 09:36:18 -0800 +Subject: [PATCH 3/3] efi: Add API for retrieving the EFI secret for cryptodisk + +cherry-picked from https://lists.gnu.org/archive/html/grub-devel/2020-12/msg00260.html. + +This module is designed to provide an efisecret command which +interrogates the EFI configuration table to find the location of the +confidential computing secret and tries to register the secret with +the cryptodisk. + +The secret is stored in a boot allocated area, usually a page in size. +The layout of the secret injection area is a header + +|GRUB_EFI_SECRET_TABLE_HEADER_GUID|len| + +with entries of the form + +|guid|len|data| + +the guid corresponding to the disk encryption passphrase is +GRUB_EFI_DISKPASSWD_GUID and data must be a zero terminated string. +To get a high entropy string that doesn't need large numbers of +iterations, use a base64 encoding of 33 bytes of random data. + +Signed-off-by: James Bottomley +--- + grub-core/Makefile.core.def | 8 ++ + grub-core/disk/efi/efisecret.c | 129 +++++++++++++++++++++++++++++++++ + include/grub/efi/api.h | 15 ++++ + 3 files changed, 152 insertions(+) + create mode 100644 grub-core/disk/efi/efisecret.c + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 0963e88..aded014 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -774,6 +774,14 @@ module = { + enable = efi; + }; + ++module = { ++ name = efisecret; ++ ++ common = disk/efi/efisecret.c; ++ ++ enable = efi; ++}; ++ + module = { + name = lsefimmap; + +diff --git a/grub-core/disk/efi/efisecret.c b/grub-core/disk/efi/efisecret.c +new file mode 100644 +index 0000000..745eede +--- /dev/null ++++ b/grub-core/disk/efi/efisecret.c +@@ -0,0 +1,129 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++static grub_efi_packed_guid_t secret_guid = GRUB_EFI_SECRET_TABLE_GUID; ++static grub_efi_packed_guid_t tableheader_guid = GRUB_EFI_SECRET_TABLE_HEADER_GUID; ++static grub_efi_packed_guid_t diskpasswd_guid = GRUB_EFI_DISKPASSWD_GUID; ++ ++/* ++ * EFI places the secret in the lower 4GB, so it uses a UINT32 ++ * for the pointer which we have to transform to the correct type ++ */ ++struct efi_secret { ++ grub_uint64_t base; ++ grub_uint64_t size; ++}; ++ ++struct secret_header { ++ grub_efi_packed_guid_t guid; ++ grub_uint32_t len; ++}; ++ ++struct secret_entry { ++ grub_efi_packed_guid_t guid; ++ grub_uint32_t len; ++ char data[0]; ++}; ++ ++static grub_err_t ++grub_efi_secret_put (const char *arg __attribute__((unused)), int have_it, ++ char **ptr) ++{ ++ struct secret_entry *e = (struct secret_entry *)(*ptr - (long)&((struct secret_entry *)0)->data); ++ ++ /* destroy the secret */ ++ grub_memset (e, 0, e->len); ++ *ptr = NULL; ++ ++ if (have_it) ++ return GRUB_ERR_NONE; ++ ++ return grub_error (GRUB_ERR_ACCESS_DENIED, "EFI secret failed to unlock any volumes"); ++} ++ ++static grub_err_t ++grub_efi_secret_find (struct efi_secret *s, char **secret_ptr) ++{ ++ int len; ++ struct secret_header *h; ++ struct secret_entry *e; ++ unsigned char *ptr = (unsigned char *)(unsigned long)s->base; ++ ++ /* the area must be big enough for a guid and a u32 length */ ++ if (s->size < sizeof (*h)) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area is too small"); ++ ++ h = (struct secret_header *)ptr; ++ if (grub_memcmp(&h->guid, &tableheader_guid, sizeof (h->guid))) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area does not start with correct guid\n"); ++ if (h->len < sizeof (*h)) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area is too small\n"); ++ ++ len = h->len - sizeof (*h); ++ ptr += sizeof (*h); ++ ++ while (len >= (int)sizeof (*e)) { ++ e = (struct secret_entry *)ptr; ++ if (e->len < sizeof(*e) || e->len > (unsigned int)len) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area is corrupt\n"); ++ ++ if (! grub_memcmp (&e->guid, &diskpasswd_guid, sizeof (e->guid))) { ++ int end = e->len - sizeof(*e); ++ ++ /* ++ * the passphrase must be a zero terminated string because the ++ * password routines call grub_strlen () to find its size ++ */ ++ if (e->data[end - 1] != '\0') ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area disk encryption password is not zero terminated\n"); ++ ++ *secret_ptr = e->data; ++ return GRUB_ERR_NONE; ++ } ++ ptr += e->len; ++ len -= e->len; ++ } ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret aread does not contain disk decryption password\n"); ++} ++ ++static grub_err_t ++grub_efi_secret_get (const char *arg __attribute__((unused)), char **ptr) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < grub_efi_system_table->num_table_entries; i++) ++ { ++ grub_efi_packed_guid_t *guid = ++ &grub_efi_system_table->configuration_table[i].vendor_guid; ++ ++ if (! grub_memcmp (guid, &secret_guid, sizeof (grub_efi_packed_guid_t))) { ++ struct efi_secret *s = ++ grub_efi_system_table->configuration_table[i].vendor_table; ++ ++ return grub_efi_secret_find(s, ptr); ++ } ++ } ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "No secret found in the EFI configuration table"); ++} ++ ++static struct grub_secret_entry secret = { ++ .name = "efisecret", ++ .get = grub_efi_secret_get, ++ .put = grub_efi_secret_put, ++}; ++ ++GRUB_MOD_INIT(efisecret) ++{ ++ grub_cryptodisk_add_secret_provider (&secret); ++} ++ ++GRUB_MOD_FINI(efisecret) ++{ ++ grub_cryptodisk_remove_secret_provider (&secret); ++} +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index a57187f..d5c805d 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -299,6 +299,21 @@ + { 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + ++#define GRUB_EFI_SECRET_TABLE_GUID \ ++ { 0xadf956ad, 0xe98c, 0x484c, \ ++ { 0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47} \ ++ } ++ ++#define GRUB_EFI_SECRET_TABLE_HEADER_GUID \ ++ { 0x1e74f542, 0x71dd, 0x4d66, \ ++ { 0x96, 0x3e, 0xef, 0x42, 0x87, 0xff, 0x17, 0x3b } \ ++ } ++ ++#define GRUB_EFI_DISKPASSWD_GUID \ ++ { 0x736869e5, 0x84f0, 0x4973, \ ++ { 0x92, 0xec, 0x06, 0x87, 0x9c, 0xe3, 0xda, 0x0b } \ ++ } ++ + #define GRUB_EFI_ACPI_TABLE_GUID \ + { 0xeb9d2d30, 0x2d88, 0x11d3, \ + { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ +-- +2.43.5 + diff --git a/grub.patches b/grub.patches index c6bf593..e150afe 100644 --- a/grub.patches +++ b/grub.patches @@ -678,3 +678,6 @@ Patch0677: 0677-fs-ext2-Rework-out-of-bounds-read-for-inline-and-ext.patch #Patch1000: 1000-loongarch64-add-support.patch Patch1001: 1001-bls-make-list.patch Patch1002: 1002-Add-LoongArch64-support-and-update-interface-to-v40.patch +Patch1003: 1003-cryptodisk-make-the-password-getter-and-additional-a.patch +Patch1004: 1004-cryptodisk-add-OS-provided-secret-support.patch +Patch1005: 1005-efi-Add-API-for-retrieving-the-EFI-secret-for-crypto.patch diff --git a/grub2.spec b/grub2.spec index 5273af0..6a2034d 100644 --- a/grub2.spec +++ b/grub2.spec @@ -544,6 +544,7 @@ fi - Add LoongArch64 support(yangqiming@loongson.cn) - LoongArch64 support fdt and phy-addr BIOS(yangqiming@loongson.cn) - Remove dtb dir with correct argument (Liwei Ge) +- Support use confidential computing provisioned secrets for disk decryption(hanliyang@hygon.cn) * Thu Apr 17 2025 Nicolas Frayer - 2.02-165 - fs/ext2: Rework of OOB read patch -- Gitee From 6cfc4eba899115a8305280af9c3b0c2e02472eb2 Mon Sep 17 00:00:00 2001 From: Xue Liu Date: Sat, 22 Mar 2025 17:31:26 +0800 Subject: [PATCH 8/8] Update for loongarch64 in sync with latest v2.04 --- ...ate-patches-in-sync-with-loongarch64.patch | 2815 +++++++++++++++++ grub.patches | 1 + grub2.spec | 1 + 3 files changed, 2817 insertions(+) create mode 100644 1006-Update-patches-in-sync-with-loongarch64.patch diff --git a/1006-Update-patches-in-sync-with-loongarch64.patch b/1006-Update-patches-in-sync-with-loongarch64.patch new file mode 100644 index 0000000..dc39a93 --- /dev/null +++ b/1006-Update-patches-in-sync-with-loongarch64.patch @@ -0,0 +1,2815 @@ +From 7118e2827e64c205e3b2241b85648f2948cab3a3 Mon Sep 17 00:00:00 2001 +From: Fedora Ninjas +Date: Sat, 22 Mar 2025 16:49:13 +0800 +Subject: [PATCH] Update patches in sync with loongarch64 + +--- + gentpl.py | 2 +- + grub-core/Makefile.am | 1 - + grub-core/Makefile.core.def | 11 +- + grub-core/kern/loongarch64/cache.S | 2 + + grub-core/kern/loongarch64/efi/init.c | 2 - + grub-core/kern/loongarch64/efi/startup.S | 4 +- + grub-core/kern/loongarch64/init.c | 47 -- + grub-core/lib/loongarch64/efi/loongson.c | 119 --- + grub-core/lib/loongarch64/relocator.c | 2 +- + grub-core/lib/loongarch64/setjmp.S | 80 +- + grub-core/loader/loongarch64/linux-efi.c | 143 ++++ + grub-core/loader/loongarch64/linux-elf.c | 910 +++++++++++++++++++++++ + grub-core/loader/loongarch64/linux.c | 731 +++++------------- + include/grub/efi/api.h | 20 + + include/grub/fdt.h | 2 +- + include/grub/loongarch64/asm.h | 10 - + include/grub/loongarch64/efi/loongson.h | 113 --- + include/grub/loongarch64/efi/memory.h | 7 +- + include/grub/loongarch64/efi/time.h | 0 + include/grub/loongarch64/linux.h | 163 +++- + include/grub/loongarch64/time.h | 12 - + 21 files changed, 1487 insertions(+), 894 deletions(-) + delete mode 100644 grub-core/kern/loongarch64/init.c + delete mode 100644 grub-core/lib/loongarch64/efi/loongson.c + create mode 100644 grub-core/loader/loongarch64/linux-efi.c + create mode 100644 grub-core/loader/loongarch64/linux-elf.c + delete mode 100644 include/grub/loongarch64/asm.h + delete mode 100644 include/grub/loongarch64/efi/loongson.h + delete mode 100644 include/grub/loongarch64/efi/time.h + +diff --git a/gentpl.py b/gentpl.py +index 3afd642..fa7f1ba 100644 +--- a/gentpl.py ++++ b/gentpl.py +@@ -78,7 +78,7 @@ GROUPS["terminfomodule"] = GRUB_PLATFORMS[:]; + for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) + + # Flattened Device Trees (FDT) +-GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi" ] ++GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi", "loongarch64_efi" ] + + # Needs software helpers for division + # Must match GRUB_DIVISION_IN_SOFTWARE in misc.h +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index a976fad..ec771c5 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -227,7 +227,6 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdt.h +-KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loongson.h + endif + + if COND_powerpc_ieee1275 +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index aded014..b89e58e 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -250,6 +250,9 @@ kernel = { + arm64_efi = kern/arm64/efi/init.c; + arm64_efi = kern/efi/fdt.c; + ++ loongarch64_efi = kern/loongarch64/efi/init.c; ++ loongarch64_efi = kern/efi/fdt.c; ++ + i386_pc = kern/i386/pc/init.c; + i386_pc = kern/i386/pc/mmap.c; + i386_pc = term/i386/pc/console.c; +@@ -300,14 +303,8 @@ kernel = { + extra_dist = video/sis315_init.c; + mips_loongson = commands/keylayouts.c; + +- loongarch64 = kern/loongarch64/init.c; + loongarch64 = kern/loongarch64/dl.c; + loongarch64 = kern/loongarch64/cache.S; +- loongarch64 = kern/generic/rtc_get_time_ms.c; +- loongarch64 = kern/efi/fdt.c; +- loongarch64 = lib/fdt.c; +- loongarch64_efi = kern/loongarch64/efi/init.c; +- loongarch64_efi = lib/loongarch64/efi/loongson.c; + + powerpc_ieee1275 = kern/powerpc/cache.S; + powerpc_ieee1275 = kern/powerpc/dl.c; +@@ -1767,6 +1764,8 @@ module = { + i386_pc = lib/i386/pc/vesa_modes_table.c; + mips = loader/mips/linux.c; + loongarch64 = loader/loongarch64/linux.c; ++ loongarch64 = loader/loongarch64/linux-elf.c; ++ loongarch64 = loader/loongarch64/linux-efi.c; + powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c; + sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c; + ia64_efi = loader/ia64/efi/linux.c; +diff --git a/grub-core/kern/loongarch64/cache.S b/grub-core/kern/loongarch64/cache.S +index d291c67..b268261 100644 +--- a/grub-core/kern/loongarch64/cache.S ++++ b/grub-core/kern/loongarch64/cache.S +@@ -19,6 +19,8 @@ + #include + + FUNCTION (grub_arch_sync_caches) ++ ibar 0 ++ dbar 0 + jr $ra + + FUNCTION (grub_arch_sync_dma_caches) +diff --git a/grub-core/kern/loongarch64/efi/init.c b/grub-core/kern/loongarch64/efi/init.c +index 632c39a..15c41aa 100644 +--- a/grub-core/kern/loongarch64/efi/init.c ++++ b/grub-core/kern/loongarch64/efi/init.c +@@ -1,4 +1,3 @@ +-/* init.c - initialize an arm-based EFI system */ + /* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. +@@ -24,7 +23,6 @@ + #include + #include + #include +-#include + + static grub_uint64_t tmr; + static grub_efi_event_t tmr_evt; +diff --git a/grub-core/kern/loongarch64/efi/startup.S b/grub-core/kern/loongarch64/efi/startup.S +index 1ffff08..00ecd15 100644 +--- a/grub-core/kern/loongarch64/efi/startup.S ++++ b/grub-core/kern/loongarch64/efi/startup.S +@@ -19,8 +19,9 @@ + #include + + .file "startup.S" +- .text + .globl start, _start ++ .text ++ + .align 4 + + FUNCTION(start) +@@ -42,4 +43,3 @@ FUNCTION(_start) + ld.d $ra, $sp, 0 + addi.d $sp, $sp, 16 + jr $ra +- +diff --git a/grub-core/kern/loongarch64/init.c b/grub-core/kern/loongarch64/init.c +deleted file mode 100644 +index b2de930..0000000 +--- a/grub-core/kern/loongarch64/init.c ++++ /dev/null +@@ -1,47 +0,0 @@ +-/* +- * GRUB -- GRand Unified Bootloader +- * Copyright (C) 2009,2017 Free Software Foundation, Inc. +- * +- * GRUB is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * GRUB is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with GRUB. If not, see . +- */ +- +-#include +-#include +-#include +-#include +- +-grub_uint32_t grub_arch_cpuclock; +- +-/* FIXME: use interrupt to count high. */ +-grub_uint64_t +-grub_get_rtc (void) +-{ +- static grub_uint32_t high = 0; +- static grub_uint32_t last = 0; +- grub_uint32_t low; +- +- asm volatile ("csrrd %0, " GRUB_CPU_LOONGARCH_COP0_TIMER_COUNT : "=r" (low)); +- if (low < last) +- high++; +- last = low; +- +- return (((grub_uint64_t) high) << 32) | low; +-} +- +-void +-grub_timer_init (grub_uint32_t cpuclock) +-{ +- grub_arch_cpuclock = cpuclock; +- grub_install_get_time_ms (grub_rtc_get_time_ms); +-} +diff --git a/grub-core/lib/loongarch64/efi/loongson.c b/grub-core/lib/loongarch64/efi/loongson.c +deleted file mode 100644 +index eda1e1c..0000000 +--- a/grub-core/lib/loongarch64/efi/loongson.c ++++ /dev/null +@@ -1,119 +0,0 @@ +-/* +- * GRUB -- GRand Unified Bootloader +- * Copyright (C) 2017 Free Software Foundation, Inc. +- * +- * GRUB is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * GRUB is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with GRUB. If not, see . +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-unsigned long +-grub_efi_get_bpi_version (const char *str) +-{ +- unsigned long version = GRUB_EFI_BPI_VER_NONE; +- +- version = grub_strtoul (str + 4, 0, 0); +- +- return version; +-} +- +-void * +-grub_efi_loongson_get_boot_params (void) +-{ +- static void * boot_params = NULL; +- grub_efi_configuration_table_t *tables; +- grub_efi_guid_t loongson_bpi_guid = GRUB_EFI_LOONGSON_BPI_TABLE_GUID; +- unsigned int i; +- +- if (boot_params) +- return boot_params; +- +- /* Look for Loongson boot params interface in UEFI config tables. */ +- tables = grub_efi_system_table->configuration_table; +- +- for (i = 0; i < grub_efi_system_table->num_table_entries; i++) +- if (grub_memcmp (&tables[i].vendor_guid, &loongson_bpi_guid, sizeof (loongson_bpi_guid)) == 0) +- { +- boot_params= tables[i].vendor_table; +- grub_dprintf ("loongson", "found registered BPI @ %p\n", boot_params); +- break; +- } +- return boot_params; +-} +- +-grub_uint8_t +-grub_efi_loongson_calculatesum8 (const grub_uint8_t *buffer, grub_efi_uintn_t length) +-{ +- grub_uint8_t sum; +- grub_efi_uintn_t count; +- +- for (sum = 0, count = 0; count < length; count++) +- { +- sum = (grub_uint8_t) (sum + *(buffer + count)); +- } +- return sum; +-} +- +-grub_uint8_t +-grub_efi_loongson_grub_calculatechecksum8 (const grub_uint8_t *buffer, grub_efi_uintn_t length) +-{ +- grub_uint8_t checksum; +- +- checksum = grub_efi_loongson_calculatesum8(buffer, length); +- +- return (grub_uint8_t) (0x100 - checksum); +-} +- +- +-grub_uint32_t +-grub_efi_loongson_memmap_v1_sort(struct memmap_v1 array[], grub_uint32_t length, +- mem_map_v1 * bpmem, grub_uint32_t index, grub_uint32_t memtype) +-{ +- grub_uint64_t tempmemsize = 0; +- grub_uint32_t j = 0; +- grub_uint32_t t = 0; +- +- for(j = 0; j < length;) +- { +- tempmemsize = array[j].memsize; +- for(t = j + 1; t < length; t++) +- { +- if(array[j].memstart + tempmemsize == array[t].memstart) +- { +- tempmemsize += array[t].memsize; +- } +- else +- { +- break; +- } +- } +- bpmem->map[index].memtype = memtype; +- bpmem->map[index].memstart = array[j].memstart; +- bpmem->map[index].memsize = tempmemsize; +- grub_dprintf("loongson", "v1 map[%d]:type %x, start 0x%lx, end 0x%lx\n", +- index, +- bpmem->map[index].memtype, +- bpmem->map[index].memstart, +- bpmem->map[index].memstart+ bpmem->map[index].memsize +- ); +- j = t; +- index++; +- } +- return index; +-} +diff --git a/grub-core/lib/loongarch64/relocator.c b/grub-core/lib/loongarch64/relocator.c +index 4b253ca..7217b68 100644 +--- a/grub-core/lib/loongarch64/relocator.c ++++ b/grub-core/lib/loongarch64/relocator.c +@@ -122,7 +122,7 @@ grub_relocator64_boot (struct grub_relocator *rel, + unsigned i; + grub_addr_t vtarget; + +- err = grub_relocator_alloc_chunk_align (rel, &ch, 0, ++ err = grub_relocator_alloc_chunk_align (rel, &ch, 0x3000000, + (0xffffffff - stateset_size) + + 1, stateset_size, + grub_relocator_align, +diff --git a/grub-core/lib/loongarch64/setjmp.S b/grub-core/lib/loongarch64/setjmp.S +index 47db814..bb09959 100644 +--- a/grub-core/lib/loongarch64/setjmp.S ++++ b/grub-core/lib/loongarch64/setjmp.S +@@ -1,6 +1,6 @@ + /* + * GRUB -- GRand Unified Bootloader +- * Copyright (C) 2003,2007,2009 Free Software Foundation, Inc. ++ * Copyright (C) 2021 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -16,9 +16,7 @@ + * along with GRUB. If not, see . + */ + +-#include + #include +-#include + + .file "setjmp.S" + +@@ -27,48 +25,44 @@ GRUB_MOD_LICENSE "GPLv3+" + .text + + /* +- * int grub_setjmp (grub_jmp_buf env) ++ * int grub_setjmp (jmp_buf env) + */ + FUNCTION(grub_setjmp) +- GRUB_ASM_REG_S $s0, $a0,0 +- GRUB_ASM_REG_S $s1, $a0,8 +- GRUB_ASM_REG_S $s2, $a0,16 +- GRUB_ASM_REG_S $s3, $a0,24 +- GRUB_ASM_REG_S $s4, $a0,32 +- GRUB_ASM_REG_S $s5, $a0,40 +- GRUB_ASM_REG_S $s6, $a0,48 +- GRUB_ASM_REG_S $s7, $a0,56 +- GRUB_ASM_REG_S $s8, $a0,64 +- GRUB_ASM_REG_S $fp, $a0,72 +- GRUB_ASM_REG_S $sp, $a0,80 +- GRUB_ASM_REG_S $ra, $a0,88 +- move $v0, $zero +- move $v1, $zero +- jr $ra +- nop ++ st.d $s0, $a0, 0x0 ++ st.d $s1, $a0, 0x8 ++ st.d $s2, $a0, 0x10 ++ st.d $s3, $a0, 0x18 ++ st.d $s4, $a0, 0x20 ++ st.d $s5, $a0, 0x28 ++ st.d $s6, $a0, 0x30 ++ st.d $s7, $a0, 0x38 ++ st.d $s8, $a0, 0x40 ++ st.d $fp, $a0, 0x48 ++ st.d $sp, $a0, 0x50 ++ st.d $ra, $a0, 0x58 ++ ++ move $a0, $zero ++ jr $ra ++ + /* +- * int grub_longjmp (grub_jmp_buf env, int val) ++ * void grub_longjmp (jmp_buf env, int val) + */ + FUNCTION(grub_longjmp) +- GRUB_ASM_REG_L $s0, $a0,0 +- GRUB_ASM_REG_L $s1, $a0,8 +- GRUB_ASM_REG_L $s2, $a0,16 +- GRUB_ASM_REG_L $s3, $a0,24 +- GRUB_ASM_REG_L $s4, $a0,32 +- GRUB_ASM_REG_L $s5, $a0,40 +- GRUB_ASM_REG_L $s6, $a0,48 +- GRUB_ASM_REG_L $s7, $a0,56 +- GRUB_ASM_REG_L $s8, $a0,64 +- GRUB_ASM_REG_L $fp, $a0,72 +- GRUB_ASM_REG_L $sp, $a0,80 +- GRUB_ASM_REG_L $ra, $a0,88 +- addi.w $v0, $zero, 1 +- /* +- * replace: movn $v0, $a1, $a1 +- */ +- bnez $a1, .ZW0 +- addi.d $v0, $a1, 0 +-.ZW0: +- addi.d $v1,$zero,0 +- jr $ra +- nop ++ ld.d $s0, $a0, 0x0 ++ ld.d $s1, $a0, 0x8 ++ ld.d $s2, $a0, 0x10 ++ ld.d $s3, $a0, 0x18 ++ ld.d $s4, $a0, 0x20 ++ ld.d $s5, $a0, 0x28 ++ ld.d $s6, $a0, 0x30 ++ ld.d $s7, $a0, 0x38 ++ ld.d $s8, $a0, 0x40 ++ ld.d $fp, $a0, 0x48 ++ ld.d $sp, $a0, 0x50 ++ ld.d $ra, $a0, 0x58 ++ ++ li.w $a0, 1 ++ beqz $a1, .L0 ++ move $a0, $a1 ++.L0: ++ jr $ra +diff --git a/grub-core/loader/loongarch64/linux-efi.c b/grub-core/loader/loongarch64/linux-efi.c +new file mode 100644 +index 0000000..6f5ff15 +--- /dev/null ++++ b/grub-core/loader/loongarch64/linux-efi.c +@@ -0,0 +1,143 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2021 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define GRUB_EFI_PE_MAGIC 0x5A4D ++ ++grub_err_t ++finalize_efi_params_linux (struct linux_loongarch64_kernel_params *kernel_params) ++{ ++ int node, retval; ++ ++ void *fdt; ++ ++ fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE); ++ ++ if (!fdt) ++ goto failure; ++ ++ node = grub_fdt_find_subnode (fdt, 0, "chosen"); ++ if (node < 0) ++ node = grub_fdt_add_subnode (fdt, 0, "chosen"); ++ ++ if (node < 1) ++ goto failure; ++ ++ /* Set initrd info */ ++ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) ++ { ++ grub_dprintf ("linux", "Initrd @ %p-%p\n", ++ (void *) kernel_params->ramdisk_addr, ++ (void *) (kernel_params->ramdisk_addr + kernel_params->ramdisk_size)); ++ ++ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start", ++ kernel_params->ramdisk_addr); ++ if (retval) ++ goto failure; ++ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end", ++ kernel_params->ramdisk_addr + kernel_params->ramdisk_size); ++ if (retval) ++ goto failure; ++ } ++ ++ if (grub_fdt_install() != GRUB_ERR_NONE) ++ goto failure; ++ ++ return GRUB_ERR_NONE; ++ ++failure: ++ grub_fdt_unload(); ++ return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); ++} ++ ++grub_err_t ++grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh) ++{ ++ if ((lh->code0 & 0xffff) == GRUB_EFI_PE_MAGIC) ++ return GRUB_ERR_NONE; ++ else ++ return 1; ++ ++ grub_dprintf ("linux", "UEFI stub kernel:\n"); ++ grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset); ++ ++ return GRUB_ERR_NONE; ++} ++ ++grub_err_t ++grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args) ++{ ++ grub_efi_memory_mapped_device_path_t *mempath; ++ grub_efi_handle_t image_handle; ++ grub_efi_boot_services_t *b; ++ grub_efi_status_t status; ++ grub_efi_loaded_image_t *loaded_image; ++ int len; ++ ++ mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t)); ++ if (!mempath) ++ return grub_errno; ++ ++ mempath[0].header.type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE; ++ mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE; ++ mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath)); ++ mempath[0].memory_type = GRUB_EFI_LOADER_DATA; ++ mempath[0].start_address = addr; ++ mempath[0].end_address = addr + size; ++ ++ mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE; ++ mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ++ mempath[1].header.length = sizeof (grub_efi_device_path_t); ++ ++ b = grub_efi_system_table->boot_services; ++ status = b->load_image (0, grub_efi_image_handle, ++ (grub_efi_device_path_t *) mempath, ++ (void *) addr, size, &image_handle); ++ if (status != GRUB_EFI_SUCCESS) ++ return grub_error (GRUB_ERR_BAD_OS, "cannot load image"); ++ ++ grub_dprintf ("linux", "linux command line: '%s'\n", args); ++ ++ /* Convert command line to UCS-2 */ ++ loaded_image = grub_efi_get_loaded_image (image_handle); ++ loaded_image->load_options_size = len = ++ (grub_strlen (args) + 1) * sizeof (grub_efi_char16_t); ++ loaded_image->load_options = ++ grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size)); ++ if (!loaded_image->load_options) ++ return grub_errno; ++ ++ loaded_image->load_options_size = ++ 2 * grub_utf8_to_utf16 (loaded_image->load_options, len, ++ (grub_uint8_t *) args, len, NULL); ++ ++ grub_dprintf ("linux", "starting image %p\n", image_handle); ++ status = b->start_image (image_handle, 0, NULL); ++ ++ /* When successful, not reached */ ++ b->unload_image (image_handle); ++ grub_efi_free_pages ((grub_addr_t) loaded_image->load_options, ++ GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size)); ++ ++ return grub_errno; ++} +diff --git a/grub-core/loader/loongarch64/linux-elf.c b/grub-core/loader/loongarch64/linux-elf.c +new file mode 100644 +index 0000000..d54028e +--- /dev/null ++++ b/grub-core/loader/loongarch64/linux-elf.c +@@ -0,0 +1,910 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2021 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define GRUB_EFI_MMAP_NR_SLACK_SLOTS 8 ++ ++#define GRUB_ADDRESS_TYPE_SYSRAM 1 ++#define GRUB_ADDRESS_TYPE_RESERVED 2 ++#define GRUB_ADDRESS_TYPE_ACPI 3 ++#define GRUB_ADDRESS_TYPE_NVS 4 ++#define GRUB_ADDRESS_TYPE_PMEM 5 ++ ++#define GRUB_EFI_LOONGSON_BPI_TABLE_GUID \ ++ { 0x4660f721, 0x2ec5, 0x416a, \ ++ { 0x89, 0x9a, 0x43, 0x18, 0x02, 0x50, 0xa0, 0xc9 } \ ++ } ++ ++#define GRUB_EFI_LARCH_SCREEN_INFO_GUID \ ++ { 0x07fd51a6, 0X9532, 0X926f, \ ++ { 0X51, 0Xdc, 0X6a, 0X63, 0X60, 0X2f, 0X84, 0Xb4 } \ ++ } ++ ++#define GRUB_EFI_SCREEN_INFO_GUID \ ++ { 0xe03fc20a, 0x85dc, 0x406e, \ ++ { 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95 } \ ++ } ++ ++static struct grub_relocator *relocator; ++static grub_efi_guid_t compat_screen_info_guid = GRUB_EFI_LARCH_SCREEN_INFO_GUID; ++static grub_efi_guid_t screen_info_guid = GRUB_EFI_SCREEN_INFO_GUID; ++ ++void grub_linux_loongarch_elf_relocator_unload (void) ++{ ++ grub_relocator_unload (relocator); ++} ++ ++static void find_bits(unsigned long mask, grub_efi_uint8_t *pos, grub_efi_uint8_t *size) ++{ ++ grub_efi_uint8_t first, len; ++ ++ first = 0; ++ len = 0; ++ ++ if (mask) { ++ while (!(mask & 0x1)) { ++ mask = mask >> 1; ++ first++; ++ } ++ ++ while (mask & 0x1) { ++ mask = mask >> 1; ++ len++; ++ } ++ } ++ ++ *pos = first; ++ *size = len; ++} ++ ++static void ++setup_pixel_info(struct screen_info *si, grub_efi_uint32_t pixels_per_scan_line, ++ struct grub_efi_gop_pixel_bitmask pixel_info, int pixel_format) ++{ ++ if (pixel_format == GRUB_EFI_GOT_RGBA8) { ++ si->lfb_depth = 32; ++ si->lfb_linelength = pixels_per_scan_line * 4; ++ si->red_size = 8; ++ si->red_pos = 0; ++ si->green_size = 8; ++ si->green_pos = 8; ++ si->blue_size = 8; ++ si->blue_pos = 16; ++ si->rsvd_size = 8; ++ si->rsvd_pos = 24; ++ } else if (pixel_format == GRUB_EFI_GOT_BGRA8) { ++ si->lfb_depth = 32; ++ si->lfb_linelength = pixels_per_scan_line * 4; ++ si->red_size = 8; ++ si->red_pos = 16; ++ si->green_size = 8; ++ si->green_pos = 8; ++ si->blue_size = 8; ++ si->blue_pos = 0; ++ si->rsvd_size = 8; ++ si->rsvd_pos = 24; ++ } else if (pixel_format == GRUB_EFI_GOT_BITMASK) { ++ find_bits(pixel_info.r, &si->red_pos, &si->red_size); ++ find_bits(pixel_info.g, &si->green_pos, ++ &si->green_size); ++ find_bits(pixel_info.b, &si->blue_pos, &si->blue_size); ++ find_bits(pixel_info.a, &si->rsvd_pos, ++ &si->rsvd_size); ++ si->lfb_depth = si->red_size + si->green_size + ++ si->blue_size + si->rsvd_size; ++ si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8; ++ } else { ++ si->lfb_depth = 4; ++ si->lfb_linelength = si->lfb_width / 2; ++ si->red_size = 0; ++ si->red_pos = 0; ++ si->green_size = 0; ++ si->green_pos = 0; ++ si->blue_size = 0; ++ si->blue_pos = 0; ++ si->rsvd_size = 0; ++ si->rsvd_pos = 0; ++ } ++} ++ ++static struct screen_info *alloc_screen_info(void) ++{ ++ grub_efi_status_t status; ++ grub_efi_boot_services_t *b; ++ struct screen_info *si; ++ ++ b = grub_efi_system_table->boot_services; ++ status = efi_call_3 (b->allocate_pool, GRUB_EFI_RUNTIME_SERVICES_DATA, ++ sizeof(*si), (void**)&si); ++ if (status != GRUB_EFI_SUCCESS) ++ return NULL; ++ ++ grub_memset ((void *)si, 0, sizeof(struct screen_info)); ++ ++ status = b->install_configuration_table (&compat_screen_info_guid, si); ++ if (status != GRUB_EFI_SUCCESS) ++ goto free_mem; ++ ++ status = b->install_configuration_table (&screen_info_guid, si); ++ if (status == GRUB_EFI_SUCCESS) { ++ return si; ++ } ++ ++free_table: ++ b->install_configuration_table (&compat_screen_info_guid, NULL); ++free_mem: ++ efi_call_1 (b->free_pool, si); ++ ++ return NULL; ++} ++ ++static struct screen_info *setup_screen_info(void) ++{ ++ grub_efi_boot_services_t *b; ++ grub_efi_handle_t gop_handle; ++ struct screen_info *si = NULL; ++ struct grub_efi_gop *gop, *first_gop; ++ grub_efi_handle_t *handles; ++ grub_efi_uintn_t num_handles, i; ++ grub_efi_guid_t graphics_output_guid = GRUB_EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; ++ grub_efi_uint16_t width, height; ++ grub_efi_uint32_t ext_lfb_base, pixels_per_scan_line; ++ grub_efi_uint64_t fb_base; ++ struct grub_efi_gop_pixel_bitmask pixel_info; ++ grub_efi_gop_pixel_format_t pixel_format; ++ ++ si = alloc_screen_info(); ++ if (!si) ++ return NULL; ++ ++ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, ++ &graphics_output_guid, NULL, &num_handles); ++ if (!handles || num_handles == 0) ++ goto free_screen_info; ++ ++ gop = NULL; ++ first_gop = NULL; ++ ++ for (i = 0; i < num_handles; i++) ++ { ++ struct grub_efi_gop_mode *mode; ++ struct grub_efi_gop_mode_info *info = NULL; ++ grub_efi_guid_t conout_proto = GRUB_EFI_CONSOLE_OUT_DEVICE_GUID; ++ void *dummy = NULL; ++ grub_efi_uint8_t conout_found = 0; ++ grub_efi_uint64_t current_fb_base; ++ ++ gop_handle = handles[i]; ++ gop = grub_efi_open_protocol (gop_handle, &graphics_output_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ ++ dummy = grub_efi_open_protocol (gop_handle, &conout_proto, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ if (dummy != NULL) ++ conout_found = 1; ++ ++ mode = gop->mode; ++ info = mode->info; ++ current_fb_base = mode->fb_base; ++ ++ if ((!first_gop || conout_found) && ++ info->pixel_format != GRUB_EFI_GOT_BLT_ONLY) { ++ /* ++ * Systems that use the UEFI Console Splitter may ++ * provide multiple GOP devices, not all of which are ++ * backed by real hardware. The workaround is to search ++ * for a GOP implementing the ConOut protocol, and if ++ * one isn't found, to just fall back to the first GOP. ++ */ ++ width = info->width; ++ height = info->height; ++ pixel_format = info->pixel_format; ++ pixel_info = info->pixel_bitmask; ++ pixels_per_scan_line = info->pixels_per_scanline; ++ fb_base = current_fb_base; ++ ++ /* ++ * Once we've found a GOP supporting ConOut, ++ * don't bother looking any further. ++ */ ++ first_gop = gop; ++ if (conout_found) ++ break; ++ } ++ } ++ ++ /* Did we find any GOPs? */ ++ if (!first_gop) ++ goto free_screen_info; ++ ++ /* EFI framebuffer */ ++ si->orig_video_isVGA = GRUB_VIDEO_TYPE_EFI; ++ ++ si->lfb_width = width; ++ si->lfb_height = height; ++ si->lfb_base = fb_base; ++ grub_dprintf ("loongson", "Screen info fb base: 0x%"PRIxGRUB_UINT32_T"\n", si->lfb_base); ++ ++ ext_lfb_base = (grub_uint64_t)fb_base >> 32; ++ if (ext_lfb_base) { ++ si->capabilities |= GRUB_VIDEO_CAPABILITY_64BIT_BASE; ++ si->ext_lfb_base = ext_lfb_base; ++ } ++ si->pages = 1; ++ ++ setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format); ++ ++ si->lfb_size = si->lfb_linelength * si->lfb_height; ++ si->capabilities |= GRUB_VIDEO_CAPABILITY_SKIP_QUIRKS; ++ ++ return si; ++ ++free_screen_info: ++ b = grub_efi_system_table->boot_services; ++ b->install_configuration_table (&compat_screen_info_guid, NULL); ++ b->install_configuration_table (&screen_info_guid, NULL); ++ if (si) ++ efi_call_1 (b->free_pool, si); ++ ++ grub_dprintf ("loongson", "No screen info\n"); ++ return NULL; ++} ++ ++static grub_err_t ++allocate_memmap_and_exit_boot (struct linux_loongarch64_kernel_params *kernel_params) ++{ ++ grub_err_t err; ++ grub_efi_status_t status; ++ grub_efi_uintn_t mmap_size, desc_size, size; ++ grub_efi_uint32_t desc_version; ++ grub_efi_memory_descriptor_t *mmap_buf; ++ grub_efi_boot_services_t *b; ++ struct efi_boot_memmap *m, tmp; ++ struct efi_initrd *tbl = NULL; ++ grub_efi_guid_t boot_memmap_guid = GRUB_EFI_BOOT_MEMMAP_GUID; ++ grub_efi_guid_t initrd_media_guid = GRUB_EFI_INITRD_MEDIA_GUID; ++ ++ setup_screen_info(); ++ ++ b = grub_efi_system_table->boot_services; ++ ++ grub_dprintf ("loongson", "ramdisk_addr:0x%"PRIxGRUB_UINT64_T", \ ++ size:0x%"PRIxGRUB_UINT64_T"\n", ++ kernel_params->ramdisk_addr, ++ kernel_params->ramdisk_size); ++#if 0 ++ char string[64]; ++ ++ /* Set initrd info to cmdline*/ ++ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) ++ { ++ grub_printf ( "Initrd @ %p-%p\n", ++ (void *) kernel_params->ramdisk_addr, ++ (void *) (kernel_params->ramdisk_addr + kernel_params->ramdisk_size)); ++ /* initrd */ ++ grub_snprintf (string, ++ sizeof (GRUB_INITRD_STRING), ++ "initrd=0x%lx,0x%lx", ++ ((grub_uint64_t) kernel_params->ramdisk_addr & 0xffffffff), ++ (grub_uint64_t) kernel_params->ramdisk_size); ++ *(char*) ((grub_addr_t) kernel_params->linux_args + kernel_params->ramdisk_args_len - 2) = ' '; ++ grub_memcpy ((char*) ((grub_addr_t) kernel_params->linux_args + kernel_params->ramdisk_args_len - 1), ++ string, sizeof (GRUB_INITRD_STRING)); ++ } ++#else ++ /* Set initrd info to system table*/ ++ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) ++ { ++ tbl = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (sizeof(struct efi_initrd))); ++ if (!tbl) ++ return grub_error (GRUB_ERR_IO, "cannot allocate tbl memory"); ++ tbl->base = kernel_params->ramdisk_addr; ++ tbl->size = kernel_params->ramdisk_size; ++ ++ status = b->install_configuration_table (&initrd_media_guid, tbl); ++ if (status != GRUB_EFI_SUCCESS) { ++ grub_error (GRUB_ERR_IO, "failed to install initrd media"); ++ goto free_tbl; ++ } ++ } ++#endif ++ ++ tmp.map_size = 0; ++ status = grub_efi_get_memory_map (&tmp.map_size, NULL, &tmp.map_key, ++ &tmp.desc_size, &tmp.desc_ver); ++ if (status != 0) { ++ grub_error (GRUB_ERR_IO, "cannot get memory map"); ++ goto uninstall_initrd_table; ++ } ++ size = tmp.map_size + tmp.desc_size * GRUB_EFI_MMAP_NR_SLACK_SLOTS; ++ m = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (sizeof(*m) + size)); ++ if (!m) { ++ grub_error (GRUB_ERR_IO, "cannot allocate m memory"); ++ goto uninstall_initrd_table; ++ } ++ ++ status = b->install_configuration_table (&boot_memmap_guid, m); ++ if (status != GRUB_EFI_SUCCESS) { ++ grub_error (GRUB_ERR_IO, "failed to install boot memmap"); ++ goto free_m; ++ } ++ ++ m->buff_size = m->map_size = size; ++ if (grub_efi_get_memory_map (&m->map_size, m->map, ++ &m->map_key, &m->desc_size, ++ &m->desc_ver) <= 0) ++ { ++ grub_error (GRUB_ERR_IO, "cannot get EFI memory map"); ++ goto uninstall_mem_table; ++ } ++ ++ mmap_size = grub_efi_find_mmap_size (); ++ if (! mmap_size) ++ goto uninstall_mem_table; ++ ++ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); ++ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, ++ &desc_size, &desc_version); ++ if (err) { ++ grub_error (GRUB_ERR_IO, "failed to finish boot services"); ++ goto free_map; ++ } ++ ++ return 0; ++ ++free_map: ++ if (mmap_buf) ++ grub_efi_free_pages ((grub_addr_t) mmap_buf, ++ GRUB_EFI_BYTES_TO_PAGES (mmap_size)); ++ ++uninstall_mem_table: ++ b->install_configuration_table (&boot_memmap_guid, NULL); ++ ++free_m: ++ if (m) ++ grub_efi_free_pages ((grub_addr_t) m, ++ GRUB_EFI_BYTES_TO_PAGES (sizeof(*m) + size)); ++ ++uninstall_initrd_table: ++ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) ++ b->install_configuration_table (&initrd_media_guid, NULL); ++ ++free_tbl: ++ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) { ++ if (tbl) ++ grub_efi_free_pages ((grub_addr_t) tbl, ++ GRUB_EFI_BYTES_TO_PAGES (sizeof(struct efi_initrd))); ++ } ++ ++ return grub_error(GRUB_ERR_BAD_OS, "failed to V40 boot"); ++} ++ ++static grub_err_t ++allocate_fdt_and_exit_boot (struct linux_loongarch64_kernel_params *kernel_params) ++{ ++ int node, retval; ++ grub_err_t err; ++ unsigned int size; ++ grub_efi_uintn_t mmap_size; ++ grub_efi_uintn_t desc_size; ++ grub_efi_uint32_t desc_version; ++ grub_efi_memory_descriptor_t *mmap_buf; ++ ++ size = GRUB_FDT_EMPTY_TREE_SZ + FDT_ADDR_SIZE_EXTRA + GRUB_EFI_LINUX_FDT_EXTRA_SPACE; ++ ++ kernel_params->fdt = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (size)); ++ if (!kernel_params->fdt) ++ return GRUB_ERR_OUT_OF_MEMORY; ++ ++ grub_fdt_create_empty_tree (kernel_params->fdt, size); ++ grub_fdt_set_prop32 (kernel_params->fdt, 0, FDT_ADDR_CELLS_STRING, 2); ++ grub_fdt_set_prop32 (kernel_params->fdt, 0, FDT_SIZE_CELLS_STRING, 2); ++ ++ node = grub_fdt_find_subnode (kernel_params->fdt, 0, "chosen"); ++ if (node < 0) ++ node = grub_fdt_add_subnode (kernel_params->fdt, 0, "chosen"); ++ if (node < 1) ++ goto failure; ++ ++ grub_dprintf ("loongson", "command_line %s, len %ld\n", (char *)kernel_params->linux_args, ++ grub_strlen(kernel_params->linux_args) + 1); ++ if ((kernel_params->linux_args != NULL) && (grub_strlen(kernel_params->linux_args) > 0)) { ++ retval = grub_fdt_set_prop (kernel_params->fdt, node, "bootargs", kernel_params->linux_args, ++ grub_strlen(kernel_params->linux_args) + 1); ++ if (retval) ++ goto failure; ++ } ++ ++ /* Set initrd info */ ++ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) ++ { ++ grub_dprintf ("linux", "Initrd @ %p-%p\n", ++ (void *) kernel_params->ramdisk_addr, ++ (void *) (kernel_params->ramdisk_addr + kernel_params->ramdisk_size)); ++ ++ retval = grub_fdt_set_prop64 (kernel_params->fdt, node, "linux,initrd-start", ++ kernel_params->ramdisk_addr); ++ if (retval) ++ goto failure; ++ retval = grub_fdt_set_prop64 (kernel_params->fdt, node, "linux,initrd-end", ++ (kernel_params->ramdisk_addr + kernel_params->ramdisk_size)); ++ if (retval) ++ goto failure; ++ } ++ ++ node = grub_fdt_find_subnode (kernel_params->fdt, 0, "chosen"); ++ retval = grub_fdt_set_prop64 (kernel_params->fdt, node, "linux,uefi-system-table", ++ (grub_uint64_t)grub_efi_system_table); ++ if (retval) ++ goto failure; ++ ++ mmap_size = grub_efi_find_mmap_size (); ++ if (! mmap_size) ++ return grub_errno; ++ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); ++ if (! mmap_buf) ++ return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); ++ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, ++ &desc_size, &desc_version); ++ if (err) ++ return err; ++ ++ if (!mmap_buf || !mmap_size || !desc_size) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ retval = grub_fdt_set_prop64 (kernel_params->fdt, node, "linux,uefi-mmap-start", ++ (grub_uint64_t)mmap_buf); ++ if (retval) ++ goto failure; ++ ++ retval = grub_fdt_set_prop32 (kernel_params->fdt, node, "linux,uefi-mmap-size", ++ mmap_size); ++ if (retval) ++ goto failure; ++ ++ retval = grub_fdt_set_prop32 (kernel_params->fdt, node, "linux,uefi-mmap-desc-size", ++ desc_size); ++ if (retval) ++ goto failure; ++ ++ retval = grub_fdt_set_prop32 (kernel_params->fdt, node, "linux,uefi-mmap-desc-ver", ++ desc_version); ++ if (retval) ++ goto failure; ++ ++ return GRUB_ERR_NONE; ++ ++failure: ++ if (!kernel_params->fdt) { ++ return GRUB_ERR_BAD_OS; ++ } ++ grub_efi_free_pages ((grub_addr_t) kernel_params->fdt, ++ GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (kernel_params->fdt))); ++ kernel_params->fdt = NULL; ++ return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); ++} ++ ++static void ++grub_linux_loongarch_elf_make_argv (struct linux_loongarch64_kernel_params *kernel_params) ++{ ++ static void* linux_args_addr; ++ int size; ++ grub_uint64_t *linux_argv; ++ char *args, *p, *linux_args; ++ int i, argc; ++ grub_err_t err; ++ ++ argc = kernel_params->linux_argc; ++ args = kernel_params->linux_args; ++ ++ /* new size */ ++ p = args; ++ size = (argc + 3 + 1) * sizeof (grub_uint64_t); /* orig arguments */ ++ for (i = 0; i < argc; i++) ++ { ++ size += ALIGN_UP (grub_strlen (p) + 1, 4); ++ p += grub_strlen (p) + 1; ++ } ++ ++ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) ++ { ++ size += ALIGN_UP (sizeof (GRUB_RD_START_STRING), 4) \ ++ + ALIGN_UP (sizeof (GRUB_RD_SIZE_STRING), 4) \ ++ + ALIGN_UP (sizeof (GRUB_INITRD_STRING), 4); ++ } ++ size = ALIGN_UP (size, 8); ++ ++ /* alloc memory */ ++ linux_args_addr = grub_linux_loongarch_alloc_virtual_mem_align (size, 8, &err); ++ ++ linux_argv = linux_args_addr; ++ linux_args = (char *)(linux_argv + (argc + 1 + 3)); ++ p = args; ++ for (i = 0; i < argc; i++) ++ { ++ grub_memcpy (linux_args, p, grub_strlen (p) + 1); ++ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; ++ linux_argv++; ++ linux_args += ALIGN_UP (grub_strlen (p) + 1, 4); ++ p += grub_strlen (p) + 1; ++ } ++ ++ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) ++ { ++ /* rd_start */ ++ grub_snprintf (linux_args, ++ sizeof (GRUB_RD_START_STRING), ++ "rd_start=0x%lx", ++ (grub_uint64_t) kernel_params->ramdisk_addr); ++ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; ++ linux_argv++; ++ linux_args += ALIGN_UP (sizeof (GRUB_RD_START_STRING), 4); ++ kernel_params->linux_argc++; ++ ++ /* rd_size */ ++ grub_snprintf (linux_args, ++ sizeof (GRUB_RD_SIZE_STRING), ++ "rd_size=0x%lx", ++ (grub_uint64_t) kernel_params->ramdisk_size); ++ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; ++ linux_argv++; ++ linux_args += ALIGN_UP (sizeof (GRUB_RD_SIZE_STRING), 4); ++ kernel_params->linux_argc++; ++ ++ /* initrd */ ++ grub_snprintf (linux_args, ++ sizeof (GRUB_INITRD_STRING), ++ "initrd=0x%lx,0x%lx", ++ ((grub_uint64_t) kernel_params->ramdisk_addr & 0xffffffff), ++ (grub_uint64_t) kernel_params->ramdisk_size); ++ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; ++ linux_argv++; ++ linux_args += ALIGN_UP (sizeof (GRUB_INITRD_STRING), 4); ++ kernel_params->linux_argc++; ++ } ++ ++ /* Reserve space for initrd arguments. */ ++ *linux_argv = 0; ++ ++ grub_free (kernel_params->linux_args); ++ kernel_params->linux_argv = (grub_addr_t) linux_args_addr; ++} ++ ++grub_err_t ++grub_linux_loongarch_elf_linux_boot_image (struct linux_loongarch64_kernel_params ++ *kernel_params) ++{ ++ struct boot_params_interface *boot_params = NULL; ++ struct grub_relocator64_state state; ++ grub_err_t err; ++ ++ /* linux kernel type is ELF */ ++ grub_memset (&state, 0, sizeof (state)); ++ ++ state.jumpreg = 1; ++ state.gpr[1] = kernel_params->kernel_addr; /* ra */ ++ if (grub_linux_loongarch_elf_get_boot_params (&boot_params) == 0) ++ { ++ grub_dprintf ("loongson", "V40 boot\n"); ++ if (allocate_memmap_and_exit_boot(kernel_params) != GRUB_ERR_NONE) ++ return grub_errno; ++ state.gpr[4] = 1 << FLAGS_EFI_SUPPORT_BIT; /* a0 = flag */ ++ state.gpr[5] = (grub_uint64_t)kernel_params->linux_args; /* a1 = cmdline */ ++ state.gpr[6] = (grub_uint64_t)grub_efi_system_table; /* a2 = system_table */ ++ } else { ++ grub_dprintf ("loongson", "BPI boot\n"); ++ grub_linux_loongarch_elf_make_argv (kernel_params); ++ state.gpr[4] = kernel_params->linux_argc; /* a0 = argc */ ++ state.gpr[5] = kernel_params->linux_argv; /* a1 = args */ ++ state.gpr[6] = (grub_uint64_t) boot_params; /* a2 = envp */ ++ err = grub_linux_loongarch_elf_boot_params (boot_params); ++ if (err) ++ return err; ++ } ++ ++ /* Boot the ELF kernel */ ++ grub_relocator64_boot (relocator, state); ++ ++ return GRUB_ERR_NONE; ++} ++ ++void* ++grub_linux_loongarch_alloc_virtual_mem_addr (grub_addr_t addr, ++ grub_size_t size, ++ grub_err_t *err) ++{ ++ relocator = grub_relocator_new (); ++ if (!relocator) ++ return NULL; ++ ++ grub_relocator_chunk_t ch; ++ *err = grub_relocator_alloc_chunk_addr (relocator, &ch, ++ grub_vtop ((void *) addr), ++ size); ++ if (*err) ++ return NULL; ++ return get_virtual_current_address (ch); ++} ++ ++void* ++grub_linux_loongarch_alloc_virtual_mem_align (grub_size_t size, ++ grub_size_t align, ++ grub_err_t *err) ++{ ++ grub_relocator_chunk_t ch; ++ ++ *err = grub_relocator_alloc_chunk_align (relocator, &ch, ++ 0x3000000, (0xffffffff - size) + 1, ++ size, align, ++ GRUB_RELOCATOR_PREFERENCE_LOW, 0); ++ return get_virtual_current_address (ch); ++} ++ ++void* ++grub_linux_loongarch_alloc_initrd_mem_align (grub_size_t size, ++ grub_size_t align, ++ grub_err_t *err) ++{ ++ grub_relocator_chunk_t ch; ++ ++ /* Firstly try to allocate from memory higher than 256MB */ ++ *err = grub_relocator_alloc_chunk_align (relocator, &ch, ++ 0x10000000, (0xffffffff - size) + 1, size, align, ++ GRUB_RELOCATOR_PREFERENCE_LOW, 0); ++ if (*err != GRUB_ERR_NONE) ++ { ++ /* Failed, try to allocate in range 0 ~ 256MB */ ++ *err = grub_relocator_alloc_chunk_align (relocator, &ch, ++ 0, (0xfffffff - size) + 1, size, align, ++ GRUB_RELOCATOR_PREFERENCE_HIGH, 0); ++ } ++ return get_virtual_current_address (ch); ++} ++ ++int ++grub_linux_loongarch_elf_get_boot_params (struct boot_params_interface **boot_params) ++{ ++ grub_efi_configuration_table_t *tables; ++ grub_efi_guid_t bpi_guid = GRUB_EFI_LOONGSON_BPI_TABLE_GUID; ++ unsigned int i; ++ int found = 0; ++ ++ /* Look for Loongson BPI in UEFI config tables. */ ++ tables = grub_efi_system_table->configuration_table; ++ ++ for (i = 0; i < grub_efi_system_table->num_table_entries; i++) ++ if (grub_memcmp (&tables[i].vendor_guid, &bpi_guid, sizeof (bpi_guid)) == 0) ++ { ++ *boot_params = tables[i].vendor_table; ++ char *p = (char*) &((*boot_params)->signature); ++ if (grub_strncmp (p, "BPI", 3) == 0) ++ { ++ found = 1; ++ break; ++ } ++ } ++ return found; ++} ++ ++static grub_uint8_t ++grub_kernel_update_checksum (const grub_uint8_t *buffer, grub_efi_uintn_t length) ++{ ++ grub_uint8_t sum; ++ grub_efi_uintn_t count; ++ ++ for (sum = 0, count = 0; count < length; count++) ++ { ++ sum = (grub_uint8_t) (sum + *(buffer + count)); ++ } ++ ++ return (grub_uint8_t) (0x100 - sum); ++} ++ ++static grub_uint32_t ++grub_efi_loongarch64_memmap_sort (struct memmap array[], ++ grub_uint32_t length, ++ struct loongsonlist_mem_map* bpmem, ++ grub_uint32_t index, ++ grub_uint32_t memtype) ++{ ++ grub_uint64_t tempmemsize = 0; ++ grub_uint32_t j = 0; ++ grub_uint32_t t = 0; ++ ++ for(j = 0; j < length;) ++ { ++ tempmemsize = array[j].mem_size; ++ for(t = j + 1; t < length; t++) ++ { ++ if(array[j].mem_start + tempmemsize == array[t].mem_start) ++ { ++ tempmemsize += array[t].mem_size; ++ } ++ else ++ { ++ break; ++ } ++ } ++ bpmem->map[index].mem_type = memtype; ++ bpmem->map[index].mem_start = array[j].mem_start; ++ bpmem->map[index].mem_size = tempmemsize; ++ grub_dprintf ("loongson", "map[%d]:type %"PRIuGRUB_UINT32_T", start 0x%" ++ PRIxGRUB_UINT64_T", end 0x%"PRIxGRUB_UINT64_T"\n", ++ index, ++ bpmem->map[index].mem_type, ++ bpmem->map[index].mem_start, ++ bpmem->map[index].mem_start+ bpmem->map[index].mem_size ++ ); ++ j = t; ++ index++; ++ } ++ return index; ++} ++ ++grub_err_t ++grub_linux_loongarch_elf_boot_params (struct boot_params_interface *boot_params) ++{ ++ grub_int8_t checksum = 0; ++ grub_err_t err; ++ ++ struct loongsonlist_mem_map *loongson_mem_map = NULL; ++ struct _extention_list_hdr * listpointer = NULL; ++ grub_uint32_t tmp_index = 0; ++ grub_efi_memory_descriptor_t * lsdesc = NULL; ++ ++ grub_uint32_t free_index = 0; ++ grub_uint32_t reserve_index = 0; ++ grub_uint32_t acpi_table_index = 0; ++ grub_uint32_t acpi_nvs_index = 0; ++ ++ grub_efi_uintn_t mmap_size; ++ grub_efi_uintn_t desc_size; ++ grub_efi_memory_descriptor_t *mmap_buf; ++ ++ struct memmap reserve_mem[GRUB_LOONGSON3_BOOT_MEM_MAP_MAX]; ++ struct memmap free_mem[GRUB_LOONGSON3_BOOT_MEM_MAP_MAX]; ++ struct memmap acpi_table_mem[GRUB_LOONGSON3_BOOT_MEM_MAP_MAX]; ++ struct memmap acpi_nvs_mem[GRUB_LOONGSON3_BOOT_MEM_MAP_MAX]; ++ ++ grub_memset (reserve_mem, 0, sizeof(struct memmap) * GRUB_LOONGSON3_BOOT_MEM_MAP_MAX); ++ grub_memset (free_mem, 0, sizeof(struct memmap) * GRUB_LOONGSON3_BOOT_MEM_MAP_MAX); ++ grub_memset (acpi_table_mem, 0, sizeof(struct memmap) * GRUB_LOONGSON3_BOOT_MEM_MAP_MAX); ++ grub_memset (acpi_nvs_mem, 0, sizeof(struct memmap) * GRUB_LOONGSON3_BOOT_MEM_MAP_MAX); ++ ++ /* Check extlist headers */ ++ listpointer = boot_params->extlist; ++ for( ;listpointer != NULL; listpointer = listpointer->next) ++ { ++ char *pl= (char *)&(listpointer->signature); ++ if(grub_strncmp(pl, "MEM", 3) == 0) ++ { ++ loongson_mem_map = (struct loongsonlist_mem_map *)listpointer; ++ break; ++ } ++ } ++ ++ mmap_size = grub_efi_find_mmap_size (); ++ if (! mmap_size) ++ return grub_errno; ++ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); ++ if (! mmap_buf) ++ return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); ++ ++ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, ++ &desc_size, NULL); ++ if (err) ++ return err; ++ ++ if (!mmap_buf || !mmap_size || !desc_size) ++ return -1; ++ ++ /* ++ According to UEFI SPEC,mmap_buf is the accurate Memory Map array \ ++ now we can fill platform specific memory structure. ++ */ ++ for (lsdesc = mmap_buf; lsdesc < (grub_efi_memory_descriptor_t *)((char *)mmap_buf + mmap_size); ++ lsdesc = (grub_efi_memory_descriptor_t *)((char *)lsdesc + desc_size)) ++ { ++ /* System RAM */ ++ if((lsdesc->type != GRUB_EFI_ACPI_RECLAIM_MEMORY) && \ ++ (lsdesc->type != GRUB_EFI_ACPI_MEMORY_NVS) && \ ++ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_DATA) && \ ++ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_CODE) && \ ++ (lsdesc->type != GRUB_EFI_RESERVED_MEMORY_TYPE) && \ ++ (lsdesc->type != GRUB_EFI_PAL_CODE)) ++ { ++ free_mem[free_index].mem_type = GRUB_ADDRESS_TYPE_SYSRAM; ++ free_mem[free_index].mem_start = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; ++ free_mem[free_index].mem_size = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; ++ free_index++; ++ ++ /*ACPI*/ ++ }else if((lsdesc->type == GRUB_EFI_ACPI_RECLAIM_MEMORY)){ ++ acpi_table_mem[acpi_table_index].mem_type = GRUB_ADDRESS_TYPE_ACPI; ++ acpi_table_mem[acpi_table_index].mem_start = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; ++ acpi_table_mem[acpi_table_index].mem_size = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; ++ acpi_table_index++; ++ }else if((lsdesc->type == GRUB_EFI_ACPI_MEMORY_NVS)){ ++ acpi_nvs_mem[acpi_nvs_index].mem_type = GRUB_ADDRESS_TYPE_NVS; ++ acpi_nvs_mem[acpi_nvs_index].mem_start = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; ++ acpi_nvs_mem[acpi_nvs_index].mem_size = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; ++ acpi_nvs_index++; ++ ++ /* Reserve */ ++ }else{ ++ reserve_mem[reserve_index].mem_type = GRUB_ADDRESS_TYPE_RESERVED; ++ reserve_mem[reserve_index].mem_start = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; ++ reserve_mem[reserve_index].mem_size = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; ++ reserve_index++; ++ } ++ } ++ ++ tmp_index = loongson_mem_map->map_count; ++ /*System RAM Sort*/ ++ tmp_index = grub_efi_loongarch64_memmap_sort(free_mem, ++ free_index, ++ loongson_mem_map, ++ tmp_index, ++ GRUB_ADDRESS_TYPE_SYSRAM); ++ /*ACPI Sort*/ ++ tmp_index = grub_efi_loongarch64_memmap_sort(acpi_table_mem, ++ acpi_table_index, ++ loongson_mem_map, ++ tmp_index, ++ GRUB_ADDRESS_TYPE_ACPI); ++ tmp_index = grub_efi_loongarch64_memmap_sort(acpi_nvs_mem, ++ acpi_nvs_index, ++ loongson_mem_map, ++ tmp_index, ++ GRUB_ADDRESS_TYPE_NVS); ++ ++ /*Reserve Sort*/ ++ { ++ grub_uint64_t loongarch_addr; ++ asm volatile ("csrrd %0, 0x181" : "=r" (loongarch_addr)); ++ if ((loongarch_addr & 0xff00000000000000) == 0x9000000000000000) ++ tmp_index = grub_efi_loongarch64_memmap_sort(reserve_mem, ++ reserve_index, ++ loongson_mem_map, ++ tmp_index, ++ GRUB_ADDRESS_TYPE_RESERVED); ++ else ++ tmp_index = grub_efi_loongarch64_memmap_sort(reserve_mem, ++ reserve_index, ++ loongson_mem_map, ++ tmp_index, ++ GRUB_ADDRESS_TYPE_RESERVED + 1); ++ } ++ loongson_mem_map->map_count = tmp_index; ++ loongson_mem_map->header.checksum = 0; ++ ++ checksum = grub_kernel_update_checksum ((grub_uint8_t *) loongson_mem_map, ++ loongson_mem_map->header.length); ++ loongson_mem_map->header.checksum = checksum; ++ ++ return grub_errno; ++} +diff --git a/grub-core/loader/loongarch64/linux.c b/grub-core/loader/loongarch64/linux.c +index 7594ca2..8dae4fe 100644 +--- a/grub-core/loader/loongarch64/linux.c ++++ b/grub-core/loader/loongarch64/linux.c +@@ -1,7 +1,6 @@ +-/* linux.c - boot Linux */ + /* + * GRUB -- GRand Unified Bootloader +- * Copyright (C) 2003,2004,2005,2007,2009,2010,2017 Free Software Foundation, Inc. ++ * Copyright (C) 2021 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -17,346 +16,76 @@ + * along with GRUB. If not, see . + */ + +-#include +-#include +-#include +-#include + #include +-#include +-#include + #include + #include +-#include +-#include +-#include +-#include + #include + #include + #include +-#include ++#include + #include + + GRUB_MOD_LICENSE ("GPLv3+"); + +-#pragma GCC diagnostic ignored "-Wcast-align" +- +-typedef unsigned long size_t; ++#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024) + +-#define FDT_ADDR_CELLS_STRING "#address-cells" +-#define FDT_SIZE_CELLS_STRING "#size-cells" +-#define FDT_ADDR_SIZE_EXTRA ((2 * grub_fdt_prop_entry_size (sizeof(grub_uint32_t))) + \ +- sizeof (FDT_ADDR_CELLS_STRING) + \ +- sizeof (FDT_SIZE_CELLS_STRING)) ++static struct linux_loongarch64_kernel_params kernel_params; + ++static grub_addr_t phys_addr; + static grub_dl_t my_mod; + static int loaded; +-static int initrd_loaded = 0; +-static grub_size_t linux_size; +- +-static struct grub_relocator *relocator; +-static grub_addr_t target_addr, entry_addr; +-static int linux_argc; +-static grub_uint8_t *linux_args_addr; +-static grub_off_t rd_addr_arg_off, rd_size_arg_off, initrd_addr_arg_off; +- +-static void *fdt; +-static int is_fdt_boot; +-static grub_addr_t initrd_start, initrd_end; +-static char *fdt_linux_args; ++static int is_bpi_boot; ++static int grub_loongarch_linux_type = GRUB_LOONGARCH_LINUX_BAD; + + static grub_err_t +-allocate_fdt_and_exit_boot (void) ++grub_linux_boot (void) + { +- int node, retval; +- grub_err_t err; +- unsigned int size; +- grub_efi_uintn_t mmap_size; +- grub_efi_uintn_t desc_size; +- grub_efi_uint32_t desc_version; +- grub_efi_memory_descriptor_t *mmap_buf; +- +- size = GRUB_FDT_EMPTY_TREE_SZ + FDT_ADDR_SIZE_EXTRA + GRUB_EFI_LINUX_FDT_EXTRA_SPACE; +- +- fdt = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (size)); +- if (!fdt) +- return GRUB_ERR_OUT_OF_MEMORY; +- +- grub_fdt_create_empty_tree (fdt, size); +- grub_fdt_set_prop32 (fdt, 0, FDT_ADDR_CELLS_STRING, 2); +- grub_fdt_set_prop32 (fdt, 0, FDT_SIZE_CELLS_STRING, 2); +- +- node = grub_fdt_find_subnode (fdt, 0, "chosen"); +- if (node < 0) +- node = grub_fdt_add_subnode (fdt, 0, "chosen"); +- if (node < 1) +- goto failure; +- +- grub_dprintf ("loongson", "command_line %s, len %ld\n", +- fdt_linux_args, grub_strlen(fdt_linux_args) + 1); +- if ((fdt_linux_args != NULL) && (grub_strlen(fdt_linux_args) > 0)) { +- retval = grub_fdt_set_prop (fdt, node, "bootargs", fdt_linux_args, +- grub_strlen(fdt_linux_args) + 1); +- if (retval) +- goto failure; +- } + +- /* Set initrd info */ +- if (initrd_start && initrd_end > initrd_start) +- { +- grub_dprintf ("linux", "Initrd @ %p-%p\n", +- (void *) initrd_start, (void *) initrd_end); +- +- retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start", +- initrd_start); +- if (retval) +- goto failure; +- retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end", +- initrd_end); +- if (retval) +- goto failure; ++ if (grub_loongarch_linux_type == GRUB_LOONGARCH_LINUX_EFI) { ++ if (finalize_efi_params_linux (&kernel_params) != GRUB_ERR_NONE) ++ return grub_errno; ++ return (grub_arch_efi_linux_boot_image((grub_addr_t) kernel_params.kernel_addr, ++ kernel_params.kernel_size, ++ kernel_params.linux_args)); + } +- +- node = grub_fdt_find_subnode (fdt, 0, "chosen"); +- retval = grub_fdt_set_prop64 (fdt, node, "linux,uefi-system-table", +- (grub_uint64_t)grub_efi_system_table); +- if (retval) +- goto failure; +- +- mmap_size = grub_efi_find_mmap_size (); +- if (! mmap_size) +- return grub_errno; +- mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); +- if (! mmap_buf) +- return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); +- err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, +- &desc_size, &desc_version); +- if (err) +- return err; +- +- if (!mmap_buf || !mmap_size || !desc_size) +- return GRUB_ERR_BAD_ARGUMENT; +- +- retval = grub_fdt_set_prop64 (fdt, node, "linux,uefi-mmap-start", +- (grub_uint64_t)mmap_buf); +- if (retval) +- goto failure; +- +- retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-size", +- mmap_size); +- if (retval) +- goto failure; +- +- retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-desc-size", +- desc_size); +- if (retval) +- goto failure; +- +- retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-desc-ver", +- desc_version); +- if (retval) +- goto failure; +- +- return GRUB_ERR_NONE; +- +-failure: +- if (!fdt) { +- return GRUB_ERR_BAD_OS; ++ if (grub_loongarch_linux_type == GRUB_LOONGARCH_LINUX_ELF) { ++ return grub_linux_loongarch_elf_linux_boot_image (&kernel_params); + } +- grub_efi_free_pages ((grub_addr_t) fdt, +- GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt))); +- fdt = NULL; +- return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); +-} +- +-static grub_err_t +-allocate_boot_params_and_exit_boot (void) +-{ +- grub_efi_uintn_t mmap_size; +- grub_efi_uintn_t desc_size; +- grub_efi_uint32_t desc_version; +- grub_efi_memory_descriptor_t *mmap_buf; +- grub_efi_memory_descriptor_t * lsdesc = NULL; +- grub_err_t err; +- struct boot_params_interface * boot_params; +- mem_map_v1 * mem_map_v1_table = NULL; +- unsigned long bpi_version = 0; +- grub_int8_t checksum = 0; +- grub_uint32_t tmp_index = 0; +- grub_uint32_t free_index = 0; +- grub_uint32_t reserve_index = 0; +- grub_uint32_t acpi_table_index = 0; +- grub_uint32_t acpi_nvs_index = 0; +- +- struct memmap_v1 reserve_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; +- struct memmap_v1 free_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; +- struct memmap_v1 acpi_table_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; +- struct memmap_v1 acpi_nvs_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; +- +- grub_memset(reserve_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); +- grub_memset(free_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); +- grub_memset(acpi_table_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); +- grub_memset(acpi_nvs_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); +- +- boot_params = (struct boot_params_interface *)grub_efi_loongson_get_boot_params(); +- +- ext_list * listpointer = NULL; +- /* Check extlist headers */ +- listpointer = boot_params->extlist; +- for( ;listpointer != NULL; listpointer = listpointer->next) +- { +- char *pl= (char *)&(listpointer->signature); +- if(grub_strncmp(pl, "MEM", 3) == 0) +- { +- mem_map_v1_table = (mem_map_v1 *)listpointer; +- break; +- } +- } +- +- mmap_size = grub_efi_find_mmap_size (); +- if (! mmap_size) +- return grub_errno; +- mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); +- if (! mmap_buf) +- return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); +- err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, +- &desc_size, &desc_version); +- if (err) +- return err; +- +- if (!mmap_buf || !mmap_size || !desc_size) +- return GRUB_ERR_BAD_ARGUMENT; +- +- char *p = (char *)&(boot_params->signature); +- bpi_version = grub_efi_get_bpi_version(p); +- grub_dprintf("loongson", "get bpi version:%ld\n", bpi_version); +- +- if (bpi_version <= GRUB_EFI_BPI_VER_V2) +- { +- /* +- According to UEFI SPEC,mmap_buf is the accurate Memory Map array \ +- now we can fill platform specific memory structure. +- */ +- for(lsdesc = mmap_buf; lsdesc < (grub_efi_memory_descriptor_t *)((char *)mmap_buf + mmap_size); +- lsdesc = (grub_efi_memory_descriptor_t *)((char *)lsdesc + desc_size)) +- { +- grub_dprintf("loongson", "type:%d, phy_start:0x%lx, phy_end:0x%lx\n", lsdesc->type, +- lsdesc->physical_start, lsdesc->physical_start + lsdesc->num_pages * GRUB_EFI_PAGE_SIZE); +- +- /* System RAM */ +- if ((lsdesc->type != GRUB_EFI_ACPI_RECLAIM_MEMORY) && \ +- (lsdesc->type != GRUB_EFI_ACPI_MEMORY_NVS) && \ +- (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_DATA) && \ +- (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_CODE) && \ +- (lsdesc->type != GRUB_EFI_RESERVED_MEMORY_TYPE) && \ +- (lsdesc->type != GRUB_EFI_PAL_CODE)) +- { +- free_mem_v1[free_index].memtype = GRUB_EFI_LOONGSON_SYSTEM_RAM; +- free_mem_v1[free_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; +- free_mem_v1[free_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; +- free_index++; +- +- /*ACPI*/ +- } else if ((lsdesc->type == GRUB_EFI_ACPI_RECLAIM_MEMORY)){ +- acpi_table_mem_v1[acpi_table_index].memtype = GRUB_EFI_LOONGSON_ACPI_TABLE; +- acpi_table_mem_v1[acpi_table_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; +- acpi_table_mem_v1[acpi_table_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; +- acpi_table_index++; +- } else if ((lsdesc->type == GRUB_EFI_ACPI_MEMORY_NVS)){ +- acpi_nvs_mem_v1[acpi_nvs_index].memtype = GRUB_EFI_LOONGSON_ACPI_NVS; +- acpi_nvs_mem_v1[acpi_nvs_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; +- acpi_nvs_mem_v1[acpi_nvs_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; +- acpi_nvs_index++; +- +- /* Reserve */ +- } else { +- reserve_mem_v1[reserve_index].memtype = GRUB_EFI_LOONGSON_MEMORY_RESERVED; +- reserve_mem_v1[reserve_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; +- reserve_mem_v1[reserve_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; +- reserve_index++; +- } +- } +- +- tmp_index = mem_map_v1_table->mapcount; +- /*System RAM Sort*/ +- tmp_index = grub_efi_loongson_memmap_v1_sort(free_mem_v1, free_index, mem_map_v1_table, +- tmp_index, GRUB_EFI_LOONGSON_SYSTEM_RAM); +- /*ACPI Sort*/ +- tmp_index = grub_efi_loongson_memmap_v1_sort(acpi_table_mem_v1, acpi_table_index, +- mem_map_v1_table, tmp_index, GRUB_EFI_LOONGSON_ACPI_TABLE); +- tmp_index = grub_efi_loongson_memmap_v1_sort(acpi_nvs_mem_v1, acpi_nvs_index, +- mem_map_v1_table, tmp_index, GRUB_EFI_LOONGSON_ACPI_NVS); +- /*Reserve Sort*/ +- { +- grub_uint64_t loongarch_addr; +- asm volatile ("csrrd %0, 0x181" : "=r" (loongarch_addr)); +- if ((loongarch_addr & 0xff00000000000000) == 0x9000000000000000) +- tmp_index = grub_efi_loongson_memmap_v1_sort(reserve_mem_v1, reserve_index, +- mem_map_v1_table, tmp_index, +- GRUB_EFI_LOONGSON_MEMORY_RESERVED); +- else +- tmp_index = grub_efi_loongson_memmap_v1_sort(reserve_mem_v1, reserve_index, +- mem_map_v1_table, tmp_index, +- GRUB_EFI_LOONGSON_MEMORY_RESERVED + 1); +- } +- mem_map_v1_table->mapcount = tmp_index; +- mem_map_v1_table->header.checksum = 0; +- +- checksum = grub_efi_loongson_grub_calculatechecksum8((grub_uint8_t *)mem_map_v1_table, +- mem_map_v1_table->header.length); +- mem_map_v1_table->header.checksum = checksum; +- } + + return GRUB_ERR_NONE; + } + + static grub_err_t +-grub_linux_boot (void) ++grub_linux_unload (void) + { +- struct grub_relocator64_state state; +- +- grub_memset (&state, 0, sizeof (state)); +- +- /* Boot the kernel. */ +- state.gpr[1] = entry_addr; +- grub_dprintf("loongson", "entry_addr is 0x%lx\n", state.gpr[1]); + +- if (is_fdt_boot == 1) +- { +- if (allocate_fdt_and_exit_boot () != GRUB_ERR_NONE) +- return grub_errno; ++ if (grub_loongarch_linux_type == GRUB_LOONGARCH_LINUX_EFI) { ++ if (kernel_params.ramdisk_addr) ++ grub_efi_free_pages ((grub_efi_physical_address_t) kernel_params.ramdisk_addr, ++ GRUB_EFI_BYTES_TO_PAGES (kernel_params.ramdisk_size)); ++ kernel_params.ramdisk_size = 0; + +- state.gpr[4] = 1 << FLAGS_EFI_SUPPORT_BIT; +- state.gpr[5] = (grub_uint64_t)fdt; +- state.gpr[6] = 0; +- } else { +- state.gpr[4] = linux_argc; +- state.gpr[5] = (grub_addr_t) linux_args_addr; +- state.gpr[6] = (grub_uint64_t)grub_efi_loongson_get_boot_params(); +- +- if (allocate_boot_params_and_exit_boot () != GRUB_ERR_NONE) +- return grub_errno; ++ if (kernel_params.kernel_addr) ++ grub_efi_free_pages ((grub_addr_t) kernel_params.kernel_addr, ++ GRUB_EFI_BYTES_TO_PAGES (kernel_params.kernel_size)); ++ kernel_params.kernel_addr = 0; + } +- grub_dprintf("loongson", "gpr[4]:%ld, gpr[5]:0x%lx, gpr[6]:0x%lx\n", +- state.gpr[4], state.gpr[5], state.gpr[6]); + +- state.jumpreg = 1; +- grub_relocator64_boot (relocator, state); +- +- return GRUB_ERR_NONE; +-} ++ if (grub_loongarch_linux_type == GRUB_LOONGARCH_LINUX_ELF) { ++ grub_free (kernel_params.linux_args); ++ kernel_params.linux_args = 0; ++ grub_linux_loongarch_elf_relocator_unload (); ++ } + +-static grub_err_t +-grub_linux_unload (void) +-{ +- grub_relocator_unload (relocator); + grub_dl_unref (my_mod); + loaded = 0; ++ grub_loongarch_linux_type = GRUB_LOONGARCH_LINUX_BAD; + + return GRUB_ERR_NONE; + } + +-static grub_err_t +-grub_linux_load64 (grub_elf_t elf, const char *filename) ++grub_err_t ++grub_linux_loongarch_elf_load_kernel (grub_elf_t elf, const char *filename) + { + Elf64_Addr base; + grub_err_t err; +@@ -365,16 +94,14 @@ grub_linux_load64 (grub_elf_t elf, const char *filename) + int flag; + + /* Linux's entry point incorrectly contains a virtual address. */ +- entry_addr = elf->ehdr.ehdr64.e_entry; +- grub_dprintf("loongson", "entry address = 0x%lx\n", entry_addr); ++ kernel_params.kernel_addr = elf->ehdr.ehdr64.e_entry; ++ kernel_params.kernel_size = grub_elf64_size (elf, &base, 0); + +- linux_size = grub_elf64_size (elf, &base, 0); +- grub_dprintf("loongson", "base = 0x%lx\n", base); +- +- if (linux_size == 0) ++ if (kernel_params.kernel_size == 0) + return grub_errno; +- target_addr = base; +- linux_size = ALIGN_UP (base + linux_size - base, 8); ++ ++ phys_addr = base; ++ kernel_params.kernel_size = ALIGN_UP (base + kernel_params.kernel_size - base, 8); + + asm volatile ("csrrd %0, 0x181" : "=r" (addr)); + if (addr & 0x1) { +@@ -382,157 +109,163 @@ grub_linux_load64 (grub_elf_t elf, const char *filename) + } else { + flag = GRUB_ELF_LOAD_FLAGS_30BITS; + base &= ~ELF64_LOADMASK; +- entry_addr &= ~ELF64_LOADMASK; ++ kernel_params.kernel_addr &= ~ELF64_LOADMASK; + } + +- relocator = grub_relocator_new (); +- if (!relocator) +- return grub_errno; +- +- { +- grub_relocator_chunk_t ch; +- err = grub_relocator_alloc_chunk_addr (relocator, &ch, +- grub_vtop ((void *) target_addr), +- linux_size); +- if (err) +- return err; +- playground = get_virtual_current_address (ch); +- } ++ playground = grub_linux_loongarch_alloc_virtual_mem_addr (phys_addr, ++ kernel_params.kernel_size, ++ &err); ++ if (playground == NULL) ++ return err; + + /* Now load the segments into the area we claimed. */ +- return grub_elf64_load (elf, filename, playground - base, flag, 0, 0); ++ return grub_elf64_load (elf, filename, playground - base, ++ flag, 0, 0); + } + + static grub_err_t + grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { +- grub_elf_t elf = 0; ++ grub_file_t file = 0; ++ struct linux_arch_kernel_header lh; ++ struct boot_params_interface *boot_params = NULL; ++ grub_elf_t elf = NULL; + grub_err_t err; +- int args_size = 0; ++ grub_size_t cmdline_size; ++ int i; + + grub_dl_ref (my_mod); + +- if (argc == 0) +- { +- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +- } +- +- elf = grub_elf_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL); +- if (! elf) +- return grub_errno; ++ /* Release the previously used memory. */ ++ grub_loader_unset (); + +- if (elf->ehdr.ehdr64.e_type != ET_EXEC) ++ if (argc == 0) + { +- grub_elf_close (elf); +- return grub_error (GRUB_ERR_UNKNOWN_OS, +- N_("this ELF file is not of the right type")); ++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ goto fail; + } + +- /* Release the previously used memory. */ +- grub_loader_unset (); +- loaded = 0; +- +- if (grub_elf_is_elf64 (elf)) +- err = grub_linux_load64 (elf, argv[0]); +- else +- err = grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic")); ++ file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL); ++ if (!file) ++ goto fail; + +- grub_elf_close (elf); ++ kernel_params.kernel_size = grub_file_size (file); ++ grub_dprintf ("linux", "kernel file size: %" PRIuGRUB_SIZE "\n", ++ kernel_params.kernel_size); + +- if (err) +- return err; ++ if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh)) ++ return grub_errno; + +- if (grub_efi_loongson_get_boot_params() == NULL) { +- grub_size_t cmdline_size; ++ if (grub_arch_efi_linux_check_image (&lh) == GRUB_ERR_NONE) { ++ grub_loongarch_linux_type = GRUB_LOONGARCH_LINUX_EFI; ++ } + +- is_fdt_boot = 1; +- cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); +- fdt_linux_args = grub_malloc (cmdline_size); +- if (!fdt_linux_args) ++ if (grub_loongarch_linux_type != GRUB_LOONGARCH_LINUX_EFI) { ++ elf = grub_elf_file (file, argv[0]); ++ if (elf != NULL) + { +- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); +- goto fail; ++ /* linux kernel type is ELF */ ++ grub_loongarch_linux_type = GRUB_LOONGARCH_LINUX_ELF; ++ if (elf->ehdr.ehdr64.e_type != ET_EXEC) ++ { ++ grub_error (GRUB_ERR_UNKNOWN_OS, ++ N_("this ELF file is not of the right type")); ++ goto fail; ++ } ++ if (elf->ehdr.ehdr64.e_machine != EM_LOONGARCH64) ++ { ++ grub_error (GRUB_ERR_BAD_OS, "invalid magic number"); ++ goto fail; ++ } ++ ++ if (grub_elf_is_elf64 (elf)) ++ { ++ err = grub_linux_loongarch_elf_load_kernel (elf, argv[0]); ++ if (err) ++ goto fail; ++ } else { ++ grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic")); ++ goto fail; ++ } ++ grub_dprintf ("linux", "kernel @ %p\n", (void*) elf->ehdr.ehdr64.e_entry); + } +- grub_memcpy (fdt_linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); +- err = grub_create_loader_cmdline (argc, argv, +- fdt_linux_args + sizeof (LINUX_IMAGE) - 1, +- cmdline_size, +- GRUB_VERIFY_KERNEL_CMDLINE); +- if (err) +- goto fail; +- grub_dprintf("loongson", "fdt linux args:%s\n", +- fdt_linux_args + sizeof (LINUX_IMAGE) - 1); +- + } else { +- int i; +- grub_uint64_t *linux_argv; +- char *linux_args; +- +- is_fdt_boot = 0; +- /* For arguments. */ +- linux_argc = argc; +- /* Main arguments. */ +- args_size = (linux_argc) * sizeof (grub_uint64_t); +- /* Initrd address/size and initrd */ +- args_size += 3 * sizeof (grub_uint64_t); +- /* NULL terminator. */ +- args_size += sizeof (grub_uint64_t); +- /* First argument is always "a0". */ +- args_size += ALIGN_UP (sizeof ("a0"), 4); +- /* Normal arguments. */ +- for (i = 1; i < argc; i++) +- args_size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); +- +- /* rd arguments. */ +- args_size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); +- args_size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); +- args_size += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); +- +- args_size = ALIGN_UP (args_size, 8); +- +- linux_args_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (args_size)); +- grub_dprintf ("linux", "linux args numpages: %lld\n", +- (long long) GRUB_EFI_BYTES_TO_PAGES (args_size)); +- if (!linux_args_addr) +- { +- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); +- goto fail; ++ if (grub_file_seek (file, 0) == (grub_off_t) -1) ++ goto fail; ++ ++ if (grub_file_read (file, &lh, sizeof (lh)) < (grub_ssize_t) sizeof (lh)) ++ { ++ if (!grub_errno) ++ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), ++ argv[0]); ++ goto fail; ++ } ++ ++ if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE) ++ { ++ goto fail; ++ } ++ /* linux kernel type is EFI */ ++ grub_loongarch_linux_type = GRUB_LOONGARCH_LINUX_EFI; ++ kernel_params.kernel_addr = (grub_addr_t) grub_efi_allocate_any_pages ( ++ GRUB_EFI_BYTES_TO_PAGES (kernel_params.kernel_size)); ++ grub_dprintf ("linux", "kernel numpages: %" PRIuGRUB_SIZE "\n", ++ GRUB_EFI_BYTES_TO_PAGES (kernel_params.kernel_size)); ++ if (!kernel_params.kernel_addr) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto fail; ++ } ++ ++ grub_file_seek (file, 0); ++ if (grub_file_read (file, (void*) kernel_params.kernel_addr, kernel_params.kernel_size) ++ < (grub_int64_t) kernel_params.kernel_size) ++ { ++ if (!grub_errno) ++ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]); ++ goto fail; ++ } ++ ++ grub_dprintf ("linux", "kernel @ %p\n", (void*) kernel_params.kernel_addr); + } +- linux_argv = (grub_uint64_t *) linux_args_addr; +- linux_args = (char *) (linux_argv + (linux_argc + 1 + 3)); +- +- grub_memcpy (linux_args, "a0", sizeof ("a0")); +- *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; +- linux_argv++; +- linux_args += ALIGN_UP (sizeof ("a0"), 4); + +- for (i = 1; i < argc; i++) ++ cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE) ++ + sizeof (GRUB_INITRD_STRING); ++ kernel_params.ramdisk_args_len = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); ++ kernel_params.linux_argc = argc; ++ kernel_params.linux_args = grub_malloc (cmdline_size); ++ if (!kernel_params.linux_args) + { +- grub_memcpy (linux_args, argv[i], grub_strlen (argv[i]) + 1); +- *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; +- linux_argv++; +- linux_args += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto fail; + } + +- /* Reserve space for rd arguments. */ +- rd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; +- linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); +- *linux_argv = 0; +- linux_argv++; ++ grub_memcpy (kernel_params.linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); + +- rd_size_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; +- linux_args += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); +- *linux_argv = 0; +- linux_argv++; +- +- /* Reserve space for initrd arguments. */ +- initrd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; +- linux_args += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); +- *linux_argv = 0; +- linux_argv++; ++ if (grub_linux_loongarch_elf_get_boot_params (&boot_params) == 1) ++ is_bpi_boot = 1; ++ else ++ is_bpi_boot = 0; + +- *linux_argv = 0; ++ if (is_bpi_boot == 0) ++ { ++ err = grub_create_loader_cmdline (argc, argv, ++ (char*) ((grub_addr_t) kernel_params.linux_args + sizeof (LINUX_IMAGE) - 1), ++ kernel_params.ramdisk_args_len, ++ GRUB_VERIFY_KERNEL_CMDLINE); ++ if (err) ++ goto fail; ++ } else { ++ /* save args from linux cmdline */ ++ char *p = kernel_params.linux_args; ++ ++ p += sizeof (LINUX_IMAGE) - 1; ++ for (i=0; i < argc; i++) ++ { ++ grub_memcpy (p, argv[i], grub_strlen(argv[i]) + 1); ++ p += grub_strlen(argv[i]) + 1; ++ } + } + + if (grub_errno == GRUB_ERR_NONE) +@@ -541,133 +274,81 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + loaded = 1; + } + +- initrd_loaded = 0; +- + fail: ++ if (elf != NULL) { ++ /* grub_elf_close will call grub_file_close() */ ++ grub_elf_close (elf); ++ } else { ++ if (file) ++ grub_file_close (file); ++ } ++ + if (grub_errno != GRUB_ERR_NONE) + { + grub_dl_unref (my_mod); + loaded = 0; + } + +- if (fdt_linux_args && !loaded) +- grub_free (fdt_linux_args); ++ if (kernel_params.linux_args && !loaded) ++ grub_free (kernel_params.linux_args); + +- if (linux_args_addr && !loaded) +- grub_efi_free_pages ((grub_addr_t) linux_args_addr, +- GRUB_EFI_BYTES_TO_PAGES (args_size)); ++ if (grub_loongarch_linux_type == GRUB_LOONGARCH_LINUX_EFI) { ++ if (kernel_params.kernel_addr && !loaded) ++ grub_efi_free_pages ((grub_addr_t) kernel_params.kernel_addr, ++ GRUB_EFI_BYTES_TO_PAGES (kernel_params.kernel_size)); ++ } + + return grub_errno; + } + +-#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024) +- +-/* +- * This function returns a pointer to a legally allocated initrd buffer, +- * or NULL if unsuccessful +- */ +-static void * +-allocate_initrd_mem (int initrd_pages) +-{ +- grub_addr_t max_addr; +- +- if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE) +- return NULL; +- +- max_addr += INITRD_MAX_ADDRESS_OFFSET - 1; +- +- return grub_efi_allocate_pages_real (max_addr, initrd_pages, +- GRUB_EFI_ALLOCATE_MAX_ADDRESS, +- GRUB_EFI_LOADER_DATA); +-} +- +- + static grub_err_t + grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { +- grub_size_t initrd_size, initrd_pages; +- grub_err_t err; +- void *initrd_mem = NULL; + struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 }; ++ grub_size_t initrd_size; ++ void *initrd_mem = NULL; ++ grub_err_t err; + + if (argc == 0) +- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ goto fail; ++ } + + if (!loaded) +- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); +- +- if (initrd_loaded) +- return grub_error (GRUB_ERR_BAD_ARGUMENT, "only one initrd command can be issued."); ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("you need to load the kernel first")); ++ goto fail; ++ } + + if (grub_initrd_init (argc, argv, &initrd_ctx)) + goto fail; + + initrd_size = grub_get_initrd_size (&initrd_ctx); ++ grub_dprintf ("linux", "Loading initrd\n"); + +- if (is_fdt_boot == 1) //fdt +- { +- initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size)); +- initrd_mem = allocate_initrd_mem (initrd_pages); +- if (!initrd_mem) ++ initrd_mem = grub_linux_loongarch_alloc_initrd_mem_align (initrd_size, 0x10000, &err); ++ if (err) ++ goto fail; ++ ++ if (!initrd_mem) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + goto fail; + } +- } else { +- grub_relocator_chunk_t ch; +- err = grub_relocator_alloc_chunk_align (relocator, &ch, +- 0, (0xffffffff - initrd_size) + 1, +- initrd_size, 0x10000, +- GRUB_RELOCATOR_PREFERENCE_HIGH, 0); +- +- if (err) +- return err; +- initrd_mem = get_virtual_current_address (ch); +- } + + if (grub_initrd_load (&initrd_ctx, argv, initrd_mem)) + goto fail; + +- initrd_start = (grub_addr_t) initrd_mem; +- initrd_end = initrd_start + initrd_size; +- grub_dprintf ("linux", "[addr=%p, size=0x%lx]\n", +- (void *) initrd_start, initrd_size); +- +- if (is_fdt_boot == 0) //bpi +- { +- grub_snprintf ((char *) linux_args_addr + rd_addr_arg_off, +- sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), +- "rd_start=0x%lx", +- (grub_uint64_t) initrd_mem); +- ((grub_uint64_t *) linux_args_addr)[linux_argc] +- = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_addr_arg_off); +- linux_argc++; +- +- grub_snprintf ((char *) linux_args_addr + rd_size_arg_off, +- sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%lx", +- (grub_uint64_t) initrd_size); +- ((grub_uint64_t *) linux_args_addr)[linux_argc] +- = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_size_arg_off); +- linux_argc++; +- +- grub_snprintf ((char *) linux_args_addr + initrd_addr_arg_off, +- sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), +- "initrd=0x%lx,0x%lx", +- ((grub_uint64_t) initrd_mem & GRUB_EFI_MAX_PHY_ADDRESS), +- (grub_uint64_t) initrd_size); +- ((grub_uint64_t *) linux_args_addr)[linux_argc] +- = (grub_uint64_t) ((grub_addr_t) linux_args_addr + initrd_addr_arg_off); +- linux_argc++; +- } +- +- initrd_loaded = 1; +- +- fail: ++ /* save ramdisk addr and size */ ++ kernel_params.ramdisk_addr = (grub_addr_t) initrd_mem; ++ kernel_params.ramdisk_size = initrd_size; ++ grub_dprintf ("linux", "ramdisk [addr=%p, size=0x%lx]\n", ++ (void *) initrd_mem, initrd_size); ++fail: + grub_initrd_close (&initrd_ctx); +- if (is_fdt_boot == 1) +- if (initrd_mem && !initrd_start) +- grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages); + + return grub_errno; + } +@@ -677,9 +358,9 @@ static grub_command_t cmd_linux, cmd_initrd; + GRUB_MOD_INIT(linux) + { + cmd_linux = grub_register_command ("linux", grub_cmd_linux, +- 0, N_("Load Linux.")); ++ N_("FILE [ARGS...]"), N_("Load Linux.")); + cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, +- 0, N_("Load initrd.")); ++ N_("FILE"), N_("Load initrd.")); + my_mod = mod; + } + +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index d5c805d..c34f9d1 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -374,6 +374,26 @@ + { 0xa1, 0x92, 0xbf, 0x1d, 0x57, 0xd0, 0xb1, 0x89 } \ + } + ++#define GRUB_EFI_BOOT_MEMMAP_GUID \ ++ { 0x800f683f, 0xd08b, 0x423a, \ ++ { 0xa2, 0x93, 0x96, 0x5c, 0x3c, 0x6f, 0xe2, 0xb4 } \ ++ } ++ ++#define GRUB_EFI_INITRD_MEDIA_GUID \ ++ { 0x5568e427, 0x68fc, 0x4f3d, \ ++ { 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68 } \ ++ } ++ ++#define GRUB_EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ ++ { 0x9042a9de, 0x23dc, 0x4a38, \ ++ { 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } \ ++ } ++ ++#define GRUB_EFI_CONSOLE_OUT_DEVICE_GUID \ ++ { 0xd3b36f2c, 0xd551, 0x11d4, \ ++ { 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ ++ } ++ + struct grub_efi_sal_system_table + { + grub_uint32_t signature; +diff --git a/include/grub/fdt.h b/include/grub/fdt.h +index a0710ab..2f4f270 100644 +--- a/include/grub/fdt.h ++++ b/include/grub/fdt.h +@@ -146,6 +146,6 @@ int EXPORT_FUNC(grub_fdt_set_prop) (void *fdt, unsigned int nodeoffset, const ch + grub_fdt_set_prop ((fdt), (nodeoffset), "reg", reg_64, 16); \ + }) + +-#endif /* defined(__arm__) || defined(__aarch64__) */ ++#endif /* defined(__arm__) || defined(__aarch64__) || defined(__loongarch__) */ + + #endif /* ! GRUB_FDT_HEADER */ +diff --git a/include/grub/loongarch64/asm.h b/include/grub/loongarch64/asm.h +deleted file mode 100644 +index c3e77e9..0000000 +--- a/include/grub/loongarch64/asm.h ++++ /dev/null +@@ -1,10 +0,0 @@ +-#ifndef GRUB_LOONGARCH64_ASM_HEADER +-#define GRUB_LOONGARCH64_ASM_HEADER 1 +- +-#define GRUB_ASM_T4 $a4 +-#define GRUB_ASM_T5 $a5 +-#define GRUB_ASM_SZREG 8 +-#define GRUB_ASM_REG_S st.d +-#define GRUB_ASM_REG_L ld.d +- +-#endif +diff --git a/include/grub/loongarch64/efi/loongson.h b/include/grub/loongarch64/efi/loongson.h +deleted file mode 100644 +index 7a9ccb4..0000000 +--- a/include/grub/loongarch64/efi/loongson.h ++++ /dev/null +@@ -1,113 +0,0 @@ +-/* +- * GRUB -- GRand Unified Bootloader +- * Copyright (C) 2017 Free Software Foundation, Inc. +- * +- * GRUB is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * GRUB is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with GRUB. If not, see . +- */ +- +-#ifndef GRUB_EFI_LOONGSON_HEADER +-#define GRUB_EFI_LOONGSON_HEADER 1 +- +-#include +- +-#include +- +-#define GRUB_EFI_LOONGSON_BPI_TABLE_GUID \ +- { 0x4660f721, 0x2ec5, 0x416a, \ +- { 0x89, 0x9a, 0x43, 0x18, 0x02, 0x50, 0xa0, 0xc9 } \ +- } +- +-#define GRUB_EFI_MAX_PHY_ADDRESS 0xffffffffffffULL +-#define ELF32_LOADMASK (0xf0000000UL) +-#define ELF64_LOADMASK (0xf000000000000000ULL) +-#define FLAGS_EFI_SUPPORT_BIT 0 +-#define GRUB_EFI_LOONGSON_MMAP_MAX 128 +- +-typedef enum +- { +- GRUB_EFI_LOONGSON_SYSTEM_RAM = 1, +- GRUB_EFI_LOONGSON_MEMORY_RESERVED, +- GRUB_EFI_LOONGSON_ACPI_TABLE, +- GRUB_EFI_LOONGSON_ACPI_NVS, +- GRUB_EFI_LOONGSON_MAX_MEMORY_TYPE +- } +-grub_efi_loongson_memory_type; +- +-typedef enum +- { +- GRUB_EFI_BPI_VER_NONE = 0, +- GRUB_EFI_BPI_VER_V1 = 1000, +- GRUB_EFI_BPI_VER_V2 = 1001, +- } +- grub_efi_loongson_bpi_version; +- +-grub_uint8_t +-EXPORT_FUNC(grub_efi_loongson_calculatesum8) (const grub_uint8_t *Buffer, +- grub_efi_uintn_t Length); +- +-grub_uint8_t +-EXPORT_FUNC(grub_efi_loongson_grub_calculatechecksum8) (const grub_uint8_t *Buffer, +- grub_efi_uintn_t Length); +- +-unsigned long +-EXPORT_FUNC(grub_efi_get_bpi_version) (const char *str); +- +-void * +-EXPORT_FUNC(grub_efi_loongson_get_boot_params) (void); +- +-typedef struct _extention_list_hdr { +- grub_uint64_t signature; +- grub_uint32_t length; +- grub_uint8_t revision; +- grub_uint8_t checksum; +- union { +- struct _extention_list_hdr *next; +- grub_uint64_t next_offset; +- }; +-}GRUB_PACKED +-ext_list; +- +-typedef struct boot_params_interface { +- grub_uint64_t signature; //{'B', 'P', 'I', 'x', 'x', 'x', 'x', 'x'} +- grub_efi_system_table_t *systemtable; +- union { +- ext_list *extlist; +- grub_uint64_t extlist_offset; +- }; +- grub_uint64_t flags; +-}GRUB_PACKED +-boot_params_interface; +- +-typedef struct { +- ext_list header; //{MEM} +- grub_uint8_t mapcount; +- struct GRUB_PACKED memmap_v1 { +- grub_uint32_t memtype; +- grub_uint64_t memstart; +- grub_uint64_t memsize; +- } map[GRUB_EFI_LOONGSON_MMAP_MAX]; +-}GRUB_PACKED +-mem_map_v1; +- +-typedef struct { +- ext_list header; //{VBIOS} +- grub_uint64_t vbiosaddr; +-}GRUB_PACKED +-vbios; +- +-grub_uint32_t +-EXPORT_FUNC (grub_efi_loongson_memmap_v1_sort) (struct memmap_v1 array[], +- grub_uint32_t length, mem_map_v1 * mem, +- grub_uint32_t index, grub_uint32_t memtype); +-#endif /* ! GRUB_EFI_LOONGSON_HEADER */ +diff --git a/include/grub/loongarch64/efi/memory.h b/include/grub/loongarch64/efi/memory.h +index 73641a1..16b2e0b 100644 +--- a/include/grub/loongarch64/efi/memory.h ++++ b/include/grub/loongarch64/efi/memory.h +@@ -6,7 +6,12 @@ grub_efi_max_usable_address(void) + { + grub_uint64_t addr; + asm volatile ("csrrd %0, 0x181" : "=r" (addr)); +- return addr |= 0xffffffffffUL; ++ if (addr & 0x1) ++ addr |= 0xfffffffffffUL; ++ else ++ addr = 0xfffffffffffUL; ++ ++ return addr; + } + + #endif /* ! GRUB_MEMORY_CPU_HEADER */ +diff --git a/include/grub/loongarch64/efi/time.h b/include/grub/loongarch64/efi/time.h +deleted file mode 100644 +index e69de29..0000000 +diff --git a/include/grub/loongarch64/linux.h b/include/grub/loongarch64/linux.h +index 3c6cf65..4ac3c57 100644 +--- a/include/grub/loongarch64/linux.h ++++ b/include/grub/loongarch64/linux.h +@@ -28,8 +28,7 @@ + + #define GRUB_LOONGSON3_BOOT_MEM_MAP_MAX 128 + +-#define GRUB_LINUX_LOONGARCH_MAGIC_SIGNATURE 0x4C6F6F6E67417263 /* 'LoongArc' */ +-#define GRUB_LINUX_LOONGARCH_MAGIC_SIGNATURE2 0x68 /* 'h' */ ++#define GRUB_LINUX_LOONGARCH_MAGIC_SIGNATURE 0x6E6F73676E6F6F4C /* 'Loongson' */ + #define linux_arch_kernel_header linux_loongarch64_kernel_header + + /* From linux/Documentation/loongarch/booting.txt +@@ -48,27 +47,171 @@ struct linux_loongarch64_kernel_header + grub_uint64_t res0; /* reserved */ + grub_uint64_t res1; /* reserved */ + grub_uint64_t res2; /* reserved */ +- grub_uint64_t magic; /* Magic number, little endian, "LoongArc" */ +- grub_uint32_t magic1; /* Magic number, little endian, "h" */ ++ grub_uint64_t magic; /* Magic number, little endian, "Loongson" */ + grub_uint64_t res3; /* reserved */ ++ grub_uint32_t res4; /* reserved */ + grub_uint32_t hdr_offset; /* Offset of PE/COFF header */ + }; + + struct linux_loongarch64_kernel_params + { +- grub_addr_t kernel_addr; /* kernel entry address */ +- grub_size_t kernel_size; /* kernel size */ +- grub_addr_t ramdisk_addr; /* initrd load address */ +- grub_size_t ramdisk_size; /* initrd size */ +- int linux_argc; +- grub_addr_t linux_argv; ++ grub_addr_t kernel_addr; /* kernel entry address */ ++ grub_size_t kernel_size; /* kernel size */ ++ grub_addr_t ramdisk_addr; /* initrd load address */ ++ grub_size_t ramdisk_size; /* initrd size */ ++ int ramdisk_args_len; /* position of initrd in linux_args*/ ++ int linux_argc; /* cmdline parameters number*/ ++ grub_addr_t linux_argv; /* cmdline parameters address*/ + void* linux_args; ++ void* fdt; + }; + + #include + #include + ++#define GRUB_EFI_MAX_PHY_ADDRESS 0xffffffffffffULL + #define ELF32_LOADMASK (0xf0000000UL) + #define ELF64_LOADMASK (0xf000000000000000ULL) ++#define FLAGS_EFI_SUPPORT_BIT 0 ++ ++/*initrd info*/ ++#define GRUB_RD_START_STRING "rd_start=0xXXXXXXXXXXXXXXXX" ++#define GRUB_RD_SIZE_STRING "rd_size=0xXXXXXXXXXXXXXXXX" ++#define GRUB_INITRD_STRING "initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX" ++ ++#define FDT_ADDR_CELLS_STRING "#address-cells" ++#define FDT_SIZE_CELLS_STRING "#size-cells" ++#define FDT_ADDR_SIZE_EXTRA ((2 * grub_fdt_prop_entry_size (sizeof(grub_uint32_t))) + \ ++ sizeof (FDT_ADDR_CELLS_STRING) + \ ++ sizeof (FDT_SIZE_CELLS_STRING)) ++ ++struct efi_boot_memmap { ++ grub_efi_uintn_t map_size; ++ grub_efi_uintn_t desc_size; ++ grub_efi_uint32_t desc_ver; ++ grub_efi_uintn_t map_key; ++ grub_efi_uintn_t buff_size; ++ grub_efi_memory_descriptor_t map[]; ++}; ++ ++struct efi_initrd { ++ grub_efi_uintn_t base; ++ grub_efi_uintn_t size; ++}; ++ ++/* ++ * These are set up by the setup-routine at boot-time: ++ */ ++struct screen_info { ++ grub_efi_uint8_t orig_x; /* 0x00 */ ++ grub_efi_uint8_t orig_y; /* 0x01 */ ++ grub_efi_uint16_t ext_mem_k; /* 0x02 */ ++ grub_efi_uint16_t orig_video_page; /* 0x04 */ ++ grub_efi_uint8_t orig_video_mode; /* 0x06 */ ++ grub_efi_uint8_t orig_video_cols; /* 0x07 */ ++ grub_efi_uint8_t flags; /* 0x08 */ ++ grub_efi_uint8_t unused2; /* 0x09 */ ++ grub_efi_uint16_t orig_video_ega_bx;/* 0x0a */ ++ grub_efi_uint16_t unused3; /* 0x0c */ ++ grub_efi_uint8_t orig_video_lines; /* 0x0e */ ++ grub_efi_uint8_t orig_video_isVGA; /* 0x0f */ ++ grub_efi_uint16_t orig_video_points;/* 0x10 */ ++ ++ /* VESA graphic mode -- linear frame buffer */ ++ grub_efi_uint16_t lfb_width; /* 0x12 */ ++ grub_efi_uint16_t lfb_height; /* 0x14 */ ++ grub_efi_uint16_t lfb_depth; /* 0x16 */ ++ grub_efi_uint32_t lfb_base; /* 0x18 */ ++ grub_efi_uint32_t lfb_size; /* 0x1c */ ++ grub_efi_uint16_t cl_magic, cl_offset; /* 0x20 */ ++ grub_efi_uint16_t lfb_linelength; /* 0x24 */ ++ grub_efi_uint8_t red_size; /* 0x26 */ ++ grub_efi_uint8_t red_pos; /* 0x27 */ ++ grub_efi_uint8_t green_size; /* 0x28 */ ++ grub_efi_uint8_t green_pos; /* 0x29 */ ++ grub_efi_uint8_t blue_size; /* 0x2a */ ++ grub_efi_uint8_t blue_pos; /* 0x2b */ ++ grub_efi_uint8_t rsvd_size; /* 0x2c */ ++ grub_efi_uint8_t rsvd_pos; /* 0x2d */ ++ grub_efi_uint16_t vesapm_seg; /* 0x2e */ ++ grub_efi_uint16_t vesapm_off; /* 0x30 */ ++ grub_efi_uint16_t pages; /* 0x32 */ ++ grub_efi_uint16_t vesa_attributes; /* 0x34 */ ++ grub_efi_uint32_t capabilities; /* 0x36 */ ++ grub_efi_uint32_t ext_lfb_base; /* 0x3a */ ++ grub_efi_uint8_t _reserved[2]; /* 0x3e */ ++} __attribute__((packed)); ++ ++#define GRUB_VIDEO_TYPE_EFI 0x70 ++#define GRUB_VIDEO_CAPABILITY_SKIP_QUIRKS (1 << 0) ++#define GRUB_VIDEO_CAPABILITY_64BIT_BASE (1 << 1) /* Frame buffer base is 64-bit */ ++ ++ ++/* From arch/loongarch/include/asm/mach-loongson64/boot_param.h */ ++struct _extention_list_hdr { ++ grub_uint64_t signature; ++ grub_uint32_t length; ++ grub_uint8_t revision; ++ grub_uint8_t checksum; ++ union { ++ struct _extention_list_hdr *next; ++ grub_uint64_t next_offset; ++ }; ++ ++} GRUB_PACKED; ++ ++struct boot_params_interface { ++ grub_uint64_t signature; /* {"B", "P", "I", "0", "1", ... } */ ++ grub_efi_system_table_t *systemtable; ++ union { ++ struct _extention_list_hdr *extlist; ++ grub_uint64_t extlist_offset; ++ }; ++ grub_uint64_t flags; ++}GRUB_PACKED; ++ ++struct loongsonlist_mem_map { ++ struct _extention_list_hdr header; /* {"M", "E", "M"} */ ++ grub_uint8_t map_count; ++ struct memmap { ++ grub_uint32_t mem_type; ++ grub_uint64_t mem_start; ++ grub_uint64_t mem_size; ++ } GRUB_PACKED map[GRUB_LOONGSON3_BOOT_MEM_MAP_MAX]; ++}GRUB_PACKED; ++ ++grub_err_t ++finalize_efi_params_linux (struct linux_loongarch64_kernel_params *kernel_params); ++ ++grub_err_t ++grub_linux_loongarch_elf_linux_boot_image (struct linux_loongarch64_kernel_params ++ *kernel_params); ++ ++void* ++grub_linux_loongarch_alloc_virtual_mem_addr (grub_addr_t addr, ++ grub_size_t size, ++ grub_err_t *err); ++ ++void* ++grub_linux_loongarch_alloc_virtual_mem_align (grub_size_t size, ++ grub_size_t align, ++ grub_err_t *err); ++ ++void* ++grub_linux_loongarch_alloc_initrd_mem_align (grub_size_t size, ++ grub_size_t align, ++ grub_err_t *err); ++ ++void ++grub_linux_loongarch_elf_relocator_unload (void); ++ ++int ++grub_linux_loongarch_elf_get_boot_params (struct boot_params_interface **boot_params); ++ ++grub_err_t ++grub_linux_loongarch_elf_boot_params (struct boot_params_interface *boot_params); ++ ++grub_err_t ++grub_linux_loongarch_elf_load_kernel (grub_elf_t elf, const char *filename); + + #endif /* ! GRUB_LOONGARCH64_LINUX_HEADER */ +diff --git a/include/grub/loongarch64/time.h b/include/grub/loongarch64/time.h +index c9a7334..0a10fbd 100644 +--- a/include/grub/loongarch64/time.h ++++ b/include/grub/loongarch64/time.h +@@ -19,18 +19,6 @@ + #ifndef KERNEL_CPU_TIME_HEADER + #define KERNEL_CPU_TIME_HEADER 1 + +-#ifndef GRUB_UTIL +- +-#define GRUB_TICKS_PER_SECOND (grub_arch_cpuclock / 2) +- +-void grub_timer_init (grub_uint32_t cpuclock); +- +-/* Return the real time in ticks. */ +-grub_uint64_t grub_get_rtc (void); +- +-extern grub_uint32_t grub_arch_cpuclock; +-#endif +- + static inline void + grub_cpu_idle(void) + { +-- +2.43.5 + diff --git a/grub.patches b/grub.patches index e150afe..db20fac 100644 --- a/grub.patches +++ b/grub.patches @@ -681,3 +681,4 @@ Patch1002: 1002-Add-LoongArch64-support-and-update-interface-to-v40.patch Patch1003: 1003-cryptodisk-make-the-password-getter-and-additional-a.patch Patch1004: 1004-cryptodisk-add-OS-provided-secret-support.patch Patch1005: 1005-efi-Add-API-for-retrieving-the-EFI-secret-for-crypto.patch +Patch1006: 1006-Update-patches-in-sync-with-loongarch64.patch diff --git a/grub2.spec b/grub2.spec index 6a2034d..e09510a 100644 --- a/grub2.spec +++ b/grub2.spec @@ -545,6 +545,7 @@ fi - LoongArch64 support fdt and phy-addr BIOS(yangqiming@loongson.cn) - Remove dtb dir with correct argument (Liwei Ge) - Support use confidential computing provisioned secrets for disk decryption(hanliyang@hygon.cn) +- Update for loongarch64 in sync with latest v2.04(liuxue@loongson.cn) * Thu Apr 17 2025 Nicolas Frayer - 2.02-165 - fs/ext2: Rework of OOB read patch -- Gitee